def test_leaf_node(self): game_state = _get_game_state_with_one_card_left() play_jack_clubs = PlayCardAction(PlayerId.ONE, Card(Suit.CLUBS, CardValue.JACK)) game_state = play_jack_clubs.execute(game_state) mcts = Mcts(PlayerId.TWO) root_node = mcts.build_tree(game_state) self.assertIsNone(root_node.parent) self.assertEqual(1, len(root_node.children)) self.assertEqual([], root_node.untried_actions) self.assertTrue(root_node.fully_expanded) self.assertFalse(root_node.terminal) self.assertEqual(PlayerId.TWO, root_node.player) self.assertFalse(root_node.fully_simulated) action = list(root_node.children.keys())[0] self.assertEqual( PlayCardAction(PlayerId.TWO, Card(Suit.SPADES, CardValue.JACK)), action) leaf: Node = root_node.children[action] self.assertIs(root_node, leaf.parent) self.assertIsNone(leaf.children) self.assertIsNone(leaf.untried_actions) self.assertTrue(leaf.fully_expanded) self.assertTrue(leaf.terminal) self.assertEqual(PlayerId.ONE, leaf.player) self.assertAlmostEqual(0.33, leaf.ucb, delta=0.01) self.assertTrue(leaf.fully_simulated)
def test_who_laughs_last_part_two_player_one_always_wins(self): game_state = get_game_state_for_who_laughs_last_puzzle() mcts = Mcts(PlayerId.ONE) root_node = mcts.build_tree(game_state) actions = root_node.best_actions() self.assertEqual( [PlayCardAction(PlayerId.ONE, Card(Suit.HEARTS, CardValue.KING))], actions) game_state = actions[0].execute(game_state) self.assertEqual(PlayerPair(19, 26), game_state.trick_points) self._assert_player_one_always_wins(game_state)
def _assert_player_one_always_wins(self, game_state: GameState): while not game_state.is_game_over: mcts = Mcts(game_state.next_player) root_node = mcts.build_tree(game_state) print() for action, child in root_node.children.items(): print(action, child) self.assertTrue(child.fully_simulated, msg=action) best_action = random.choice(root_node.best_actions()) print(f"{game_state.next_player}: {best_action}") game_state = best_action.execute(game_state) self.assertEqual(0, game_state.game_points.two)
def test_elimination_play_fully_simulated_tree(self): # TODO(tests): Maybe do this for more game states that can be fully # simulated. game_state = get_game_state_for_elimination_play_puzzle() mcts = Mcts(game_state.next_player) root_node = mcts.build_tree(game_state) golden_data_file = os.path.join(os.path.dirname(__file__), "test_data", "elimination_play_tree.pickle") # Uncomment this to save a golden version of the tree: # with open(golden_data_file, "wb") as output_file: # pickle.dump(root_node, output_file) with open(golden_data_file, "rb") as input_file: expected_tree = pickle.load(input_file) self._assert_trees_equal(expected_tree, root_node)
def test_elimination_play_player_one(self): game_state = get_game_state_for_elimination_play_puzzle() mcts = Mcts(PlayerId.ONE) root_node = mcts.build_tree(game_state) for action, child in root_node.children.items(): print(action, child) for action, child in root_node.children.items(): self.assertTrue(child.fully_simulated) self.assertEqual(PlayerId.TWO, child.player) self.assertAlmostEqual( 0.33 if action.card.suit == Suit.HEARTS else -0.33, child.ucb, delta=0.01, msg=action)
def test_elimination_play_player_two(self): game_state = get_game_state_for_elimination_play_puzzle() action = PlayCardAction(PlayerId.ONE, Card(Suit.CLUBS, CardValue.JACK)) game_state = action.execute(game_state) action = PlayCardAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.KING)) game_state = action.execute(game_state) self.assertEqual(34, game_state.trick_points.one) self.assertEqual(40, game_state.trick_points.two) mcts = Mcts(PlayerId.TWO) root_node = mcts.build_tree(game_state) for action, child in root_node.children.items(): print(action, child) for action, child in root_node.children.items(): self.assertTrue(child.fully_simulated) self.assertEqual(PlayerId.ONE, child.player) self.assertAlmostEqual(0.33, child.ucb, delta=0.01, msg=action)
def test_one_card_left_for_each_player(self): game_state = _get_game_state_with_one_card_left() mcts = Mcts(PlayerId.ONE) root_node = mcts.build_tree(game_state) self.assertIsNone(root_node.parent) self.assertEqual(1, len(root_node.children)) self.assertEqual([], root_node.untried_actions) self.assertTrue(root_node.fully_expanded) self.assertFalse(root_node.terminal) self.assertEqual(PlayerId.ONE, root_node.player) self.assertFalse(root_node.fully_simulated) action = list(root_node.children.keys())[0] self.assertEqual( PlayCardAction(PlayerId.ONE, Card(Suit.CLUBS, CardValue.JACK)), action) player_two_node: Node = root_node.children[action] print(str(player_two_node)) self.assertIs(root_node, player_two_node.parent) self.assertEqual(1, len(player_two_node.children)) self.assertEqual([], player_two_node.untried_actions) self.assertTrue(player_two_node.fully_expanded) self.assertFalse(player_two_node.terminal) self.assertEqual(PlayerId.TWO, player_two_node.player) self.assertAlmostEqual(-0.33, player_two_node.ucb, delta=0.01) self.assertTrue(player_two_node.fully_simulated) action = list(player_two_node.children.keys())[0] self.assertEqual( PlayCardAction(PlayerId.TWO, Card(Suit.SPADES, CardValue.JACK)), action) leaf: Node = player_two_node.children[action] self.assertIs(player_two_node, leaf.parent) self.assertIsNone(leaf.children) self.assertIsNone(leaf.untried_actions) self.assertTrue(leaf.fully_expanded) self.assertTrue(leaf.terminal) self.assertEqual(PlayerId.ONE, leaf.player) self.assertAlmostEqual(0.33, leaf.ucb, delta=0.01) self.assertTrue(leaf.fully_simulated)
def test_you_first_no_you_first(self): game_state = get_game_state_for_you_first_no_you_first_puzzle() mcts = Mcts(PlayerId.ONE) root_node = mcts.build_tree(game_state) self.assertIsNone(root_node.parent) self.assertEqual(5, len(root_node.children)) self.assertEqual([], root_node.untried_actions) self.assertTrue(root_node.fully_expanded) self.assertFalse(root_node.terminal) self.assertEqual(PlayerId.ONE, root_node.player) self.assertFalse(root_node.fully_simulated) for action, child in root_node.children.items(): print(action, child) for action, child in root_node.children.items(): self.assertTrue(child.fully_simulated) self.assertEqual(PlayerId.TWO, child.player) self.assertAlmostEqual( 0.33 if action.card.suit == Suit.HEARTS else -0.33, child.ucb, delta=0.01, msg=action)
def test_fully_expanded_tree(self): mcts = Mcts(PlayerId.ONE, _TestNode) root_node = mcts.build_tree(0) nodes = [root_node] index = 0 while index < len(nodes): node = nodes[index] if node.children is not None: actions = list(sorted(node.children.keys())) for action in actions: child = node.children[action] nodes.append(child) self.assertEqual(node, child.parent) index += 1 self.assertEqual(10, len(nodes)) self.assertEqual([(2, 6), (1, 3), (1, 2), (1, 2)], [(node.q, node.n) for node in nodes if not node.terminal]) self.assertEqual([1, 0, 1, 0, 1, 0, 1, 0, 1], [node.ucb for node in nodes[1:]]) for node in nodes: if node != root_node: self.assertTrue(node.fully_expanded, msg=node) self.assertTrue(node.fully_simulated, msg=node)