def test_move_with_capture(self): start_board = test_utils.load_board(EMPTY_ROW * 5 + ''' XXXX..... XOOX..... O.OX..... OOXX..... ''') start_position = Position( board=start_board, n=0, komi=6.5, caps=(1, 2), ko=None, recent=tuple(), to_play=BLACK, ) expected_board = test_utils.load_board(EMPTY_ROW * 5 + ''' XXXX..... X..X..... .X.X..... ..XX..... ''') expected_position = Position( board=expected_board, n=1, komi=6.5, caps=(7, 2), ko=None, recent=(PlayerMove(BLACK, coords.from_kgs('B2')),), to_play=WHITE, ) actual_position = start_position.play_move(coords.from_kgs('B2')) self.assertEqualPositions(actual_position, expected_position)
def test_capture_multiple_groups(self): board = test_utils.load_board(''' .OX...... OXX...... XX....... ''' + EMPTY_ROW * 6) lib_tracker = LibertyTracker.from_board(board) captured = lib_tracker.add_stone(BLACK, coords.from_kgs('A9')) self.assertEqual(len(lib_tracker.groups), 2) self.assertEqual(captured, coords_from_kgs_set('B9 A8')) corner_stone = lib_tracker.groups[lib_tracker.group_index[coords.from_kgs( 'A9')]] self.assertEqual(corner_stone.stones, coords_from_kgs_set('A9')) self.assertEqual(corner_stone.liberties, coords_from_kgs_set('B9 A8')) surrounding_stones = lib_tracker.groups[lib_tracker.group_index[coords.from_kgs( 'C9')]] self.assertEqual(surrounding_stones.stones, coords_from_kgs_set('C9 B8 C8 A7 B7')) self.assertEqual(surrounding_stones.liberties, coords_from_kgs_set('B9 D9 A8 D8 C7 A6 B6')) liberty_cache = lib_tracker.liberty_cache for stone in corner_stone.stones: self.assertEqual(liberty_cache[stone], 2, str(stone)) for stone in surrounding_stones.stones: self.assertEqual(liberty_cache[stone], 7, str(stone))
def test_parsing_9x9(self): self.assertEqual(coords.from_sgf('aa'), (0, 0)) self.assertEqual(coords.from_sgf('ac'), (2, 0)) self.assertEqual(coords.from_sgf('ca'), (0, 2)) self.assertEqual(coords.from_sgf(''), None) self.assertEqual(coords.to_sgf(None), '') self.assertEqual( 'aa', coords.to_sgf(coords.from_sgf('aa'))) self.assertEqual( 'sa', coords.to_sgf(coords.from_sgf('sa'))) self.assertEqual( (1, 17), coords.from_sgf(coords.to_sgf((1, 17)))) self.assertEqual(coords.from_kgs('A1'), (8, 0)) self.assertEqual(coords.from_kgs('A9'), (0, 0)) self.assertEqual(coords.from_kgs('C2'), (7, 2)) self.assertEqual(coords.from_kgs('J2'), (7, 8)) self.assertEqual(coords.from_pygtp((1, 1)), (8, 0)) self.assertEqual(coords.from_pygtp((1, 9)), (0, 0)) self.assertEqual(coords.from_pygtp((3, 2)), (7, 2)) self.assertEqual(coords.to_pygtp((8, 0)), (1, 1)) self.assertEqual(coords.to_pygtp((0, 0)), (1, 9)) self.assertEqual(coords.to_pygtp((7, 2)), (3, 2)) self.assertEqual(coords.to_kgs((0, 8)), 'J9') self.assertEqual(coords.to_kgs((8, 0)), 'A1')
def test_neighbors(self): corner = coords.from_kgs('A1') neighbors = [go.EMPTY_BOARD[c] for c in go.NEIGHBORS[corner]] self.assertEqual(len(neighbors), 2) side = coords.from_kgs('A2') side_neighbors = [go.EMPTY_BOARD[c] for c in go.NEIGHBORS[side]] self.assertEqual(len(side_neighbors), 3)
def test_chinese_handicap_handling(self): intermediate_board = utils_test.load_board(''' ......... ......... ......X.. ......... ......... ......... ......... ......... ......... ''') intermediate_position = go.Position( utils_test.BOARD_SIZE, intermediate_board, n=1, komi=5.5, caps=(0, 0), recent=(go.PlayerMove(go.BLACK, coords.from_kgs( utils_test.BOARD_SIZE, 'G7')),), to_play=go.BLACK, ) final_board = utils_test.load_board(''' ....OX... .O.OOX... O.O.X.X.. .OXXX.... OX...XX.. .X.XXO... X.XOOXXX. XXXO.OOX. .XOOX.O.. ''') final_position = go.Position( utils_test.BOARD_SIZE, final_board, n=50, komi=5.5, caps=(7, 2), ko=None, recent=( go.PlayerMove( go.WHITE, coords.from_kgs(utils_test.BOARD_SIZE, 'E9')), go.PlayerMove( go.BLACK, coords.from_kgs(utils_test.BOARD_SIZE, 'F9')),), to_play=go.WHITE ) positions_w_context = list(replay_sgf( utils_test.BOARD_SIZE, CHINESE_HANDICAP_SGF)) self.assertEqualPositions( intermediate_position, positions_w_context[1].position) self.assertEqual( positions_w_context[1].next_move, coords.from_kgs( utils_test.BOARD_SIZE, 'C3')) final_replayed_position = positions_w_context[-1].position.play_move( positions_w_context[-1].next_move) self.assertEqualPositions(final_position, final_replayed_position)
def test_japanese_handicap_handling(self): intermediate_board = utils_test.load_board(''' ......... ......... ......X.. ......... ....O.... ......... ..X...... ......... ......... ''') intermediate_position = go.Position( utils_test.BOARD_SIZE, intermediate_board, n=1, komi=5.5, caps=(0, 0), recent=(go.PlayerMove(go.WHITE, coords.from_kgs( utils_test.BOARD_SIZE, 'E5')),), to_play=go.BLACK, ) final_board = utils_test.load_board(''' ......... ......... ......X.. ......... ....O.... ......... ..XX..... ......... ......... ''') final_position = go.Position( utils_test.BOARD_SIZE, final_board, n=2, komi=5.5, caps=(0, 0), recent=( go.PlayerMove(go.WHITE, coords.from_kgs( utils_test.BOARD_SIZE, 'E5')), go.PlayerMove(go.BLACK, coords.from_kgs( utils_test.BOARD_SIZE, 'D3')),), to_play=go.WHITE, ) positions_w_context = list(replay_sgf( utils_test.BOARD_SIZE, JAPANESE_HANDICAP_SGF)) self.assertEqualPositions( intermediate_position, positions_w_context[1].position) final_replayed_position = positions_w_context[-1].position.play_move( positions_w_context[-1].next_move) self.assertEqualPositions(final_position, final_replayed_position)
def test_capture_stone(self): board = test_utils.load_board(''' .X....... XO....... .X....... ''' + EMPTY_ROW * 6) lib_tracker = LibertyTracker.from_board(board) captured = lib_tracker.add_stone(BLACK, coords.from_kgs('C8')) self.assertEqual(len(lib_tracker.groups), 4) self.assertEqual( lib_tracker.group_index[coords.from_kgs('B8')], go.MISSING_GROUP_ID) self.assertEqual(captured, coords_from_kgs_set('B8'))
def test_lib_tracker_init(self): board = test_utils.load_board('X........' + EMPTY_ROW * 8) lib_tracker = LibertyTracker.from_board(board) self.assertEqual(len(lib_tracker.groups), 1) self.assertNotEqual( lib_tracker.group_index[coords.from_kgs('A9')], go.MISSING_GROUP_ID) self.assertEqual(lib_tracker.liberty_cache[coords.from_kgs('A9')], 2) sole_group = lib_tracker.groups[lib_tracker.group_index[coords.from_kgs( 'A9')]] self.assertEqual(sole_group.stones, coords_from_kgs_set('A9')) self.assertEqual(sole_group.liberties, coords_from_kgs_set('B9 A8')) self.assertEqual(sole_group.color, BLACK)
def test_same_friendly_group_neighboring_twice(self): board = test_utils.load_board(''' XX....... X........ ''' + EMPTY_ROW * 7) lib_tracker = LibertyTracker.from_board(board) captured = lib_tracker.add_stone(BLACK, coords.from_kgs('B8')) self.assertEqual(len(lib_tracker.groups), 1) sole_group_id = lib_tracker.group_index[coords.from_kgs('A9')] sole_group = lib_tracker.groups[sole_group_id] self.assertEqual(sole_group.stones, coords_from_kgs_set('A9 B9 A8 B8')) self.assertEqual(sole_group.liberties, coords_from_kgs_set('C9 C8 A7 B7')) self.assertEqual(captured, set())
def test_parallel_tree_search(self): player = initialize_almost_done_player() # check -- white is losing. self.assertEqual(player.root.position.score(), -0.5) # initialize the tree so that the root node has populated children. player.tree_search(num_parallel=1) # virtual losses should enable multiple searches to happen simultaneously # without throwing an error... for i in range(5): player.tree_search(num_parallel=4) # uncomment to debug this test # print(player.root.describe()) # Search should converge on D9 as only winning move. flattened = coords.to_flat(utils_test.BOARD_SIZE, coords.from_kgs( utils_test.BOARD_SIZE, 'D9')) best_move = np.argmax(player.root.child_N) self.assertEqual(best_move, flattened) # D9 should have a positive value self.assertGreater(player.root.children[flattened].Q, 0) self.assertGreaterEqual(player.root.N, 20) # passing should be ineffective. self.assertLess(player.root.child_Q[-1], 0) # no virtual losses should be pending self.assertNoPendingVirtualLosses(player.root)
def test_select_leaf(self): flattened = coords.to_flat(coords.from_kgs('D9')) probs = np.array([.02] * (go.N * go.N + 1)) probs[flattened] = 0.4 root = MCTSNode(SEND_TWO_RETURN_ONE) root.select_leaf().incorporate_results(probs, 0, root) self.assertEqual(root.position.to_play, go.WHITE) self.assertEqual(root.select_leaf(), root.children[flattened])
def test_upperleft(self): self.assertEqual(coords.from_sgf('aa'), (0, 0)) self.assertEqual(coords.from_flat(0), (0, 0)) self.assertEqual(coords.from_kgs('A9'), (0, 0)) self.assertEqual(coords.from_pygtp((1, 9)), (0, 0)) self.assertEqual(coords.to_sgf((0, 0)), 'aa') self.assertEqual(coords.to_flat((0, 0)), 0) self.assertEqual(coords.to_kgs((0, 0)), 'A9') self.assertEqual(coords.to_pygtp((0, 0)), (1, 9))
def test_pass(self): self.assertEqual(coords.from_sgf(''), None) self.assertEqual(coords.from_flat(81), None) self.assertEqual(coords.from_kgs('pass'), None) self.assertEqual(coords.from_pygtp((0, 0)), None) self.assertEqual(coords.to_sgf(None), '') self.assertEqual(coords.to_flat(None), 81) self.assertEqual(coords.to_kgs(None), 'pass') self.assertEqual(coords.to_pygtp(None), (0, 0))
def test_pass(self): self.assertEqual(coords.from_sgf(''), None) self.assertEqual(coords.from_flat(utils_test.BOARD_SIZE, 81), None) self.assertEqual(coords.from_kgs(utils_test.BOARD_SIZE, 'pass'), None) self.assertEqual(coords.from_pygtp(utils_test.BOARD_SIZE, (0, 0)), None) self.assertEqual(coords.to_sgf(None), '') self.assertEqual(coords.to_flat(utils_test.BOARD_SIZE, None), 81) self.assertEqual(coords.to_kgs(utils_test.BOARD_SIZE, None), 'pass') self.assertEqual(coords.to_pygtp(utils_test.BOARD_SIZE, None), (0, 0))
def test_topleft(self): self.assertEqual(coords.from_sgf('ia'), (0, 8)) self.assertEqual(coords.from_flat(8), (0, 8)) self.assertEqual(coords.from_kgs('J9'), (0, 8)) self.assertEqual(coords.from_pygtp((9, 9)), (0, 8)) self.assertEqual(coords.to_sgf((0, 8)), 'ia') self.assertEqual(coords.to_flat((0, 8)), 8) self.assertEqual(coords.to_kgs((0, 8)), 'J9') self.assertEqual(coords.to_pygtp((0, 8)), (9, 9))
def test_topleft(self): self.assertEqual(coords.from_sgf('ia'), (0, 8)) self.assertEqual(coords.from_flat(utils_test.BOARD_SIZE, 8), (0, 8)) self.assertEqual(coords.from_kgs(utils_test.BOARD_SIZE, 'J9'), (0, 8)) self.assertEqual(coords.from_pygtp(utils_test.BOARD_SIZE, (9, 9)), (0, 8)) self.assertEqual(coords.to_sgf((0, 8)), 'ia') self.assertEqual(coords.to_flat(utils_test.BOARD_SIZE, (0, 8)), 8) self.assertEqual(coords.to_kgs(utils_test.BOARD_SIZE, (0, 8)), 'J9') self.assertEqual(coords.to_pygtp(utils_test.BOARD_SIZE, (0, 8)), (9, 9))
def test_upperleft(self): self.assertEqual(coords.from_sgf('aa'), (0, 0)) self.assertEqual(coords.from_flat(utils_test.BOARD_SIZE, 0), (0, 0)) self.assertEqual(coords.from_kgs(utils_test.BOARD_SIZE, 'A9'), (0, 0)) self.assertEqual(coords.from_pygtp(utils_test.BOARD_SIZE, (1, 9)), (0, 0)) self.assertEqual(coords.to_sgf((0, 0)), 'aa') self.assertEqual(coords.to_flat(utils_test.BOARD_SIZE, (0, 0)), 0) self.assertEqual(coords.to_kgs(utils_test.BOARD_SIZE, (0, 0)), 'A9') self.assertEqual(coords.to_pygtp(utils_test.BOARD_SIZE, (0, 0)), (1, 9))
def test_move(self): start_position = Position( board=TEST_BOARD, n=0, komi=6.5, caps=(1, 2), ko=None, recent=tuple(), to_play=BLACK, ) expected_board = test_utils.load_board(''' .XX....OO X........ ''' + EMPTY_ROW * 7) expected_position = Position( board=expected_board, n=1, komi=6.5, caps=(1, 2), ko=None, recent=(PlayerMove(BLACK, coords.from_kgs('C9')),), to_play=WHITE, ) actual_position = start_position.play_move(coords.from_kgs('C9')) self.assertEqualPositions(actual_position, expected_position) expected_board2 = test_utils.load_board(''' .XX....OO X.......O ''' + EMPTY_ROW * 7) expected_position2 = Position( board=expected_board2, n=2, komi=6.5, caps=(1, 2), ko=None, recent=(PlayerMove(BLACK, coords.from_kgs('C9')), PlayerMove(WHITE, coords.from_kgs('J8'))), to_play=BLACK, ) actual_position2 = actual_position.play_move(coords.from_kgs('J8')) self.assertEqualPositions(actual_position2, expected_position2)
def test_move(self): start_position = Position( board=TEST_BOARD, n=0, komi=6.5, caps=(1, 2), ko=None, recent=tuple(), to_play=BLACK, ) expected_board = test_utils.load_board(''' .XX....OO X........ ''' + EMPTY_ROW * 7) expected_position = Position( board=expected_board, n=1, komi=6.5, caps=(1, 2), ko=None, recent=(PlayerMove(BLACK, coords.from_kgs('C9')), ), to_play=WHITE, ) actual_position = start_position.play_move(coords.from_kgs('C9')) self.assertEqualPositions(actual_position, expected_position) expected_board2 = test_utils.load_board(''' .XX....OO X.......O ''' + EMPTY_ROW * 7) expected_position2 = Position( board=expected_board2, n=2, komi=6.5, caps=(1, 2), ko=None, recent=(PlayerMove(BLACK, coords.from_kgs('C9')), PlayerMove(WHITE, coords.from_kgs('J8'))), to_play=BLACK, ) actual_position2 = actual_position.play_move(coords.from_kgs('J8')) self.assertEqualPositions(actual_position2, expected_position2)
def test_same_opponent_group_neighboring_twice(self): board = test_utils.load_board(''' XX....... X........ ''' + EMPTY_ROW * 7) lib_tracker = LibertyTracker.from_board(board) captured = lib_tracker.add_stone(WHITE, coords.from_kgs('B8')) self.assertEqual(len(lib_tracker.groups), 2) black_group = lib_tracker.groups[lib_tracker.group_index[coords.from_kgs( 'A9')]] self.assertEqual(black_group.stones, coords_from_kgs_set('A9 B9 A8')) self.assertEqual(black_group.liberties, coords_from_kgs_set('C9 A7')) white_group = lib_tracker.groups[lib_tracker.group_index[coords.from_kgs( 'B8')]] self.assertEqual(white_group.stones, coords_from_kgs_set('B8')) self.assertEqual(white_group.liberties, coords_from_kgs_set('C8 B7')) self.assertEqual(captured, set())
def test_same_opponent_group_neighboring_twice(self): board = test_utils.load_board(''' XX....... X........ ''' + EMPTY_ROW * 7) lib_tracker = LibertyTracker.from_board(board) captured = lib_tracker.add_stone(WHITE, coords.from_kgs('B8')) self.assertEqual(len(lib_tracker.groups), 2) black_group = lib_tracker.groups[lib_tracker.group_index[ coords.from_kgs('A9')]] self.assertEqual(black_group.stones, coords_from_kgs_set('A9 B9 A8')) self.assertEqual(black_group.liberties, coords_from_kgs_set('C9 A7')) white_group = lib_tracker.groups[lib_tracker.group_index[ coords.from_kgs('B8')]] self.assertEqual(white_group.stones, coords_from_kgs_set('B8')) self.assertEqual(white_group.liberties, coords_from_kgs_set('C8 B7')) self.assertEqual(captured, set())
def test_select_leaf(self): flattened = coords.to_flat( utils_test.BOARD_SIZE, coords.from_kgs(utils_test.BOARD_SIZE, 'D9')) probs = np.array([.02] * (utils_test.BOARD_SIZE * utils_test.BOARD_SIZE + 1)) probs[flattened] = 0.4 root = MCTSNode(utils_test.BOARD_SIZE, SEND_TWO_RETURN_ONE) root.select_leaf().incorporate_results(probs, 0, root) self.assertEqual(root.position.to_play, go.WHITE) self.assertEqual(root.select_leaf(), root.children[flattened])
def test_place_stone(self): board = utils_test.load_board('X........' + EMPTY_ROW * 8) lib_tracker = LibertyTracker.from_board(utils_test.BOARD_SIZE, board) lib_tracker.add_stone(BLACK, coords.from_kgs(utils_test.BOARD_SIZE, 'B9')) self.assertEqual(len(lib_tracker.groups), 1) self.assertNotEqual( lib_tracker.group_index[coords.from_kgs(utils_test.BOARD_SIZE, 'A9')], go.MISSING_GROUP_ID) self.assertEqual( lib_tracker.liberty_cache[coords.from_kgs(utils_test.BOARD_SIZE, 'A9')], 3) self.assertEqual( lib_tracker.liberty_cache[coords.from_kgs(utils_test.BOARD_SIZE, 'B9')], 3) sole_group = lib_tracker.groups[lib_tracker.group_index[ coords.from_kgs(utils_test.BOARD_SIZE, 'A9')]] self.assertEqual(sole_group.stones, coords_from_kgs_set('A9 B9')) self.assertEqual(sole_group.liberties, coords_from_kgs_set('C9 A8 B8')) self.assertEqual(sole_group.color, BLACK)
def test_ko_move(self): start_board = test_utils.load_board(''' .OX...... OX....... ''' + EMPTY_ROW * 7) start_position = Position( board=start_board, n=0, komi=6.5, caps=(1, 2), ko=None, recent=tuple(), to_play=BLACK, ) expected_board = test_utils.load_board(''' X.X...... OX....... ''' + EMPTY_ROW * 7) expected_position = Position( board=expected_board, n=1, komi=6.5, caps=(2, 2), ko=coords.from_kgs('B9'), recent=(PlayerMove(BLACK, coords.from_kgs('A9')),), to_play=WHITE, ) actual_position = start_position.play_move(coords.from_kgs('A9')) self.assertEqualPositions(actual_position, expected_position) # Check that retaking ko is illegal until two intervening moves with self.assertRaises(go.IllegalMove): actual_position.play_move(coords.from_kgs('B9')) pass_twice = actual_position.pass_move().pass_move() ko_delayed_retake = pass_twice.play_move(coords.from_kgs('B9')) expected_position = Position( board=start_board, n=4, komi=6.5, caps=(2, 3), ko=coords.from_kgs('A9'), recent=( PlayerMove(BLACK, coords.from_kgs('A9')), PlayerMove(WHITE, None), PlayerMove(BLACK, None), PlayerMove(WHITE, coords.from_kgs('B9'))), to_play=BLACK, ) self.assertEqualPositions(ko_delayed_retake, expected_position)
def test_merge_multiple_groups(self): board = test_utils.load_board(''' .X....... X.X...... .X....... ''' + EMPTY_ROW * 6) lib_tracker = LibertyTracker.from_board(board) lib_tracker.add_stone(BLACK, coords.from_kgs('B8')) self.assertEqual(len(lib_tracker.groups), 1) self.assertNotEqual(lib_tracker.group_index[coords.from_kgs('B8')], go.MISSING_GROUP_ID) sole_group = lib_tracker.groups[lib_tracker.group_index[ coords.from_kgs('B8')]] self.assertEqual(sole_group.stones, coords_from_kgs_set('B9 A8 B8 C8 B7')) self.assertEqual(sole_group.liberties, coords_from_kgs_set('A9 C9 D8 A7 C7 B6')) self.assertEqual(sole_group.color, BLACK) liberty_cache = lib_tracker.liberty_cache for stone in sole_group.stones: self.assertEqual(liberty_cache[stone], 6, str(stone))
def test_parsing_9x9(self): self.assertEqual(coords.from_sgf('aa'), (0, 0)) self.assertEqual(coords.from_sgf('ac'), (2, 0)) self.assertEqual(coords.from_sgf('ca'), (0, 2)) self.assertEqual(coords.from_sgf(''), None) self.assertEqual(coords.to_sgf(None), '') self.assertEqual('aa', coords.to_sgf(coords.from_sgf('aa'))) self.assertEqual('sa', coords.to_sgf(coords.from_sgf('sa'))) self.assertEqual((1, 17), coords.from_sgf(coords.to_sgf((1, 17)))) self.assertEqual(coords.from_kgs('A1'), (8, 0)) self.assertEqual(coords.from_kgs('A9'), (0, 0)) self.assertEqual(coords.from_kgs('C2'), (7, 2)) self.assertEqual(coords.from_kgs('J2'), (7, 8)) self.assertEqual(coords.from_pygtp((1, 1)), (8, 0)) self.assertEqual(coords.from_pygtp((1, 9)), (0, 0)) self.assertEqual(coords.from_pygtp((3, 2)), (7, 2)) self.assertEqual(coords.to_pygtp((8, 0)), (1, 1)) self.assertEqual(coords.to_pygtp((0, 0)), (1, 9)) self.assertEqual(coords.to_pygtp((7, 2)), (3, 2)) self.assertEqual(coords.to_kgs((0, 8)), 'J9') self.assertEqual(coords.to_kgs((8, 0)), 'A1')
def test_merge_multiple_groups(self): board = test_utils.load_board(''' .X....... X.X...... .X....... ''' + EMPTY_ROW * 6) lib_tracker = LibertyTracker.from_board(board) lib_tracker.add_stone(BLACK, coords.from_kgs('B8')) self.assertEqual(len(lib_tracker.groups), 1) self.assertNotEqual( lib_tracker.group_index[coords.from_kgs('B8')], go.MISSING_GROUP_ID) sole_group = lib_tracker.groups[lib_tracker.group_index[coords.from_kgs( 'B8')]] self.assertEqual(sole_group.stones, coords_from_kgs_set('B9 A8 B8 C8 B7')) self.assertEqual(sole_group.liberties, coords_from_kgs_set('A9 C9 D8 A7 C7 B6')) self.assertEqual(sole_group.color, BLACK) liberty_cache = lib_tracker.liberty_cache for stone in sole_group.stones: self.assertEqual(liberty_cache[stone], 6, str(stone))
def test_ko_move(self): start_board = test_utils.load_board(''' .OX...... OX....... ''' + EMPTY_ROW * 7) start_position = Position( board=start_board, n=0, komi=6.5, caps=(1, 2), ko=None, recent=tuple(), to_play=BLACK, ) expected_board = test_utils.load_board(''' X.X...... OX....... ''' + EMPTY_ROW * 7) expected_position = Position( board=expected_board, n=1, komi=6.5, caps=(2, 2), ko=coords.from_kgs('B9'), recent=(PlayerMove(BLACK, coords.from_kgs('A9')), ), to_play=WHITE, ) actual_position = start_position.play_move(coords.from_kgs('A9')) self.assertEqualPositions(actual_position, expected_position) # Check that retaking ko is illegal until two intervening moves with self.assertRaises(go.IllegalMove): actual_position.play_move(coords.from_kgs('B9')) pass_twice = actual_position.pass_move().pass_move() ko_delayed_retake = pass_twice.play_move(coords.from_kgs('B9')) expected_position = Position( board=start_board, n=4, komi=6.5, caps=(2, 3), ko=coords.from_kgs('A9'), recent=(PlayerMove(BLACK, coords.from_kgs('A9')), PlayerMove(WHITE, None), PlayerMove(BLACK, None), PlayerMove(WHITE, coords.from_kgs('B9'))), to_play=BLACK, ) self.assertEqualPositions(ko_delayed_retake, expected_position)
def test_move_with_capture(self): start_board = utils_test.load_board(EMPTY_ROW * 5 + ''' XXXX..... XOOX..... O.OX..... OOXX..... ''') start_position = Position( utils_test.BOARD_SIZE, board=start_board, n=0, komi=6.5, caps=(1, 2), ko=None, recent=tuple(), to_play=BLACK, ) expected_board = utils_test.load_board(EMPTY_ROW * 5 + ''' XXXX..... X..X..... .X.X..... ..XX..... ''') expected_position = Position( utils_test.BOARD_SIZE, board=expected_board, n=1, komi=6.5, caps=(7, 2), ko=None, recent=(PlayerMove(BLACK, coords.from_kgs(utils_test.BOARD_SIZE, 'B2')), ), to_play=WHITE, ) actual_position = start_position.play_move( coords.from_kgs(utils_test.BOARD_SIZE, 'B2')) self.assertEqualPositions(actual_position, expected_position)
def test_capture_many(self): board = utils_test.load_board(''' .XX...... XOO...... .XX...... ''' + EMPTY_ROW * 6) lib_tracker = LibertyTracker.from_board(utils_test.BOARD_SIZE, board) captured = lib_tracker.add_stone( BLACK, coords.from_kgs(utils_test.BOARD_SIZE, 'D8')) self.assertEqual(len(lib_tracker.groups), 4) self.assertEqual( lib_tracker.group_index[coords.from_kgs(utils_test.BOARD_SIZE, 'B8')], go.MISSING_GROUP_ID) self.assertEqual(captured, coords_from_kgs_set('B8 C8')) left_group = lib_tracker.groups[lib_tracker.group_index[ coords.from_kgs(utils_test.BOARD_SIZE, 'A8')]] self.assertEqual(left_group.stones, coords_from_kgs_set('A8')) self.assertEqual(left_group.liberties, coords_from_kgs_set('A9 B8 A7')) right_group = lib_tracker.groups[lib_tracker.group_index[ coords.from_kgs(utils_test.BOARD_SIZE, 'D8')]] self.assertEqual(right_group.stones, coords_from_kgs_set('D8')) self.assertEqual(right_group.liberties, coords_from_kgs_set('D9 C8 E8 D7')) top_group = lib_tracker.groups[lib_tracker.group_index[coords.from_kgs( utils_test.BOARD_SIZE, 'B9')]] self.assertEqual(top_group.stones, coords_from_kgs_set('B9 C9')) self.assertEqual(top_group.liberties, coords_from_kgs_set('A9 D9 B8 C8')) bottom_group = lib_tracker.groups[lib_tracker.group_index[ coords.from_kgs(utils_test.BOARD_SIZE, 'B7')]] self.assertEqual(bottom_group.stones, coords_from_kgs_set('B7 C7')) self.assertEqual(bottom_group.liberties, coords_from_kgs_set('B8 C8 A7 D7 B6 C6')) liberty_cache = lib_tracker.liberty_cache for stone in top_group.stones: self.assertEqual(liberty_cache[stone], 4, str(stone)) for stone in left_group.stones: self.assertEqual(liberty_cache[stone], 3, str(stone)) for stone in right_group.stones: self.assertEqual(liberty_cache[stone], 4, str(stone)) for stone in bottom_group.stones: self.assertEqual(liberty_cache[stone], 6, str(stone)) for stone in captured: self.assertEqual(liberty_cache[stone], 0, str(stone))
def test_flipturn(self): start_position = Position( board=TEST_BOARD, n=0, komi=6.5, caps=(1, 2), ko=coords.from_kgs('A1'), recent=tuple(), to_play=BLACK, ) expected_position = Position( board=TEST_BOARD, n=0, komi=6.5, caps=(1, 2), ko=None, recent=tuple(), to_play=WHITE, ) flip_position = start_position.flip_playerturn() self.assertEqualPositions(flip_position, expected_position)
def test_passing(self): start_position = Position( board=TEST_BOARD, n=0, komi=6.5, caps=(1, 2), ko=coords.from_kgs('A1'), recent=tuple(), to_play=BLACK, ) expected_position = Position( board=TEST_BOARD, n=1, komi=6.5, caps=(1, 2), ko=None, recent=(PlayerMove(BLACK, None), ), to_play=WHITE, ) pass_position = start_position.pass_move() self.assertEqualPositions(pass_position, expected_position)
def test_capture_many(self): board = test_utils.load_board(''' .XX...... XOO...... .XX...... ''' + EMPTY_ROW * 6) lib_tracker = LibertyTracker.from_board(board) captured = lib_tracker.add_stone(BLACK, coords.from_kgs('D8')) self.assertEqual(len(lib_tracker.groups), 4) self.assertEqual( lib_tracker.group_index[coords.from_kgs('B8')], go.MISSING_GROUP_ID) self.assertEqual(captured, coords_from_kgs_set('B8 C8')) left_group = lib_tracker.groups[lib_tracker.group_index[coords.from_kgs( 'A8')]] self.assertEqual(left_group.stones, coords_from_kgs_set('A8')) self.assertEqual(left_group.liberties, coords_from_kgs_set('A9 B8 A7')) right_group = lib_tracker.groups[lib_tracker.group_index[coords.from_kgs( 'D8')]] self.assertEqual(right_group.stones, coords_from_kgs_set('D8')) self.assertEqual(right_group.liberties, coords_from_kgs_set('D9 C8 E8 D7')) top_group = lib_tracker.groups[lib_tracker.group_index[coords.from_kgs( 'B9')]] self.assertEqual(top_group.stones, coords_from_kgs_set('B9 C9')) self.assertEqual(top_group.liberties, coords_from_kgs_set('A9 D9 B8 C8')) bottom_group = lib_tracker.groups[lib_tracker.group_index[coords.from_kgs( 'B7')]] self.assertEqual(bottom_group.stones, coords_from_kgs_set('B7 C7')) self.assertEqual(bottom_group.liberties, coords_from_kgs_set('B8 C8 A7 D7 B6 C6')) liberty_cache = lib_tracker.liberty_cache for stone in top_group.stones: self.assertEqual(liberty_cache[stone], 4, str(stone)) for stone in left_group.stones: self.assertEqual(liberty_cache[stone], 3, str(stone)) for stone in right_group.stones: self.assertEqual(liberty_cache[stone], 4, str(stone)) for stone in bottom_group.stones: self.assertEqual(liberty_cache[stone], 6, str(stone)) for stone in captured: self.assertEqual(liberty_cache[stone], 0, str(stone))
def test_passing(self): start_position = Position( board=TEST_BOARD, n=0, komi=6.5, caps=(1, 2), ko=coords.from_kgs('A1'), recent=tuple(), to_play=BLACK, ) expected_position = Position( board=TEST_BOARD, n=1, komi=6.5, caps=(1, 2), ko=None, recent=(PlayerMove(BLACK, None),), to_play=WHITE, ) pass_position = start_position.pass_move() self.assertEqualPositions(pass_position, expected_position)
def test_dont_pass_if_losing(self): player = initialize_almost_done_player() # check -- white is losing. self.assertEqual(player.root.position.score(), -0.5) for i in range(20): player.tree_search() # uncomment to debug this test # print(player.root.describe()) # Search should converge on D9 as only winning move. flattened = coords.to_flat(coords.from_kgs('D9')) best_move = np.argmax(player.root.child_N) self.assertEqual(best_move, flattened) # D9 should have a positive value self.assertGreater(player.root.children[flattened].Q, 0) self.assertGreaterEqual(player.root.N, 20) # passing should be ineffective. self.assertLess(player.root.child_Q[-1], 0) # no virtual losses should be pending self.assertNoPendingVirtualLosses(player.root)
def test_place_stone_opposite_color(self): board = test_utils.load_board('X........' + EMPTY_ROW * 8) lib_tracker = LibertyTracker.from_board(board) lib_tracker.add_stone(WHITE, coords.from_kgs('B9')) self.assertEqual(len(lib_tracker.groups), 2) self.assertNotEqual( lib_tracker.group_index[coords.from_kgs('A9')], go.MISSING_GROUP_ID) self.assertNotEqual( lib_tracker.group_index[coords.from_kgs('B9')], go.MISSING_GROUP_ID) self.assertEqual(lib_tracker.liberty_cache[coords.from_kgs('A9')], 1) self.assertEqual(lib_tracker.liberty_cache[coords.from_kgs('B9')], 2) black_group = lib_tracker.groups[lib_tracker.group_index[coords.from_kgs( 'A9')]] white_group = lib_tracker.groups[lib_tracker.group_index[coords.from_kgs( 'B9')]] self.assertEqual(black_group.stones, coords_from_kgs_set('A9')) self.assertEqual(black_group.liberties, coords_from_kgs_set('A8')) self.assertEqual(black_group.color, BLACK) self.assertEqual(white_group.stones, coords_from_kgs_set('B9')) self.assertEqual(white_group.liberties, coords_from_kgs_set('C9 B8')) self.assertEqual(white_group.color, WHITE)
def test_place_stone_opposite_color(self): board = test_utils.load_board('X........' + EMPTY_ROW * 8) lib_tracker = LibertyTracker.from_board(board) lib_tracker.add_stone(WHITE, coords.from_kgs('B9')) self.assertEqual(len(lib_tracker.groups), 2) self.assertNotEqual(lib_tracker.group_index[coords.from_kgs('A9')], go.MISSING_GROUP_ID) self.assertNotEqual(lib_tracker.group_index[coords.from_kgs('B9')], go.MISSING_GROUP_ID) self.assertEqual(lib_tracker.liberty_cache[coords.from_kgs('A9')], 1) self.assertEqual(lib_tracker.liberty_cache[coords.from_kgs('B9')], 2) black_group = lib_tracker.groups[lib_tracker.group_index[ coords.from_kgs('A9')]] white_group = lib_tracker.groups[lib_tracker.group_index[ coords.from_kgs('B9')]] self.assertEqual(black_group.stones, coords_from_kgs_set('A9')) self.assertEqual(black_group.liberties, coords_from_kgs_set('A8')) self.assertEqual(black_group.color, BLACK) self.assertEqual(white_group.stones, coords_from_kgs_set('B9')) self.assertEqual(white_group.liberties, coords_from_kgs_set('C9 B8')) self.assertEqual(white_group.color, WHITE)
def test_dont_pass_if_losing(self): player = initialize_almost_done_player() # check -- white is losing. self.assertEqual(player.root.position.score(), -0.5) for i in range(20): player.tree_search() # uncomment to debug this test # print(player.root.describe()) # Search should converge on D9 as only winning move. flattened = coords.to_flat(utils_test.BOARD_SIZE, coords.from_kgs( utils_test.BOARD_SIZE, 'D9')) best_move = np.argmax(player.root.child_N) self.assertEqual(best_move, flattened) # D9 should have a positive value self.assertGreater(player.root.children[flattened].Q, 0) self.assertGreaterEqual(player.root.N, 20) # passing should be ineffective. self.assertLess(player.root.child_Q[-1], 0) # no virtual losses should be pending self.assertNoPendingVirtualLosses(player.root)
def test_parallel_tree_search(self): player = initialize_almost_done_player() # check -- white is losing. self.assertEqual(player.root.position.score(), -0.5) # initialize the tree so that the root node has populated children. player.tree_search(num_parallel=1) # virtual losses should enable multiple searches to happen simultaneously # without throwing an error... for i in range(5): player.tree_search(num_parallel=4) # uncomment to debug this test # print(player.root.describe()) # Search should converge on D9 as only winning move. flattened = coords.to_flat(coords.from_kgs('D9')) best_move = np.argmax(player.root.child_N) self.assertEqual(best_move, flattened) # D9 should have a positive value self.assertGreater(player.root.children[flattened].Q, 0) self.assertGreaterEqual(player.root.N, 20) # passing should be ineffective. self.assertLess(player.root.child_Q[-1], 0) # no virtual losses should be pending self.assertNoPendingVirtualLosses(player.root)
def test_is_koish(self): self.assertEqual(go.is_koish( TEST_BOARD, coords.from_kgs('A9')), BLACK) self.assertEqual(go.is_koish(TEST_BOARD, coords.from_kgs('B8')), None) self.assertEqual(go.is_koish(TEST_BOARD, coords.from_kgs('B9')), None) self.assertEqual(go.is_koish(TEST_BOARD, coords.from_kgs('E5')), None)
def test_is_koish(self): self.assertEqual(go.is_koish(TEST_BOARD, coords.from_kgs('A9')), BLACK) self.assertEqual(go.is_koish(TEST_BOARD, coords.from_kgs('B8')), None) self.assertEqual(go.is_koish(TEST_BOARD, coords.from_kgs('B9')), None) self.assertEqual(go.is_koish(TEST_BOARD, coords.from_kgs('E5')), None)
def _from_kgs(kgsc): return coords.from_kgs(utils_test.BOARD_SIZE, kgsc)