Exemple #1
0
def start_board():
    """
    """
    gs = GameState(size=7)
    gs.do_move((1, 1))
    gs.do_move((2, 2))
    return gs
Exemple #2
0
def _sgf_init_gamestate(sgf_root):
    """
       Helper function to set up a GameState object from the root node
       of an SGF file
    """

    props = sgf_root.properties
    s_size = int(props.get('SZ', ['19'])[0])
    s_player = props.get('PL', ['B'])[0]
    # init board with specified size
    gs = GameState(size=s_size)
    # handle 'add black' property
    if 'AB' in props:
        for stone in props['AB']:
            gs.place_handicap_stone(_parse_sgf_move(stone), go.BLACK)
    # handle 'add white' property
    if 'AW' in props:
        for stone in props['AW']:
            gs.place_handicap_stone(_parse_sgf_move(stone), go.WHITE)
    # setup done; set player according to 'PL' property
    gs.current_player = go.BLACK if s_player == 'B' else go.WHITE
    return gs
Exemple #3
0
 def setUp(self):
     self.gs = GameState()
     self.mcts = MCTSearch(policy_value_generator(random_policy,
                                                  zero_value),
                           config,
                           max_playout=1)
Exemple #4
0
class TestMCTS(unittest.TestCase):
    def setUp(self):
        self.gs = GameState()
        self.mcts = MCTSearch(policy_value_generator(random_policy,
                                                     zero_value),
                              config,
                              max_playout=1)

    def _tree_traversal_helper(self, node):
        if node._children != {}:
            expansions = 1
        else:
            return 0
        for action, _ in sorted(random_policy(self.gs),
                                key=itemgetter(1),
                                reverse=True):
            if action in node._children:
                expansions += self._tree_traversal_helper(
                    node._children[action])
        return expansions

    def _count_expansions(self):
        """Helper function to count the number of expansions past the root using the dummy policy
        """
        node = self.mcts._root
        return self._tree_traversal_helper(node) - 1  # remove root node count

    def test_playout(self):
        for _ in range(8):
            self.mcts._playout(self.gs.copy(), self.mcts._root)
        # for i in range(19):
        #     for j in range(19):
        #         if self.mcts._root._children[(i, j)].visit_count >= 1:
        #             print((i, j), self.mcts._root._children[(i, j)].visit_count)
        self.mcts._playout(self.gs.copy(), self.mcts._root)
        # Assert that the most likely child was visited (according to the dummy policy below).
        self.assertEqual(1, self.mcts._root._children[(18, 18)].visit_count)
        # Assert that the search depth expanded nodes 8 times.
        self.assertEqual(8, self._count_expansions())

    # def test_playout_with_pass(self):
    #     # Test that playout handles the end of the game (i.e. passing/no moves). Mock this by
    #     # creating a policy that returns nothing after 4 moves.
    #     def stop_early_policy(state):
    #         if state.turns <= 4:
    #             return random_policy(state)
    #         else:
    #             return []
    #
    #     self.mcts = MCTSearch(policy_value_generator(stop_early_policy, zero_value), config, max_playout=8)
    #     for _ in range(8):
    #         self.mcts._playout(self.gs.copy(), self.mcts._root)
    #     # Assert that (18, 18) and (18, 17) are still only visited once.
    #     self.assertEqual(1, self.mcts._root._children[(18, 18)].visit_count)
    #     # Assert that no expansions happened after reaching the "end" in 4 moves.
    #     self.assertEqual(5, self._count_expansions())

    def test_get_move(self):
        move = self.mcts.calc_move(self.gs)
        self.mcts.update_with_move(move)
        # success if no errors

    def test_update_with_move(self):
        move = self.mcts.calc_move(self.gs)
        self.gs.do_move(move)
        self.mcts.update_with_move(move)
        # Assert that the new root still has children.
        self.assertTrue(len(self.mcts._root._children) > 0)
        # Assert that the new root has no parent (the rest of the tree will be garbage collected).
        self.assertIsNone(self.mcts._root._parent)
        # Assert that the next best move according to the root is (18, 17), according to the
        # dummy policy below.
        self.assertEqual((18, 18), move)
        self.assertEqual((18, 17), self.mcts._root.select()[0])
Exemple #5
0
 def setUp(self):
     self.gs = GameState()
     self.node = MCTreeNode(None, 1.0)
def simple_board():
    """

    """
    gs = GameState(size=7)

    # make a tiny board for the sake of testing and hand-coding expected results
    #
    #         X
    #   0 1 2 3 4 5 6
    #   B W . . . . . 0
    #   B W . . . . . 1
    #   B . . . B . . 2
    # Y . . . B k B . 3
    #   . . . W B W . 4
    #   . . . . W . . 5
    #   . . . . . . . 6
    #
    # where k is a ko position (white was just captured)

    # ladder-looking thing in the top-left
    gs.do_move((0, 0))  # B
    gs.do_move((1, 0))  # W
    gs.do_move((0, 1))  # B
    gs.do_move((1, 1))  # W
    gs.do_move((0, 2))  # B

    # ko position in the middle
    gs.do_move((3, 4))  # W
    gs.do_move((3, 3))  # B
    gs.do_move((4, 5))  # W
    gs.do_move((4, 2))  # B
    gs.do_move((5, 4))  # W
    gs.do_move((5, 3))  # B
    gs.do_move((4, 3))  # W - the ko position
    gs.do_move((4, 4))  # B - does the capture

    return gs
Exemple #7
0
    def play(self, save_path, save_filename, is_selfplay=False):
        """ Plays the game and saves to a sgf file.
        """

        mcts1 = MCTSearch(random_state_transform,
                          lambda s: self.player1.response([s]))
        mcts2 = MCTSearch(random_state_transform,
                          lambda s: self.player2.response([s]))
        mcts = [mcts1, mcts2]
        gs = GameState(size=self.board_size)

        # Randomly assign colors
        player1_is_black = random.randint(0, 1) == 0
        # player 1 refers to mcts[0]
        if player1_is_black:
            current_player = 0
        else:
            current_player = 1

        # Create a list to store search probabilities for self-play
        # if is_selfplay is not necessary, creating a list won't have side effects
        search_probs_history = []

        # Play the game
        for turn in range(self.max_moves):
            # Whether to enable exploration depends on the mode,
            # exploration is only enabled in the first 30 turns in a self-play
            if is_selfplay and turn + 1 <= 30:
                dirichlet = True
            else:
                dirichlet = False

            # Record search probabilities for self-play
            if is_selfplay:
                move, search_probs = mcts[current_player].calc_move_with_probs(
                    gs, dirichlet)
                search_probs_history.append(search_probs)
            else:
                move = mcts[current_player].calc_move(gs, dirichlet)

            # Make the move and update both player's search tree
            # TODO: Should we use a single search tree for self-play?
            gs.do_move(move)
            for p in range(2):
                mcts[p].update_with_move(gs)

            # Toggle player
            current_player = 1 - current_player

            # Check if the game ends
            if gs.is_end_of_game:
                break

        # Game ends
        result = gs.get_winner()
        # TODO: Detailed result info, i.e. W+Resign
        if result is WHITE:
            result_string = "W+"
        elif result is BLACK:
            result_string = "B+"
        else:
            # TODO: How should we deal with ties? discarding ties for now
            return 0
        save_gamestate_to_sgf(gs,
                              save_path,
                              save_filename + '.sgf',
                              result=result_string)

        # Return an extra list of search probabilities in the same order, other features can be extracted in sgf
        # search_probs_history is a list of a list of (action, probs)
        if is_selfplay:
            return player1_is_black, result, search_probs_history
        else:
            return player1_is_black, result
Exemple #8
0
def empty_board():
    """
    """
    gs = GameState(size=7)
    return gs