Game Tree Navigation

Playing Stones

The sente.game object records all of the moves played in a tree structure. Sente provides utilities for navigating around this tree with the game.play(), game.step_up() and game.get_branches() methods.

The game.play() method plays at a given point on the board.

>>> import sente
>>> game = sente.Game(9) # creates a 9x9 board
>>> game.play(4, 4) # plays a stone on the 4-4 point
>>> print(game)
 1  .  .  .  .  .  .  .  .  .
 2  .  .  .  .  .  .  .  .  .
 3  .  .  *  .  .  .  *  .  .
 4  .  .  .  ⚫ .  .  .  .  .
 5  .  .  .  .  *  .  .  .  .
 6  .  .  .  .  .  .  .  .  .
 7  .  .  *  .  .  .  *  .  .
 8  .  .  .  .  .  .  .  .  .
 9  .  .  .  .  .  .  .  .  .
    A  B  C  D  E  F  G  H  J

Undoing Moves

The game.step_up() method on the other hand, undoes the previous move played on the board.

>>> import sente
>>> game = sente.Game()
>>> game.play(4, 4)
>>> game.step_up() # undo the previous move
>>> print(game)
 1  .  .  .  .  .  .  .  .  .
 2  .  .  .  .  .  .  .  .  .
 3  .  .  *  .  .  .  *  .  .
 4  .  .  .  .  .  .  .  .  .
 5  .  .  .  .  *  .  .  .  .
 6  .  .  .  .  .  .  .  .  .
 7  .  .  *  .  .  .  *  .  .
 8  .  .  .  .  .  .  .  .  .
 9  .  .  .  .  .  .  .  .  .
    A  B  C  D  E  F  G  H  J

Repeatedly calling step_up() can be tedious and slow, so the number of steps that step_up() takes can be specified as an argument.

>>> import sente
>>> game = sente.Game()
>>> game.play(4, 4)
>>> game.play(7, 7)
>>> game.play(7, 4)
>>> game.step_up(2) # undo two moves
>>> print(game)
 1  .  .  .  .  .  .  .  .  .
 2  .  .  .  .  .  .  .  .  .
 3  .  .  *  .  .  .  *  .  .
 4  .  .  .  ⚫ .  .  .  .  .
 5  .  .  .  .  *  .  .  .  .
 6  .  .  .  .  .  .  .  .  .
 7  .  .  *  .  .  .  *  .  .
 8  .  .  .  .  .  .  .  .  .
 9  .  .  .  .  .  .  .  .  .
    A  B  C  D  E  F  G  H  J

Another alternative to the step_up() method is the advance_to_root() method which simply undoes every move in the game leaving the board empty.

>>> import sente
>>> game = sente.Game()
>>> game.play(4, 4)
>>> game.play(7, 7)
>>> game.play(7, 4)
>>> game.advance_to_root()
>>> print(game)
 1  .  .  .  .  .  .  .  .  .
 2  .  .  .  .  .  .  .  .  .
 3  .  .  *  .  .  .  *  .  .
 4  .  .  .  .  .  .  .  .  .
 5  .  .  .  .  *  .  .  .  .
 6  .  .  .  .  .  .  .  .  .
 7  .  .  *  .  .  .  *  .  .
 8  .  .  .  .  .  .  .  .  .
 9  .  .  .  .  .  .  .  .  .
    A  B  C  D  E  F  G  H  J

Once moves have been undone, the move(s) played at a given node of the tree can be obtained using the get_branches() method.

>>> import sente
>>> game = sente.Game(9)
>>> game.play(4, 4)
>>> game.play(7, 7)
>>> game.step_up()
>>> print(game.get_branches())
[<sente.Move W[gg]>]

The sente.Move object is an object that can be passed to the game.play() method to play the specified move. The get_branches() method returns a python list containing all of the moves that were played at the current node of the tree.

>>> import sente
>>> game = sente.Game(9)
>>> game.play(4, 4)
>>> game.play(7, 7)
>>> game.step_up()
>>> branches = game.get_branches()
>>> game.play(branches[0])
>>> print(game)
 1  .  .  .  .  .  .  .  .  .
 2  .  .  .  .  .  .  .  .  .
 3  .  .  *  .  .  .  *  .  .
 4  .  .  .  ⚫ .  .  .  .  .
 5  .  .  .  .  *  .  .  .  .
 6  .  .  .  .  .  .  .  .  .
 7  .  .  *  .  .  .  ⚪ .  .
 8  .  .  .  .  .  .  .  .  .
 9  .  .  .  .  .  .  .  .  .
    A  B  C  D  E  F  G  H  J

If multiple branches exist from the current node, then get_branches() will return a list containing all of them.

Move Sequences

When undoing moves in sente it can be tricky to keep track of the sequence of moves that leads to a given board position. To make game tree navigation easier, the sente.Game Object contains a method called get_sequence that generates a python list containing the sequence of moves that have been played in the game so far.

>>> game.play(4, 4)
>>> game.play(15, 4)
>>> game.play(15, 15)
>>> print(game.get_sequence())
[<sente.Move B[dd]>, <sente.Move W[od]>, <sente.Move B[oo]>]

If the moves in a sequence are undone, the board position can be restored by using the play_sequence() method.

>>> print(game)
 1  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 2  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 3  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 4  .  .  .  ⚫ .  .  .  .  .  *  .  .  .  .  .  *  .  .  .
 5  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 6  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 7  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 8  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 9  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
10  .  .  .  *  .  .  .  .  .  *  .  .  .  .  .  *  .  .  .
11  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
12  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
13  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
14  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
15  .  .  .  ⚪ .  .  .  .  .  .  .  .  .  .  ⚫ .  .  .  .
16  .  .  .  *  .  .  .  .  .  *  .  .  .  .  .  *  .  .  .
17  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
18  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
19  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
    A  B  C  D  E  F  G  H  J  K  L  M  N  O  P  Q  R  S  T
>>> move_sequence = game.get_sequence()
>>> game.step_up(3) # alternatively, you could use the advance_to_root() method
>>> game.play_sequence(move_sequence)
>>> print(game)
 1  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 2  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 3  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 4  .  .  .  ⚫ .  .  .  .  .  *  .  .  .  .  .  *  .  .  .
 5  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 6  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 7  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 8  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 9  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
10  .  .  .  *  .  .  .  .  .  *  .  .  .  .  .  *  .  .  .
11  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
12  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
13  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
14  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
15  .  .  .  ⚪ .  .  .  .  .  .  .  .  .  .  ⚫ .  .  .  .
16  .  .  .  *  .  .  .  .  .  *  .  .  .  .  .  *  .  .  .
17  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
18  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
19  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
    A  B  C  D  E  F  G  H  J  K  L  M  N  O  P  Q  R  S  T

Additionally, because the get_sequence method returns a python list, python list slicing is supported.