The game flow works like this:
During config phase, the clients can send game.move_root_square
and game.move_null_square. The referee will respond with
game.set_root_square and game.set_null_square
for valid moves.
When the game begins, the referee will immediately send
game.turn("white"). The White client should now accept
the player's move, and send game.move. If this is valid,
the referee will send game.move, possibly followed
by game.bonus. The referee will then send
game.turn("black"), and the cycle will continue.
(All ref-to-client RPCs are broadcast simultaneously to all players and observers. This game has no hidden information.)
white
black
game.move_root_square(x, y)
-- Move the root token.
(Config phase only.)
game.move_null_square(x, y)
-- Move the null token.
(Config phase only.)
game.move(x, y, size, dir)
-- Make a move.
game.set_root_square(player, x, y)
-- The root token has been moved by the given player.
(Config phase only.)
game.set_null_square(player, x, y)
-- The null token has been moved by the given player.
(Config phase only.)
game.turn(seat)
-- It is now the given seat's turn.
(This is sent after game-unsuspend, even if it was sent for the current turn
before the game was suspended.)
game.move(seat, x, y, size, dir)
-- The given seat has made a move.
game.bonus(seat, bonus, x, y, dir)
-- The given seat gains bonus points,
because of the opponent's move at x, y, dir.
The bonus will be between 2 and 6.
game.out_of_bounds
-- "That location is off the board."
game.root_null_overlap
-- "The root square and the null square cannot occupy the same space."
game.invalid_direction
-- "The "direction" field is invalid."
game.invalid_size
-- "The "size" field is invalid."
game.out_of_pieces
-- "You have no more pieces of that size to play."
game.square_occupied
-- "That square is already occupied."
game.no_target
-- "Your piece must point at another piece or the root."
game.null_target
-- "No piece may point at the null square."