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))
Exemple #3
0
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