def _minigui_report_position(self): root = self._player.get_root() position = root.position board = [] for row in range(go.N): for col in range(go.N): stone = position.board[row, col] if stone == go.BLACK: board.append("X") elif stone == go.WHITE: board.append("O") else: board.append(".") msg = { "id": hex(id(root)), "toPlay": "B" if position.to_play == 1 else "W", "moveNum": position.n, "stones": "".join(board), "gameOver": position.is_game_over(), "caps": position.caps, } if root.parent and root.parent.parent: msg["parentId"] = hex(id(root.parent)) msg["q"] = float(root.parent.Q) if position.recent: msg["move"] = coords.to_gtp(position.recent[-1].move) dbg("mg-position:%s" % json.dumps(msg, sort_keys=True))
def _minigui_report_search_status(self, leaves): """Prints the current MCTS search status to stderr. Reports the current search path, root node's child_Q, root node's child_N, the most visited path in a format that can be parsed by one of the STDERR_HANDLERS in minigui.ts. Args: leaves: list of leaf MCTSNodes returned by tree_search(). """ root = self._player.get_root() msg = { "id": hex(id(root)), "n": int(root.N), "q": float(root.Q), } msg["childQ"] = [int(round(q * 1000)) for q in root.child_Q] msg["childN"] = [int(n) for n in root.child_N] ranked_children = root.rank_children() variations = {} for i in ranked_children[:15]: if root.child_N[i] == 0 or i not in root.children: break c = coords.to_gtp(coords.from_flat(i)) child = root.children[i] nodes = child.most_visited_path_nodes() moves = [coords.to_gtp(coords.from_flat(m.fmove)) for m in nodes] variations[c] = { "n": int(root.child_N[i]), "q": float(root.child_Q[i]), "moves": [c] + moves, } if leaves: path = [] leaf = leaves[0] while leaf != root: path.append(leaf.fmove) leaf = leaf.parent if path: path.reverse() variations["live"] = { "n": int(root.child_N[path[0]]), "q": float(root.child_Q[path[0]]), "moves": [coords.to_gtp(coords.from_flat(m)) for m in path] } if variations: msg["variations"] = variations dbg("mg-update:%s" % json.dumps(msg, sort_keys=True))
def main(argv): """Run Minigo in GTP mode.""" del argv engine = make_gtp_instance(FLAGS.load_file, cgos_mode=FLAGS.cgos_mode, kgs_mode=FLAGS.kgs_mode, minigui_mode=FLAGS.minigui_mode) dbg('GTP engine ready\n') for msg in sys.stdin: if not engine.handle_msg(msg.strip()): break
def cmd_spin(self): for _ in range(50): for _ in range(100): self._player.tree_search() moves = self.cmd_nextplay().lower() moves = moves.split() root = self._player.get_root() colors = "bw" if root.position.to_play is go.BLACK else "wb" moves_cols = " ".join([ "{} {}".format(*z) for z in zip(itertools.cycle(colors), moves) ]) dbg("gogui-gfx: TEXT", "{:.3f} after {}".format(root.Q, root.N)) dbg("gogui-gfx: VAR", moves_cols) return self.cmd_nextplay()
def cmd_clear_board(self): position = self._player.get_position() if (self._player.get_result_string() and position and len(position.recent) > 1): try: sgf = self._player.to_sgf() with open( datetime.datetime.now().strftime("%Y-%m-%d-%H:%M.sgf"), "w") as f: f.write(sgf) except NotImplementedError: pass except: dbg("Error saving sgf") self._player.initialize_game(go.Position(komi=self._komi))
def cmd_loadsgf(self, filename, movenum=0): try: with open(filename, "r") as f: contents = f.read() except: raise ValueError("Unreadable file: " + filename) # Clear the board before replaying sgf # should this use the sgfs komi? self._player.initialize_game(go.Position()) # This is kinda bad, because replay_sgf is already calling # 'play move' on its internal position objects, but we really # want to advance the engine along with us rather than try to # push in some finished Position object. for idx, p in enumerate(sgf_wrapper.replay_sgf(contents)): dbg("playing #", idx, p.next_move) self._player.play_move(p.next_move) if movenum and idx == movenum: break
def cmd_genmove(self, color=None): start = time.time() result = super().cmd_genmove(color) duration = time.time() - start root = self._player.get_root() if result != "resign": dbg("") dbg(root.position.__str__(colors=False)) dbg("%d readouts, %.3f s/100. (%.2f sec)" % (self._player.get_num_readouts(), duration / self._player.get_num_readouts() * 100.0, duration)) dbg("") if root.is_done(): self._player.set_result(root.position.result(), was_resign=False) self._minigui_report_position() return result
def cmd_showboard(self): dbg("\n\n" + str(self._player.get_position()) + "\n\n") return True
def play(network): """Plays out a self-play match, returning a MCTSPlayer object containing. - the final position - the n x 362 tensor of floats representing the mcts search probabilities - the n-ary tensor of floats representing the original value-net estimate where n is the number of moves in the game """ readouts = FLAGS.num_readouts # defined in strategies.py # Disable resign in 5% of games if random.random() < FLAGS.resign_disable_pct: resign_threshold = -1.0 else: resign_threshold = None player = MCTSPlayer(network, resign_threshold=resign_threshold) player.initialize_game() # Must run this once at the start to expand the root node. first_node = player.root.select_leaf() prob, val = network.run(first_node.position) first_node.incorporate_results(prob, val, first_node) while True: start = time.time() player.root.inject_noise() current_readouts = player.root.N # we want to do "X additional readouts", rather than "up to X readouts". while player.root.N < current_readouts + readouts: player.tree_search() if FLAGS.verbose >= 3: print(player.root.position) print(player.root.describe()) if player.should_resign(): player.set_result(-1 * player.root.position.to_play, was_resign=True) break move = player.pick_move() player.play_move(move) if player.root.is_done(): player.set_result(player.root.position.result(), was_resign=False) break if (FLAGS.verbose >= 2) or (FLAGS.verbose >= 1 and player.root.position.n % 10 == 9): print('Q: {:.5f}'.format(player.root.Q)) dur = time.time() - start print('%d: %d readouts, %.3f s/100. (%.2f sec)' % (player.root.position.n, readouts, dur / readouts * 100.0, dur)) if FLAGS.verbose >= 3: print('Played >>', coords.to_gtp(coords.from_flat(player.root.fmove))) if FLAGS.verbose >= 2: utils.dbg('%s: %.3f' % (player.result_string, player.root.Q)) utils.dbg(player.root.position, player.root.position.score()) return player