def test_leela_board_with_history(self): state = State(3, max_history_n=8) moves = [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] for move in moves: state.make_move(move, Color.BLACK) state.current_player = Color.BLACK expected_black_history = np.array([ [[1, 1, 1], [1, 1, 1], [1, 1, 1]], [[1, 1, 1], [1, 1, 1], [1, 1, 0]], [[1, 1, 1], [1, 1, 1], [1, 0, 0]], [[1, 1, 1], [1, 1, 1], [0, 0, 0]], [[1, 1, 1], [1, 1, 0], [0, 0, 0]], [[1, 1, 1], [1, 0, 0], [0, 0, 0]], [[1, 1, 1], [0, 0, 0], [0, 0, 0]], [[1, 1, 0], [0, 0, 0], [0, 0, 0]], ], ) expected_planes = np.concatenate( (expected_black_history, np.zeros((8, 3, 3)))) actual_planes = F.leela_board(state, Order.TH) npt.assert_equal(expected_planes, actual_planes)
def capture_size(state: State, order=Order.TH, nb_planes=8, dtype=np.float32) -> np.ndarray: if order == Order.TH: planes = np.zeros((nb_planes, state.board_size, state.board_size), dtype=dtype) else: planes = np.zeros((state.board_size, state.board_size, nb_planes), dtype=dtype) for x, y in state.legal_moves(): nb_captured = 0 for neighbors in state.groups_around_at((x, y)): neighbor = next( iter(neighbors)) # get an arbitrary stone in the 'neighbors' if state.liberty_counts[neighbor] == 1 and state.board[ neighbor] != state.current_player: # if the group has 1 liberty and the group is not my color, # the group would be captured nb_captured += len(state.groups[neighbor]) if order == Order.TH: planes[min(nb_captured, nb_planes - 1), x, y] = 1 else: planes[x, y, min(nb_captured, nb_planes - 1)] = 1 return planes
def test_history_no_history(self): size = 3 state = State(board_size=size, max_history_n=0) assert len(state.history_buffer) == 0 state.make_move((0, 0)) assert len(state.history_buffer) == 0
def test_copy_maintains_shared_sets(): state = State(7) state.make_move((4, 4), Color.BLACK) state.make_move((4, 5), Color.BLACK) # assert that state has *the same object* referenced by group/liberty sets assert state.groups[(4, 5)] is state.groups[(4, 4)] assert state.liberty_sets[(4, 5)] is state.liberty_sets[(4, 4)] copied = state.copy() assert copied.groups[(4, 5)] is copied.groups[(4, 4)] assert copied.liberty_sets[(4, 5)] is copied.liberty_sets[(4, 4)]
def sensibleness(state: State, order=Order.TH, dtype=np.float32) -> np.ndarray: if order == Order.TH: planes = np.zeros((1, state.board_size, state.board_size), dtype=dtype) for x, y in state.legal_moves(include_eyes=False): planes[0, x, y] = 1 else: planes = np.zeros((state.board_size, state.board_size, 1), dtype=dtype) for x, y in state.legal_moves(include_eyes=False): planes[x, y, 0] = 1 return planes
def ladder_escape(state: State, order=Order.TH, dtype=np.float32) -> np.ndarray: if order == Order.TH: planes = np.zeros((1, state.board_size, state.board_size), dtype=dtype) for x, y in state.legal_moves(): planes[0, x, y] = state.is_ladder_capture((x, y)) else: planes = np.zeros((state.board_size, state.board_size, 1), dtype=dtype) for x, y in state.legal_moves(): planes[x, y, 0] = state.is_ladder_capture((x, y)) return planes
def self_atari_size(state: State, order=Order.TH, nb_planes=8, dtype=np.float32) -> np.ndarray: if order == Order.TH: planes = np.zeros((nb_planes, state.board_size, state.board_size), dtype=dtype) else: planes = np.zeros((state.board_size, state.board_size, nb_planes), dtype=dtype) for x, y in state.legal_moves(): liberty_set_after = set(state.liberty_sets[(x, y)]) group_after_move = {(x, y)} captured_stones = set() for neighbors in state.groups_around_at((x, y)): neighbor = next( iter(neighbors)) # get an arbitrary stone in 'neighbors' if state.board[neighbor] == state.current_player: # if the group is mine, take them into account liberty_set_after |= state.liberty_sets[neighbor] group_after_move |= state.groups[neighbor] elif state.liberty_counts[neighbor] == 1: # if the group is enemy's and the group would be captured # (neighbor cannot be Color.EMPTY because neighbors has one liberty) captured_stones |= state.groups[neighbor] if captured_stones: for stone in group_after_move: # if there are some groups that can be captured, # the coordinates in which captured group was in can be new liberties of mine liberty_set_after |= set( state.crosswise_neighbors_of(stone)) & captured_stones if (x, y) in liberty_set_after: liberty_set_after.remove((x, y)) if len(liberty_set_after) == 1: if order == Order.TH: planes[min(nb_planes - 1, len(group_after_move) - 1), x, y] = 1 else: planes[x, y, min(nb_planes - 1, len(group_after_move) - 1)] = 1 return planes
def test_board_i_when_state_has_no_history(self): state = State(max_history_n=0) # with no exception when i = 0 F.board_i(state, i=0, order=Order.TF) with pytest.raises(AssertionError): F.board_i(state, i=1, order=Order.TF)
def test_leela_board_initial_state(self): state = State(3, max_history_n=8) npt.assert_equal( F.leela_board(state, order=Order.TH, n=2), np.array([ [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], ]))
def test_board_i(self): state = State(board_size=3, max_history_n=10) state.make_move((0, 0)) # Black state.make_move((0, 1)) # White state.make_move((0, 2)) # Black expected_2 = np.array([ [[0, 0, 0], [0, 0, 0], [0, 0, 0]], # White board [[1, 0, 0], [0, 0, 0], [0, 0, 0]], # Black board ]) expected_1 = np.array([ [[0, 1, 0], [0, 0, 0], [0, 0, 0]], # ditto [[1, 0, 0], [0, 0, 0], [0, 0, 0]], ]) expected_0 = np.array([ [[0, 1, 0], [0, 0, 0], [0, 0, 0]], [[1, 0, 1], [0, 0, 0], [0, 0, 0]], ]) expected_outbound = np.zeros((2, 3, 3)) assert state.current_player == Color.WHITE assert len(state.history_buffer) == 3 npt.assert_array_equal(expected_2, F.board_i(state, 2, order=Order.TH)) npt.assert_array_equal(expected_1, F.board_i(state, 1, order=Order.TH)) npt.assert_array_equal(expected_0, F.board_i(state, 0, order=Order.TH)) for n in range(3, 10): npt.assert_array_equal(expected_outbound, F.board_i(state, n, order=Order.TH))
def liberties_after_move(state: State, order=Order.TH, nb_planes=8, dtype=np.float32) -> np.ndarray: if order == Order.TH: planes = np.zeros((nb_planes, state.board_size, state.board_size), dtype=dtype) else: planes = np.zeros((state.board_size, state.board_size, nb_planes), dtype=dtype) for x, y in state.legal_moves(): liberty_set_after = set(state.liberty_sets[(x, y)]) group_after = {(x, y)} captured_stones = set() for neighbors in state.groups_around_at((x, y)): neighbor = next(iter(neighbors)) if state.board[neighbor] == state.current_player: liberty_set_after |= state.liberty_sets[neighbor] group_after |= state.groups[neighbor] elif state.liberty_counts[neighbor] == 1: captured_stones |= state.groups[neighbor] if captured_stones: for stone in group_after: liberty_set_after |= set( state.crosswise_neighbors_of(stone)) & captured_stones if (x, y) in liberty_set_after: liberty_set_after.remove((x, y)) if order == Order.TH: planes[min(nb_planes - 1, len(liberty_set_after) - 1), x, y] = 1 else: planes[x, y, min(nb_planes - 1, len(liberty_set_after) - 1)] = 1 return planes
def random_state(seed=None): import os import sys seed = seed or int.from_bytes(os.urandom(4), sys.byteorder) random = Random(seed) size = random.randint(3, 19) length = random.randint(0, size * size) state = State(board_size=size) for i in range(length): move = (random.randrange(0, size), random.randrange(0, size)) try: state.make_move(move) except IllegalMoveError: pass return state, seed
def test_turns_since(self): size = 3 state = State(board_size=size) expected_planes = [ np.array([[0, 0, 0], [0, 0, 0], [0, 0, 1]]), np.array([[0, 0, 0], [0, 0, 0], [0, 1, 0]]), np.array([[0, 0, 0], [0, 0, 0], [1, 0, 0]]), np.array([[0, 0, 0], [0, 0, 1], [0, 0, 0]]), np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]]), np.array([[0, 0, 0], [1, 0, 0], [0, 0, 0]]), np.array([[0, 0, 1], [0, 0, 0], [0, 0, 0]]), np.array([[1, 1, 0], [0, 0, 0], [0, 0, 0]]), ] for move in all_coordinates(size=size): state.make_move(move, Color.BLACK) planes = F.turns_since(state, order=Order.TF) assert planes.shape == (state.board_size, state.board_size, 8) for i, expected_plane in enumerate(expected_planes): npt.assert_array_equal(expected_plane, planes[:, :, i])
def test_history(self): size = 3 state = State(board_size=size, max_history_n=10) expected_boards = [ np.array([[+0, +0, +0], [+0, +0, +0], [+0, +0, +0]]), np.array([[+1, +0, +0], [+0, +0, +0], [+0, +0, +0]]), np.array([[+1, -1, +0], [+0, +0, +0], [+0, +0, +0]]), ] state.make_move((0, 0)) state.make_move((0, 1)) state.make_move((0, 2)) assert len(state.history_buffer) == len(expected_boards) npt.assert_equal(state.history_buffer[0], expected_boards[0]) npt.assert_equal(state.history_buffer[1], expected_boards[1]) npt.assert_equal(state.history_buffer[2], expected_boards[2])