Abapa Rules =========== :abstract: This part describe the rules implemented by our game; And additionally, explain how to use the python ``awale`` module. Our **pyAwale** game is an implementation of the *Abapa Rules* (from the `Oware Society`_) as descibed bolow. .. _Oware Society: http://www.oware.org/ Board ----- The Awalé consists of a tray dug by 2 rows of 6 pits or cavities called *houses* (also named holes or cups); the one will be the South camp (player), the other one the North camp (computer). Two extra houses used for storing captured seeds are placed at either side of the board in-between the two rows. In the beginning of the game, each house receives four seeds:: >>> from awale import * >>> awale = Awale() >>> awale {'board': [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], 'score': [0, 0]} Goal ---- The goal of the game is to capture more seeds than one's opponent (he places them then in its reserve). The game -------- Maneuver ~~~~~~~~ At each move the player takes the content of one of the houses not empty of his own camp and sow the seeds one by one in the next cups, counter-clockwise. Sow "D":: >>> awale.sow_and_capture(3) >>> print awale f e d c b a North ( 0) [ 4] [ 4] [ 4] [ 4] [ 5] [ 5] [ 4] [ 4] [ 4] [ 0] [ 5] [ 5] ( 0) South A B C D E F Knowing the number of seeds in each house is, of course, important to gameplay. When there are many seeds in a house, sometimes enough to make a full lap of the board or more, they cannot easily be counted by eye, and their number is often guarded by the player who controls that house. This may be done by repeatedly moving the seeds in the house. A player may count the seeds when contemplating a move; in such cases the last few are usually counted in the hand to avoid revealing their number. Omitting a house ~~~~~~~~~~~~~~~~ In the course of a seedling, you have never to give seed in the square of departure. Sow "E":: >>> awale.board = [3, 1, 0, 0, 14, 2, 3, 3, 3, 5, 3, 3] >>> awale {'board': [3, 1, 0, 0, 14, 2, 3, 3, 3, 5, 3, 3], 'score': [0, 0]} >>> awale.sow_and_capture(4) >>> print awale f e d c b a North ( 0) [ 4] [ 4] [ 6] [ 4] [ 5] [ 5] [ 4] [ 2] [ 1] [ 1] [ 0] [ 4] ( 0) South A B C D E F Capturing seeds ~~~~~~~~~~~~~~~ If the last sown seed falls in an adverse square containing 1 or 2 seeds, the player captures the content of this square (including the last seed that it comes to sow). It takes equally the content of preceding adverse squares if the former contain then 2 or 3 seeds. These squares allowing supplementary plugs have to form a uninterrupted chain. All plugs are definitive; they constitute the gain of the player. Sow "D"; Capture "d" and "c":: >>> awale.board = [0, 3, 0, 6, 1, 2, 0, 0, 2, 1, 0, 3] >>> awale {'board': [0, 3, 0, 6, 1, 2, 0, 0, 2, 1, 0, 3], 'score': [0, 0]} >>> awale.sow_and_capture(3) >>> print awale f e d c b a North ( 0) [ 3] [ 0] [ 0] [ 0] [ 1] [ 1] [ 0] [ 3] [ 0] [ 0] [ 2] [ 3] ( 5) South A B C D E F However, if a move would capture all an opponent's seeds, the capture is forfeited, and the seeds are instead left on the board, since this would prevent the opponent from continuing the game (the adversary should not be starved):: >>> awale.board = [1, 2, 3, 4, 5, 6, 1, 1, 1, 2, 2, 1] >>> awale.score = [0, 0] >>> awale {'board': [1, 2, 3, 4, 5, 6, 1, 1, 1, 2, 2, 1], 'score': [0, 0]} >>> awale.sow_and_capture(5) >>> print awale f e d c b a North ( 0) [ 2] [ 3] [ 3] [ 2] [ 2] [ 2] [ 1] [ 2] [ 3] [ 4] [ 5] [ 0] ( 0) South A B C D E F Let the opponent play ~~~~~~~~~~~~~~~~~~~~~ The proscription against capturing all an opponent's seeds is related to a more general idea, that one ought to make a move that allows the opponent to continue playing. If an opponent's houses are all empty, the current player must make a move that gives the opponent seeds ("to feed him"):: >>> awale.board = [0, 0, 0, 0, 0, 0, 5, 1, 1, 2, 2, 1] >>> awale.score = [0, 0] >>> awale {'board': [0, 0, 0, 0, 0, 0, 5, 1, 1, 2, 2, 1], 'score': [0, 0]} >>> awale.best_sown(1) 10 >>> awale.sow_and_capture(10) >>> print awale f e d c b a North ( 0) [ 2] [ 0] [ 2] [ 1] [ 1] [ 5] [ 1] [ 0] [ 0] [ 0] [ 0] [ 0] ( 0) South A B C D E F The player that infringes this prescription, in gathering all seeds on its side, depriving thus its partner the possibility to play, is punished: its adversary gathers then to its profit all resting seeds. If no such move is possible, the current player captures all seeds in his/her own territory, ending the game:: >>> awale.board = [0, 0, 0, 0, 0, 0, 1, 3, 1, 0, 1, 0] >>> awale.score = [23, 23] >>> awale {'board': [0, 0, 0, 0, 0, 0, 1, 3, 1, 0, 1, 0], 'score': [23, 23]} >>> awale.best_sown(1) Traceback (most recent call last): ... NoMoreMove: No move available! >>> print awale f e d c b a North (23) [ 0] [ 1] [ 0] [ 1] [ 3] [ 1] [ 0] [ 0] [ 0] [ 0] [ 0] [ 0] (23) South A B C D E F End of game ~~~~~~~~~~~ Since the game has only 48 seeds, capturing 25 is sufficient to accomplish this:: >>> awale.board = [1, 1, 3, 3, 1, 1, 0, 5, 0, 3, 3, 0] >>> awale.score = [4, 23] >>> awale {'board': [1, 1, 3, 3, 1, 1, 0, 5, 0, 3, 3, 0], 'score': [4, 23]} >>> awale.best_sown(1) 7 >>> awale.sow_and_capture(7) Traceback (most recent call last): ... EndOfGame: North player wins! >>> print awale f e d c b a North (25) [ 1] [ 4] [ 4] [ 1] [ 0] [ 0] [ 0] [ 1] [ 3] [ 3] [ 1] [ 1] ( 4) South A B C D E F Rk: Since there are an even number of seeds, it is possible for the game to end in a draw. The end of game is also reached if less than 6 seeds left on board:: >>> awale.board = [0, 1, 0, 0, 3, 0, 0, 1, 0, 1, 0, 0] >>> awale.score = [22, 18] >>> awale {'board': [0, 1, 0, 0, 3, 0, 0, 1, 0, 1, 0, 0], 'score': [22, 18]} >>> awale.sow_and_capture(4) Traceback (most recent call last): ... EndOfGame: No enough seeds! >>> print awale f e d c b a North (18) [ 0] [ 0] [ 1] [ 0] [ 0] [ 1] [ 0] [ 1] [ 0] [ 0] [ 0] [ 1] (24) South A B C D E F