def is_point_an_eye(board, point, color): if board.get(point) is not None: return False for neighbor in point.neighbors(): if board.is_on_grid(neighbor): neighbor_color = board.get(neighbor) if neighbor_color != color: return False friendly_corners = 0 off_board_corners = 0 corners = [ Point(point.row - 1, point.col - 1), Point(point.row - 1, point.col + 1), Point(point.row + 1, point.col - 1), Point(point.row + 1, point.col + 1), ] for corner in corners: if board.is_on_grid(corner): corner_color = board.get(corner) if corner_color == color: friendly_corners += 1 else: off_board_corners += 1 if off_board_corners > 0: return off_board_corners + friendly_corners == 4 return friendly_corners >= 3
def init_neighbor_table(dim): rows, cols = dim new_table = {} for r in range(1, rows + 1): for c in range(1, cols + 1): p = Point(row=r, col=c) full_neighbors = p.neighbors() true_neighbors = [ n for n in full_neighbors if 1 <= n.row <= rows and 1 <= n.col <= cols] new_table[p] = true_neighbors neighbor_tables[dim] = new_table
def _update_cache(self, dim): # <1> self.dim = dim rows, cols = dim self.point_cache = [] for r in range(1, rows + 1): for c in range(1, cols + 1): self.point_cache.append(Point(row=r, col=c))
def test_generator(self): encoder_name = 'oneplane' generator = SupervisedLearningDataGenerator(encoder_name) with open('test_data/game1.sgf', "rb") as f: game = sgf.Sgf_game.from_bytes(f.read()) board_size = game.get_size() generator.new_game(board_size) main_sequence = game.get_main_sequence() node = main_sequence[1] generator.set_move(node.get_move()) X, y = generator.return_data() encoder = get_encoder_by_name(encoder_name, board_size) expected_X = np.zeros((encoder.num_planes, board_size, board_size)) expected_y = np.zeros(encoder.num_points()) expected_y[encoder.encode_point(Point(6, 6))] = 1 #B[fd] = Point (6,6) self.assertEqual(X[0].tolist(), expected_X.tolist()) self.assertEqual(y[0].tolist(), expected_y.tolist()) #todo: develop unit test for X[1], and X[2] node = main_sequence[2] generator.set_move(node.get_move()) node = main_sequence[3] generator.set_move(node.get_move()) X, y = generator.return_data()
def init_corner_table(dim): rows, cols = dim new_table = {} for r in range(1, rows + 1): for c in range(1, cols + 1): p = Point(row=r, col=c) full_corners = [ Point(row=p.row - 1, col=p.col - 1), Point(row=p.row - 1, col=p.col + 1), Point(row=p.row + 1, col=p.col - 1), Point(row=p.row + 1, col=p.col + 1), ] true_corners = [ n for n in full_corners if 1 <= n.row <= rows and 1 <= n.col <= cols] new_table[p] = true_corners corner_tables[dim] = new_table
def legal_moves(self): if self.is_over(): return [] moves = [] for row in range(1, self.board.num_rows + 1): for col in range(1, self.board.num_cols + 1): move = Move.play(Point(row, col)) if self.is_valid_move(move): moves.append(move) # These two moves are always legal. moves.append(Move.pass_turn()) moves.append(Move.resign()) return moves
def encode(self, game_state): # <1> board_matrix = np.zeros(self.shape()) next_player = game_state.next_player for r in range(self.board_height): for c in range(self.board_width): p = Point(row=r + 1, col=c + 1) go_string = game_state.board.get_go_string(p) if go_string is None: continue elif go_string.color == next_player: board_matrix[0, r, c] = 1 else: board_matrix[0, r, c] = -1 return board_matrix
def select_move(self, game_state): candidates = [] for r in range(1, game_state.board.num_rows + 1): for c in range(1, game_state.board.num_cols + 1): candidate = Point(row=r, col=c) if game_state.is_valid_move( Move.play(candidate)) and not is_point_an_eye( game_state.board, candidate, game_state.next_player): candidates.append(candidate) if not candidates: return Move.pass_turn() return Move.play(random.choice(candidates))
def encode(self, game_state): board_tensor = np.zeros(self.shape()) if game_state.next_player == Player.black: board_tensor[8] = 1 else: board_tensor[9] = 1 for r in range(self.board_height): for c in range(self.board_width): p = Point(row=r + 1, col=c + 1) go_string = game_state.board.get_go_string(p) if go_string is None: if game_state.does_move_violate_ko(game_state.next_player, Move.play(p)): board_tensor[10][r][c] = 1 else: liberty_plane = min(4, go_string.num_liberties) - 1 if go_string.color == Player.white: liberty_plane += 4 board_tensor[liberty_plane][r][c] = 1 return board_tensor
def evaluate_territory(board): status = {} for r in range(1, board.num_rows + 1): for c in range(1, board.num_cols + 1): p = Point(row=r, col=c) if p in status: # <1> continue stone = board.get(p) if stone is not None: # <2> status[p] = board.get(p) else: group, neighbors = _collect_region(p, board) if len(neighbors) == 1: # <3> neighbor_stone = neighbors.pop() stone_str = 'b' if neighbor_stone == Player.black else 'w' fill_with = 'territory_' + stone_str else: fill_with = 'dame' # <4> for pos in group: status[pos] = fill_with return Territory(status)
def _collect_region(start_pos, board, visited=None): if visited is None: visited = {} if start_pos in visited: return [], set() all_points = [start_pos] all_borders = set() visited[start_pos] = True here = board.get(start_pos) deltas = [(-1, 0), (1, 0), (0, -1), (0, 1)] for delta_r, delta_c in deltas: next_p = Point(row=start_pos.row + delta_r, col=start_pos.col + delta_c) if not board.is_on_grid(next_p): continue neighbor = board.get(next_p) if neighbor == here: points, borders = _collect_region(next_p, board, visited) all_points += points all_borders |= borders else: all_borders.add(neighbor) return all_points, all_borders
else: return Player.white MAX63 = 0x7fffffffffffffff random.seed(0) table = {} empty_barod = 0 codes = [] for row in range(1,20): for col in range(1,20): for state in (Player.black, Player.white, None): code = random.randint(1,MAX63) table[Point(row, col), state] = code codes.append(code) for code in codes: if codes.count(code) > 1: print("Hash collision occurred! Please change a different random seed!!") input("Press Enter to continue...") import sys original_stdout = sys.stdout with open('zobrist.py', 'w') as outfile: sys.stdout = outfile print('from dokigo.base import Player, Point') print('') print("__all__ = ['HASH_CODE', 'EMPTY_BOARD']")
def decode_point_index(self, index): row = index // self.board_width col = index % self.board_width return Point(row=row + 1, col=col + 1)
def _point(self, sgf_point): if sgf_point: return Point(row=sgf_point[0] + 1, col=sgf_point[1] + 1) else: return None
from dokigo.base import Player, Point __all__ = ['HASH_CODE', 'EMPTY_BOARD'] HASH_CODE = { (Point(row=1, col=1), Player.black): 3553260803050964942, (Point(row=1, col=1), Player.white): 8211050864078048429, (Point(row=1, col=2), Player.black): 373402508605428822, (Point(row=1, col=2), Player.white): 8904841857247764027, (Point(row=1, col=3), Player.black): 4481891911369680483, (Point(row=1, col=3), Player.white): 8469216845598671737, (Point(row=1, col=4), Player.black): 7654042048833979962, (Point(row=1, col=4), Player.white): 8926379391851030282, (Point(row=1, col=5), Player.black): 3302422582397125125, (Point(row=1, col=5), Player.white): 8224117987793733248, (Point(row=1, col=6), Player.black): 2014778559842358804, (Point(row=1, col=6), Player.white): 1284573236628236407, (Point(row=1, col=7), Player.black): 1288927344666773108, (Point(row=1, col=7), Player.white): 874659381428118138, (Point(row=1, col=8), Player.black): 7373187333409828413, (Point(row=1, col=8), Player.white): 9105858850789076728, (Point(row=1, col=9), Player.black): 4912032505523413355, (Point(row=1, col=9), Player.white): 6504065999293633590, (Point(row=1, col=10), Player.black): 5551566716156929439, (Point(row=1, col=10), Player.white): 1355479673763813644, (Point(row=1, col=11), Player.black): 910931048343655642, (Point(row=1, col=11), Player.white): 680153880282415356, (Point(row=1, col=12), Player.black): 7844236507003634717, (Point(row=1, col=12), Player.white): 3045531827580801579, (Point(row=1, col=13), Player.black): 5163369892407040088, (Point(row=1, col=13), Player.white): 3263149039050788341,
def decode_point_index(self, index): """Turn an integer index into a board point.""" row = index // self.board_width col = index % self.board_width return Point(row=row + 1, col=col + 1)