def test_new_game(self): start = GameState.new_game(19) next_state = start.apply_move(Move.play(Point(16, 16))) self.assertEqual(start, next_state.previous_state) self.assertEqual(Player.white, next_state.next_player) self.assertEqual(Player.black, next_state.board.get(Point(16, 16)))
def remove_dead_stones_and_score(game_state): b_resign = False w_resign = False if game_state.last_move.is_resign: if game_state.next_player == Player.black: w_resign = True else: b_resign = True if b_resign or w_resign: return GameResult( b_resign, w_resign, 0.0, 0.0, game_state.komi(), game_state.board) end_game = game_state while end_game.last_move == Move.pass_turn(): end_game = end_game.previous_state final_board = remove_dead_stones(end_game) final_state = GameState.from_board( final_board, game_state.next_player, game_state.komi()) final_state = final_state.apply_move(Move.pass_turn()) final_state = final_state.apply_move(Move.pass_turn()) return compute_game_result(final_state)
def test_ko(self): start = GameState.new_game(19) # .wb. # wb.b # .wb. # .... game = start.apply_move(Move.play(Point(1, 3))) game = game.apply_move(Move.play(Point(1, 2))) game = game.apply_move(Move.play(Point(2, 2))) game = game.apply_move(Move.play(Point(2, 1))) game = game.apply_move(Move.play(Point(3, 3))) game = game.apply_move(Move.play(Point(3, 2))) game = game.apply_move(Move.play(Point(2, 4))) # W takes the ko game = game.apply_move(Move.play(Point(2, 3))) # B can't take back self.assertTrue(game.does_move_violate_ko(Move.play(Point(2, 2)))) self.assertFalse(game.is_valid_move(Move.play(Point(2, 2)))) # "ko threat" game = game.apply_move(Move.play(Point(19, 19))) game = game.apply_move(Move.play(Point(18, 18))) # B can take now self.assertFalse(game.does_move_violate_ko(Move.play(Point(2, 2)))) self.assertTrue(game.is_valid_move(Move.play(Point(2, 2))))
def test_create_game_from_board(self): board = Board(5, 5) board.place_stone(Player.black, Point(2, 2)) board.place_stone(Player.black, Point(4, 4)) game = GameState.from_board(board, Player.white) self.assertEqual(Player.white, game.next_player) self.assertFalse(game.is_valid_move(Move.play(Point(2, 2)))) self.assertTrue(game.is_valid_move(Move.play(Point(3, 3))))
def read_game_state(self): board = self.read_board() next_player = self.read_player() komi = self.read_float() game = GameState.from_board(board, next_player, komi) move = self.read_optional(self.read_move) while move is not None: game = game.apply_move(move) move = self.read_optional(self.read_move) return game
def test_large_dead_dragon(self): orig_board = board_from_string(''' oxx...xoo...oox.... ooxx..xxo.o.oxx..x. .oox..xoooxxooxx..x ..oxxxxxxxoooooxxxo .oxxo.x.x.xo.xooxoo ..oooxxooxxoxxxooo. ..oxxoooxx.x...xo.. .oxxxo.xox.xxxxxoo. .ox.xxo.oxxooxoox.. ..oxxooooxxo.o.oo.. ..oxxxoxxxo...o.xo. ..oxxoooxo.o.oxxxo. .oxxooooxooxoo.xooo ..oxxoxxoo.xxxxxxo. ..oxxoxxo.oxx..xo.. ..ooxxxooo.oox.xoo. ....oxxxoo..ox.xo.. ..o.ox.xxo..ooxxxoo ...oxxooxo..oxxxxxo ''') # White has a large dragon that is dead (black stone on the # nakade point) expected_board = board_from_string(''' oxx...xoo...oox.... ooxx..xxo.o.oxx..x. .oox..xooo..ooxx..x ..oxxxxxxxoooooxxxo .oxxo.x.x.xo.xooxoo ..oooxx..xxoxxxooo. ..oxx...xx.x...xo.. .oxxx..x.x.xxxxxoo. .ox.xx...xxooxoo... ..oxx....xxo.o.oo.. ..oxxx.xxxo...o.xo. ..oxx...xo.o.oxxxo. .oxx....xooxoo.xooo ..oxx.xxoo.xxxxxxo. ..oxx.xxo.oxx..xo.. ..ooxxxooo.oox.xoo. ....oxxxoo..ox.xo.. ..o.ox.xxo..ooxxxoo ...oxx..xo..oxxxxxo ''') game = GameState.from_board(orig_board, Player.white, komi=7.5) final_board = remove_dead_stones(game) self.assertEqual(final_board, expected_board)
def read_game_from_sgf(sgffile): tree = sgf_grammar.parse(sgffile.read()) visitor = SGFVisitor() sequence = visitor.visit(tree) root, moves = sequence[0], sequence[1:] board_size = int(get_prop(root, 'SZ')) try: komi = float(get_prop(root, 'KM')) except KeyError: # We don't truly support zero komi, pretend it's half point # komi. komi = 0.5 result = get_prop(root, 'RE') if result.startswith('B+'): winner = Player.black elif result.startswith('W+'): winner = Player.white else: raise ValueError(result) handicap = int(get_prop(root, 'HA', 0)) board = Board(board_size, board_size) first_player = Player.black if handicap > 0: handicap_stones = get_props(root, 'AB') for sgf_move in handicap_stones: move = decode_sgf_move(sgf_move, board_size) board.place_stone(Player.black, move.point) first_player = Player.white initial_state = GameState.from_board(board, first_player, komi) state = initial_state decoded_moves = [] for node in moves: key = 'B' if state.next_player == Player.black else 'W' sgf_move = get_prop(node, key) move = decode_sgf_move(sgf_move, board_size) decoded_moves.append(move) state = state.apply_move(move) return GameRecord(initial_state=initial_state, moves=decoded_moves, winner=winner)
def test_easy_scoring(self): # Both B and W have an unconditionally alive group. One # unconditionally dead W stone. orig_board = board_from_string(''' ..xo. xxxo. .oxo. xxxoo ..xo. ''') final_board = board_from_string(''' ..xo. xxxo. ..xo. xxxoo ..xo. ''') game = GameState.from_board(orig_board, Player.white, komi=7.5) board = remove_dead_stones(game) self.assertEqual(final_board, board)
def test_ko_as_array(self): start = GameState.new_game(19) # .wb. # wb.b # .wb. # .... game = start.apply_move(Move.play(Point(1, 3))) game = game.apply_move(Move.play(Point(1, 2))) game = game.apply_move(Move.play(Point(2, 2))) game = game.apply_move(Move.play(Point(2, 1))) game = game.apply_move(Move.play(Point(3, 3))) game = game.apply_move(Move.play(Point(3, 2))) game = game.apply_move(Move.play(Point(2, 4))) # W takes the ko game = game.apply_move(Move.play(Point(2, 3))) ko_array = game.ko_points_as_array() self.assertEqual((19, 19), ko_array.shape) self.assertEqual(1, ko_array[1, 1]) self.assertEqual(0, ko_array[2, 1]) self.assertEqual(0, ko_array[5, 5])
def test_legal_move_mask(self): start = GameState.new_game(19) # .wb. # wb.b # .wb. # .... game = start.apply_move(Move.play(Point(1, 3))) game = game.apply_move(Move.play(Point(1, 2))) game = game.apply_move(Move.play(Point(2, 2))) game = game.apply_move(Move.play(Point(2, 1))) game = game.apply_move(Move.play(Point(3, 3))) game = game.apply_move(Move.play(Point(3, 2))) game = game.apply_move(Move.play(Point(2, 4))) # W takes the ko game = game.apply_move(Move.play(Point(2, 3))) legal_moves = game.legal_moves_as_array() self.assertEqual((19 * 19 + 1, ), legal_moves.shape) illegal_indices = [ # Suicide 19 * 0 + 0, # Stones here 19 * 0 + 2, 19 * 0 + 1, 19 * 1 + 0, 19 * 2 + 2, 19 * 2 + 1, 19 * 1 + 3, 19 * 1 + 2, # ko 19 * 1 + 1, ] for i, val in enumerate(legal_moves): if i in illegal_indices: self.assertEqual(0, val, "{} should be illegal".format(i)) else: self.assertEqual(1, val, "{} should be legal".format(i))
def test_komi(self): start = GameState.new_game(19, 0.5) next_state = start.apply_move(Move.play(Point(16, 16))) self.assertAlmostEqual(0.5, next_state.komi())
def test_last_move_is_none(self): start = GameState.new_game(19) self.assertIsNone(start.last_move)
def test_last_move(self): start = GameState.new_game(19) next_move = Move.play(Point(16, 16)) state = start.apply_move(next_move) self.assertEqual(Move.play(Point(16, 16)), state.last_move)
def test_move_number(self): start = GameState.new_game(19) self.assertEqual(0, start.num_moves) game = start.apply_move(Move.play(Point(1, 3))) game = game.apply_move(Move.play(Point(1, 2))) self.assertEqual(2, game.num_moves)
def test_is_valid_move(self): start = GameState.new_game(19) state = start.apply_move(Move.play(Point(16, 16))) self.assertTrue(state.is_valid_move(Move.play(Point(16, 17)))) self.assertFalse(state.is_valid_move(Move.play(Point(16, 16))))