def test_get_setup_and_moves(tc): g1 = sgf.Sgf_game.from_string(SAMPLE_SGF) board1, plays1 = sgf_moves.get_setup_and_moves(g1) tc.assertBoardEqual(board1, DIAGRAM1) tc.assertEqual(plays1, [('b', (2, 3)), ('w', (3, 4)), ('b', None), ('w', None)]) g2 = sgf.Sgf_game(size=9) root = g2.get_root() root.set("AB", [(1, 2), (3, 4)]) node = g2.extend_main_sequence() node.set("B", (5, 6)) node = g2.extend_main_sequence() node.set("W", (5, 7)) board2, plays2 = sgf_moves.get_setup_and_moves(g2) tc.assertBoardEqual(board2, DIAGRAM2) tc.assertEqual(plays2, [('b', (5, 6)), ('w', (5, 7))]) g3 = sgf.Sgf_game.from_string("(;AB[ab][ba]AW[aa])") tc.assertRaisesRegexp(ValueError, "setup position not legal", sgf_moves.get_setup_and_moves, g3) g4 = sgf.Sgf_game.from_string("(;SZ[9];B[ab];AW[bc])") tc.assertRaisesRegexp(ValueError, "setup properties after the root node", sgf_moves.get_setup_and_moves, g4) g5 = sgf.Sgf_game.from_string("(;SZ[26];B[ab];W[bc])") board5, plays5 = sgf_moves.get_setup_and_moves(g5) tc.assertEqual(plays5, [('b', (24, 0)), ('w', (23, 1))])
def load_from_sgf(self, sgf_filepath): """ Adaptation of show_sgf_file function on examples/show_sgf in gomill package. Args: sgf_filepath Raises: IOError, if file open and/or read fails. """ try: with open(sgf_filepath) as f: sgf_game = sgf.Sgf_game.from_string(f.read()) except ValueError: raise StandardError("bad sgf file") try: (gomill_board, plays) = sgf_moves.get_setup_and_moves(sgf_game) except ValueError as e: raise StandardError(str(e)) self.initial_board = gomill_board.board self.plays = plays self._winner = sgf_game.get_winner() if sgf_filepath[-5:] == "1.sgf": self.win = True else: self.win = False
def build_popularity_boards(self, games_to_load = -1, base_path = "/home/birdmw/Desktop/final_project/"): self.popularity_boards = [] for i in range(362): self.popularity_boards.append([0]*len(self.columns)) path_list = self.build_recursive_dir_tree(base_path) for path in path_list[:games_to_load]: try: with open(path) as p: game_string = p.read() sgf_game = sgf.Sgf_game.from_string(game_string) board = sgf_moves.get_setup_and_moves(sgf_game, Board(sgf_game.get_size())) if board[1][0][0] == 'b': # no handicap for i in range(len(board[1])): location = board[1][i][1] if location != None: npb_index = self.location_to_npboard_index(location) self.popularity_boards[i][ npb_index ] += 1 else: os.remove(path) except: os.remove(path) for pb in self.popularity_boards: sumVal = sum(pb) for loc in range(len(pb)): pb[loc] = round(pb[loc] / float(sumVal),3) self.popularity_boards = np.array(self.popularity_boards) pickle.dump( self.popularity_boards, open( "popularity_boards.pkl", "wb" ) ) print "==========COMPLETE=========" return self.popularity_boards
def game_to_move_examples(sgf_src): """Converts an SGF string to a generator of tuples. Each tuple is of the form (board_bitmap, (row, col)) or (board_bitmap, None). We get one such tuple for each move made in the game, where board_bitmap is the state of the board before the move is made. Here, the board_bitmap's channels are (player_to_move, opponent) """ sgf_game = sgf.Sgf_game.from_string(sgf_src) board, plays = sgf_moves.get_setup_and_moves(sgf_game) history = [] moves = [] for color, move in plays: bitmap = board_to_bitmap(board) if color == 'w': bitmap = np.flipud(bitmap) yield (bitmap, move) if move is not None: row, col = move board.play(row, col, color)
def load(self, sgf_string): """load the given SGF string.""" if not sgf_string: return self.sgf = sgf_string self.game = sgf.Sgf_game.from_string(sgf_string) self.board, _ = sgf_moves.get_setup_and_moves(self.game) self.node = self.root self.initial_nodes = self.get_descendants(self.node)
def show_sgf_file(pathname, move_number): f = open(pathname) sgf_src = f.read() f.close() try: sgf_game = sgf.Sgf_game.from_string(sgf_src) except ValueError: raise StandardError("bad sgf file") try: board, plays = sgf_moves.get_setup_and_moves(sgf_game) except ValueError, e: raise StandardError(str(e))
def test_get_setup_and_moves_board_provided(tc): b = boards.Board(9) g1 = sgf.Sgf_game.from_string(SAMPLE_SGF) board1, plays1 = sgf_moves.get_setup_and_moves(g1, b) tc.assertIs(board1, b) tc.assertBoardEqual(board1, DIAGRAM1) tc.assertEqual(plays1, [('b', (2, 3)), ('w', (3, 4)), ('b', None), ('w', None)]) tc.assertRaisesRegexp(ValueError, "board not empty", sgf_moves.get_setup_and_moves, g1, b) b2 = boards.Board(19) tc.assertRaisesRegexp(ValueError, "wrong board size, must be 9$", sgf_moves.get_setup_and_moves, g1, b2)
def test_get_setup_and_moves_move_in_root(tc): # A move in the root node is allowed (though deprecated) if there are no # setup stones. g1 = sgf.Sgf_game(size=9) root = g1.get_root() root.set("B", (1, 2)) node = g1.extend_main_sequence() node.set("W", (3, 4)) board1, plays1 = sgf_moves.get_setup_and_moves(g1) tc.assertTrue(board1.is_empty()) tc.assertEqual(plays1, [('b', (1, 2)), ('w', (3, 4))]) g2 = sgf.Sgf_game(size=9) root = g2.get_root() root.set("B", (1, 2)) root.set("AW", [(3, 3)]) node = g2.extend_main_sequence() node.set("W", (3, 4)) tc.assertRaisesRegexp(ValueError, "mixed setup and moves in root node", sgf_moves.get_setup_and_moves, g2)
def game_string_to_npboard(self, game_string, move_number): """Convert a game string into an npboard""" sgf_game = sgf.Sgf_game.from_string(game_string) properties = self.get_properties(game_string) properties = self.get_more_properties(properties, sgf_game) board = sgf_moves.get_setup_and_moves(sgf_game, Board(sgf_game.get_size())) npboard = None if board[1][0][0] == 'b': for move in board[1][:move_number]: color, coordinates = move x, y = coordinates board[0].play(x, y, color) board_locations = deepcopy(self.locations) for moves in board[0].list_occupied_points(): board_locations[moves[1]] = moves[0] npboard = [] for column in self.universal_columns[:6]: npboard.append(properties[column]) for column in self.universal_columns[6:]: npboard.append(board_locations[column]) return npboard
def show_sgf_file(pathname, move_number): """ Print the moves of the leftmost branch in the first game in the file. Arguments: pathname -- path of SGF file move_number -- optional move at which to stop printing moves """ file_handle = open(pathname) sgf_src = file_handle.read() file_handle.close() try: sgf_game = sgf.Sgf_game.from_string(sgf_src) handicap = sgf_game.get_handicap() except ValueError: raise StandardError("bad sgf file") try: _, plays = sgf_moves.get_setup_and_moves(sgf_game) except ValueError, err: raise StandardError(str(err))
def handle_loadsgf(self, args): try: pathname = args[0] except IndexError: gtp_engine.report_bad_arguments() if len(args) > 1: move_number = gtp_engine.interpret_int(args[1]) else: move_number = None # The GTP spec mandates the "cannot load file" error message, so we # can't be more helpful. try: s = self._load_file(pathname) except EnvironmentError: raise GtpError("cannot load file") try: sgf_game = sgf.Sgf_game.from_string(s) except ValueError: raise GtpError("cannot load file") new_size = sgf_game.get_size() if new_size not in self.acceptable_sizes: raise GtpError("unacceptable size") self.board_size = new_size try: komi = sgf_game.get_komi() except ValueError: raise GtpError("bad komi") try: handicap = sgf_game.get_handicap() except ValueError: # Handicap isn't important, so soldier on handicap = None try: sgf_board, plays = sgf_moves.get_setup_and_moves(sgf_game) except ValueError, e: raise GtpError(str(e))
if not ok: raise GCCException("%s rejected this board size (%ix%i)" % (bot_name, size, size)) bot.reset() log(1, "Checking for existing stones or handicap stones on the board") gameroot = sgf_g.get_root() if node_has(gameroot, "HA"): nb_handicap = node_get(gameroot, "HA") log(1, "The SGF indicates", nb_handicap, "stone(s)") else: nb_handicap = 0 log(1, "The SGF does not indicate handicap stone") # import pdb; pdb.set_trace() board, unused = sgf_moves.get_setup_and_moves(sgf_g) nb_occupied_points = len(board.list_occupied_points()) log(1, "The SGF indicates", nb_occupied_points, "occupied point(s)") free_handicap_black_stones_positions = [] already_played_black_stones_position = [] already_played_white_stones_position = [] for color, move in board.list_occupied_points(): if move != None: row, col = move move = ij2gtp((row, col)) if color.lower() == 'b': if nb_handicap > 0: free_handicap_black_stones_positions.append(move) nb_handicap -= 1
def display_move(self, move=1): self.frame = 0 dim = self.dim goban = self.goban self.move_number.config(text=str(move) + '/' + str(get_node_number(self.gameroot))) print "========================" print "displaying move", move grid = [[0 for row in range(dim)] for col in range(dim)] markup = [["" for row in range(dim)] for col in range(dim)] network = [[0 for row in range(dim)] for col in range(dim)] links = [0] * 2 * dim * dim board, _ = sgf_moves.get_setup_and_moves(self.sgf) for colour, move0 in board.list_occupied_points(): if move0 is None: continue row, col = move0 if colour == 'b': place(grid, row, col, 1) else: place(grid, row, col, 2) m = 0 for m in range(1, move + 1): one_move = get_node(self.gameroot, m) #if one_move==False: # print "(0)leaving because one_move==False" # return if one_move != False: ij = one_move.get_move()[1] if ij == None: print "(0)skipping because ij==None", ij continue if one_move.get_move()[0] == 'b': color = 1 else: color = 2 i, j = ij place(grid, i, j, color) if len(one_move) == 0: print "(0)leaving because len(one_move)==0" goban.display(grid, markup, network, links) self.grid = grid self.markup = markup self.network = network return #indicating last play with delta try: if m > 0: place(grid, i, j, color) markup[i][j] = 0 except: print "no move on goban?" goban.display(grid, markup, network, links) self.grid = grid self.markup = markup self.network = network self.links = links
def initialize(self): self sgf = self.sgf komi = self.sgf.get_komi() gameroot = self.sgf.get_root() self.popup = Toplevel() popup = self.popup dim = self.dim move = self.move popup.configure(background=bg) self.locked = False panel = Frame(popup) panel.configure(background=bg) #Button(panel, text='undo',command=lambda :click_on_undo(self)).grid(column=0,row=1) Button(panel, text='undo', command=self.undo).grid(column=0, row=1) Button(panel, text=' Color ', command=self.color_map).grid(column=0, row=2) Button(panel, text='Shadow ', command=self.shadow_map).grid(column=0, row=4) Button(panel, text='Export', command=self.save_as_ps).grid(column=0, row=5) panel.grid(column=0, row=1, sticky=N) goban3 = Goban(dim, master=popup, width=10, height=10, bg=bg, bd=0, borderwidth=0) goban3.space = self.goban_size / (dim + 1 + 1) goban3.grid(column=1, row=1) grid3 = [[0 for row in range(dim)] for col in range(dim)] markup3 = [["" for row in range(dim)] for col in range(dim)] network3 = [[0 for row in range(dim)] for col in range(dim)] links3 = [0] * 2 * dim * dim print "========================" print "opening move", move board, _ = sgf_moves.get_setup_and_moves(self.sgf) for colour, move0 in board.list_occupied_points(): if move0 is None: continue row, col = move0 if colour == 'b': place(grid3, row, col, 1) else: place(grid3, row, col, 2) m = 0 for m in range(1, move): one_move = get_node(gameroot, m) #if one_move==False: # print "(0)leaving because one_move==False" # return if one_move != False: ij = one_move.get_move()[1] print ij if one_move.get_move()[0] == 'b': color = 1 else: color = 2 if ij == None: print "(0)skipping because ij==None", ij continue i, j = ij place(grid3, i, j, color) try: if m > 0: markup3[i][j] = 0 except: print "No move on goban?" try: if get_node(gameroot, move).get_move()[0].lower() == "w": self.next_color = 2 else: self.next_color = 1 except: print "error when trying to figure out next color to play, so black is selected" self.next_color = 1 goban3.display(grid3, markup3, network3, links3) self.goban = goban3 self.grid = grid3 self.markup = markup3 self.network = network3 self.links = links3 popup.protocol("WM_DELETE_WINDOW", self.close) goban3.bind("<Button-1>", self.click) goban3.bind("<Button-2>", self.undo) goban3.bind("<Button-3>", lambda event: click_on_undo(popup)) self.history = []
def preprocess_sgf(sgf_filename): """ Takes an .sgf file and creates three numpy arrays. Every boardstate is partitioned into the pieces of the player to play and the player who just played. These create the first two numpy arrays. The third numpy array is simply the sequence of resulting moves given a boardstate. """ # retrieve the raw data with open(sgf_filename) as f: raw_sgf = f.read() # load the game into the sgf game object game = sgf.Sgf_game.from_string(raw_sgf) assert game.get_size() == BOARDSIZE # retrieve the initial board setup and the sequence of moves for the game (init_board, moves) = sgf_moves.get_setup_and_moves(game) main_seq = [node.get_move() for node in game.get_main_sequence()] # assume the loaded data structure has (None, None) as the first move # in the main sequence assert main_seq[0] == (None, None) main_seq = main_seq[1:] # if the game ended with two passes, remove them. we won't consider them # for move prediction if (main_seq[-1][1] is None) and (main_seq[-2][1] is None): main_seq = main_seq[:len(main_seq) - 2] # assert that no other moves are passes -- this is a good assumption but # we can double check for the moment for move in main_seq: assert move[1] is not None # intitialize a 3D numpy array to keep track of all the games depth = len(main_seq) G = np.empty((depth, BOARDSIZE, BOARDSIZE), dtype=int) G[0] = make_board_arr(init_board.list_occupied_points()) # contains board class instances for each state throughout the game states_list = [init_board] # populate the 3D array of game states via states_list for i, move in enumerate(main_seq): if i == depth - 1: break new_state = copy.deepcopy(states_list[-1]) new_state.play(move[1][0], move[1][1], move[0]) G[i + 1] = make_board_arr(new_state.list_occupied_points()) states_list.append(new_state) assert len(states_list) == len(main_seq) # sanity check # parition all the board states to create the first two arrays, then # create the third array (curr_arr, prev_arr) = partition_board_states(G, main_seq, depth) move_arr = make_move_arr(main_seq, depth) # create filenames to save the processed arrays sgf_file_prefix = os.path.splitext(sgf_filename)[0] full_filename = './processed/' + sgf_file_prefix + '_full.npy' # complete states curr_filename = './processed/' + sgf_file_prefix + '_curr.npy' # to move prev_filename = './processed/' + sgf_file_prefix + '_prev.npy' # just moved move_filename = './processed/' + sgf_file_prefix + '_move.npy' # resulting moves # create a directory for the processed arrays newpath = r'./processed' if not os.path.exists(newpath): os.makedirs(newpath) # save the arrays np.save(curr_filename, fix_imports=True, arr=curr_arr) np.save(prev_filename, fix_imports=True, arr=prev_arr) np.save(move_filename, fix_imports=True, arr=move_arr) return