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
