Beispiel #1
0
    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)
Beispiel #2
0
    def _on_lead_do_not_follow_suit(self,
                                    game_view: GameState) -> PlayerAction:
        # If the cards that cannot be won by the opponent can get us to the end,
        # start playing them.
        action = self._play_winning_cards(game_view)
        if action is not None:
            return action

        # If we cannot win yet, and we have a marriage, announce it. If the Ace and
        # Ten from that suit cannot be in the opponents hand, play the King.
        if self._marriage_suit is not None:
            logging.debug("HeuristicPlayer: Announcing marriage for %s",
                          self._marriage_suit)
            king = Card(self._marriage_suit, CardValue.KING)
            ten = Card(self._marriage_suit, CardValue.TEN)
            ace = Card(self._marriage_suit, CardValue.ACE)
            if (ten in self._my_cards or ten in self._played_cards) and \
                (ace in self._my_cards or ace in self._played_cards):
                return AnnounceMarriageAction(self.id, king)
            return AnnounceMarriageAction(self.id, king.marriage_pair)

        # If we expect that the opponent has more trumps and we have big cards
        # (i.e., tens or aces), play one of the high card to force the opponent to
        # either play a trump or give up a lot of points.
        card = self._maybe_trump_control(game_view)
        if card is not None:
            return PlayCardAction(self.id, card)

        # Discard one of the small cards.
        card = self._best_discard(game_view)
        logging.debug("HeuristicPlayer: Discarding %s", card)
        return PlayCardAction(self.id, card)
  def test_actions_after_the_opponent_played_one_card_talon_is_empty(self):
    game_state = get_game_state_with_empty_talon_for_tests()
    action = PlayCardAction(PlayerId.ONE, Card(Suit.SPADES, CardValue.TEN))
    game_state = action.execute(game_state)

    actions = get_available_actions(game_state)
    self.assertEqual(set(actions),
                     set(get_available_actions(game_state.next_player_view())))
    expected_actions = [
      PlayCardAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.KING)),
      PlayCardAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.JACK)),
      PlayCardAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.QUEEN)),
    ]
    self.assertSetEqual(set(expected_actions), set(actions))

    game_state = get_game_state_with_empty_talon_for_tests()
    with GameStateValidator(game_state):
      game_state.next_player = PlayerId.TWO
    action = PlayCardAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.JACK))
    game_state = action.execute(game_state)

    actions = get_available_actions(game_state)
    self.assertEqual(set(actions),
                     set(get_available_actions(game_state.next_player_view())))
    expected_actions = [
      PlayCardAction(PlayerId.ONE, Card(Suit.CLUBS, CardValue.ACE)),
    ]
    self.assertSetEqual(set(expected_actions), set(actions))
 def test_duck_puzzle(self):
     game_view = get_game_view_for_duck_puzzle()
     action = self._mcts_player.request_next_action(game_view)
     print(f"Selected action: {action}")
     expected_actions = {
         PlayCardAction(PlayerId.ONE, Card(Suit.SPADES, CardValue.ACE)),
         PlayCardAction(PlayerId.ONE, Card(Suit.SPADES, CardValue.TEN))
     }
     self.assertIn(action, expected_actions)
Beispiel #5
0
 def test_no_marriage_available(self):
   self.assertIsNone(get_best_marriage(
     [
       PlayCardAction(PlayerId.ONE, Card.from_string("jh")),
       PlayCardAction(PlayerId.ONE, Card.from_string("ad")),
       PlayCardAction(PlayerId.ONE, Card.from_string("js")),
       PlayCardAction(PlayerId.ONE, Card.from_string("ts")),
       PlayCardAction(PlayerId.ONE, Card.from_string("qc")),
     ], Suit.SPADES))
  def test_must_follow_suit_must_use_higher_trump(self):
    """
    Player.ONE plays the trump Queen. Player.TWO has three trump cards.
    The valid cards are only the trump King and Ace.
    """
    game_state = get_game_state_with_empty_talon_for_tests()

    with GameStateValidator(game_state):
      ace_clubs = game_state.cards_in_hand.one[0]
      queen_clubs = game_state.cards_in_hand.two[3]
      game_state.cards_in_hand.two[3] = ace_clubs
      game_state.cards_in_hand.one[0] = queen_clubs

    action = PlayCardAction(PlayerId.ONE, queen_clubs)
    self.assertTrue(action.can_execute_on(game_state))
    game_state = action.execute(game_state)
    num_legal_cards = 0
    valid_cards = [Card(Suit.CLUBS, CardValue.KING),
                   Card(Suit.CLUBS, CardValue.ACE)]
    for card in game_state.cards_in_hand[PlayerId.TWO]:
      action = PlayCardAction(PlayerId.TWO, card)
      is_legal_card = action.can_execute_on(game_state)
      self.assertEqual(card in valid_cards, is_legal_card, msg=f"{card}")
      self.assertEqual(is_legal_card,
                       action.can_execute_on(game_state.next_player_view()))
      if is_legal_card:
        num_legal_cards += 1
    self.assertEqual(2, num_legal_cards)
  def test_must_follow_suit_can_play_any_higher_card_same_suit(self):
    """
    Player.ONE has two cards of the same suit as the card played by Player.TWO,
    both higher. Player.ONE also has a trump card. Any of the two cards from the
    same suit as the card played by Player.TWO are valid.
    """
    game_state = get_game_state_for_tests()

    with GameStateValidator(game_state):
      queen_hearts = game_state.cards_in_hand.one[0]
      queen_clubs = game_state.cards_in_hand.two[4]
      game_state.cards_in_hand.two[4] = queen_hearts
      game_state.cards_in_hand.one[0] = queen_clubs
      game_state.close_talon()
      game_state.next_player = PlayerId.TWO

    self.assertTrue(game_state.must_follow_suit())
    jack_spades = Card(Suit.SPADES, CardValue.JACK)
    action = PlayCardAction(PlayerId.TWO, jack_spades)
    self.assertTrue(action.can_execute_on(game_state))
    game_state = action.execute(game_state)
    num_legal_cards = 0
    for card in game_state.cards_in_hand[PlayerId.ONE]:
      action = PlayCardAction(PlayerId.ONE, card)
      is_legal_card = action.can_execute_on(game_state)
      self.assertEqual(card.suit == Suit.SPADES, is_legal_card, msg=f"{card}")
      self.assertEqual(is_legal_card,
                       action.can_execute_on(game_state.next_player_view()))
      if is_legal_card:
        num_legal_cards += 1
    self.assertEqual(2, num_legal_cards)
 def test_play_trick_talon_closed_opponent_cannot_follow_suit_or_trump(self):
   game_state = get_game_state_for_tests()
   with GameStateValidator(game_state):
     trick = game_state.won_tricks.one.pop(0)
     game_state.talon.append(trick.one)
     game_state.talon.append(trick.two)
     game_state.trick_points.one -= trick.one.card_value
     game_state.trick_points.one -= trick.two.card_value
     trick = game_state.won_tricks.two.pop(-1)
     game_state.talon.append(trick.one)
     game_state.talon.append(trick.two)
     game_state.trick_points.two -= trick.one.card_value
     game_state.trick_points.two -= trick.two.card_value
     game_state.next_player = PlayerId.TWO
   game_state.close_talon()
   self.assertEqual([False, False, False, False, False],
                    [card.public for card in game_state.talon])
   action = PlayCardAction(PlayerId.TWO, Card(Suit.DIAMONDS, CardValue.QUEEN))
   self.assertTrue(action.can_execute_on(game_state))
   game_state = action.execute(game_state)
   self.assertEqual([False, False, False, False, False],
                    [card.public for card in game_state.talon])
   action = PlayCardAction(PlayerId.ONE, Card(Suit.HEARTS, CardValue.QUEEN))
   self.assertTrue(action.can_execute_on(game_state))
   game_state = action.execute(game_state)
   self.assertEqual([True, False, False, True, True],
                    [card.public for card in game_state.talon])
Beispiel #9
0
 def _not_on_lead_action(self, game_view: GameState) -> PlayerAction:
     if game_view.must_follow_suit():
         card = self._not_on_lead_follow_suit(game_view)
     else:
         card = self._not_on_lead_do_not_follow_suit(game_view)
     logging.debug("HeuristicPlayer: Playing %s", card)
     return PlayCardAction(self.id, card)
Beispiel #10
0
 def test_save_marriages(self):
   self._run_test_cases_with_option("save_marriages", [False, True], [
     # Do not break a marriage to win a Jack.
     {
       "cards_in_hand": (["qd", "kd", "ad", "js", "qs"],
                         [None, None, None, None, None]),
       "trump": Suit.CLUBS,
       "trump_card": "ac",
       "talon": [None, None, None, None, None, None, None, None, None],
       "current_trick": (None, "jd"),
       "expected_action": [
         PlayCardAction(PlayerId.ONE, Card.from_string("kd")),
         PlayCardAction(PlayerId.ONE, Card.from_string("js")),
       ]
     },
   ])
Beispiel #11
0
 def test_trump_marriage_is_preferred(self):
   self.assertIn(get_best_marriage(
     [
       PlayCardAction(PlayerId.ONE, Card.from_string("jh")),
       PlayCardAction(PlayerId.ONE, Card.from_string("ad")),
       PlayCardAction(PlayerId.ONE, Card.from_string("js")),
       PlayCardAction(PlayerId.ONE, Card.from_string("ts")),
       PlayCardAction(PlayerId.ONE, Card.from_string("qc")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("kh")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("qh")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("ks")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("qs")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("kc")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("qc")),
     ], Suit.SPADES),
     {
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("ks")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("qs")),
     })
 def test_who_laughs_last_puzzle(self):
     # Part one
     game_state = get_game_state_for_who_laughs_last_puzzle()
     action = self._mcts_player.request_next_action(
         game_state.next_player_view())
     expected_actions = {
         PlayCardAction(PlayerId.ONE, Card(Suit.HEARTS, CardValue.KING)),
         PlayCardAction(PlayerId.ONE, Card(Suit.HEARTS, CardValue.QUEEN))
     }
     self.assertIn(action, expected_actions)
     game_state = action.execute(game_state)
     if action.card.card_value == CardValue.KING:
         self.assertEqual(PlayerPair(19, 26), game_state.trick_points)
     else:
         self.assertEqual(PlayerPair(18, 26), game_state.trick_points)
     # Part two
     game_state = self._play_against_another_mcts_player_until_the_end(
         game_state)
     self.assertEqual(0, game_state.game_points.two)
 def test_equality(self):
   self.assertEqual(
     PlayCardAction(PlayerId.ONE, Card(Suit.DIAMONDS, CardValue.ACE)),
     PlayCardAction(PlayerId.ONE, Card(Suit.DIAMONDS, CardValue.ACE)))
   self.assertNotEqual(
     PlayCardAction(PlayerId.ONE, Card(Suit.DIAMONDS, CardValue.ACE)),
     PlayCardAction(PlayerId.TWO, Card(Suit.DIAMONDS, CardValue.ACE)))
   self.assertNotEqual(
     PlayCardAction(PlayerId.ONE, Card(Suit.DIAMONDS, CardValue.KING)),
     PlayCardAction(PlayerId.ONE, Card(Suit.DIAMONDS, CardValue.ACE)))
   self.assertNotEqual(
     PlayCardAction(PlayerId.TWO, Card(Suit.DIAMONDS, CardValue.KING)),
     PlayCardAction(PlayerId.ONE, Card(Suit.DIAMONDS, CardValue.ACE)))
   self.assertNotEqual(
     PlayCardAction(PlayerId.TWO, Card(Suit.DIAMONDS, CardValue.KING)),
     AnnounceMarriageAction(PlayerId.TWO, Card(Suit.DIAMONDS, CardValue.KING)))
Beispiel #14
0
 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)
Beispiel #15
0
    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_play_trick_winner_has_pending_marriage_points(self):
    game_state = get_game_state_for_tests()
    with GameStateValidator(game_state):
      for trick in game_state.won_tricks[PlayerId.TWO]:
        game_state.trick_points[PlayerId.TWO] -= trick.one.card_value
        game_state.trick_points[PlayerId.TWO] -= trick.two.card_value
        game_state.talon.extend([trick.one, trick.two])
      game_state.trick_points = PlayerPair(22, 0)
      game_state.won_tricks[PlayerId.TWO] = []

    first_talon_card = game_state.talon[0]
    second_talon_card = game_state.talon[1]

    queen_hearts = game_state.cards_in_hand[PlayerId.ONE][0]
    action = PlayCardAction(PlayerId.ONE, queen_hearts)
    game_state = action.execute(game_state)
    self.assertEqual(queen_hearts, game_state.current_trick[PlayerId.ONE])
    self.assertEqual(PlayerId.TWO, game_state.next_player)
    self.assertEqual([Suit.DIAMONDS], game_state.marriage_suits[PlayerId.TWO])
    self.assertEqual(0, game_state.trick_points[PlayerId.TWO])

    queen_clubs = game_state.cards_in_hand[PlayerId.TWO][4]
    action = PlayCardAction(PlayerId.TWO, queen_clubs)
    game_state = action.execute(game_state)
    self.assertEqual(PlayerPair(None, None), game_state.current_trick)
    self.assertEqual(PlayerPair(22, 26), game_state.trick_points)
    self.assertEqual(PlayerPair(queen_hearts, queen_clubs),
                     game_state.won_tricks[PlayerId.TWO][-1])
    self.assertFalse(queen_hearts in game_state.cards_in_hand[PlayerId.ONE])
    self.assertFalse(queen_clubs in game_state.cards_in_hand[PlayerId.TWO])
    self.assertTrue(second_talon_card in game_state.cards_in_hand[PlayerId.ONE])
    self.assertTrue(first_talon_card in game_state.cards_in_hand[PlayerId.TWO])
    self.assertEqual(PlayerId.TWO, game_state.next_player)
  def test_play_trick_talon_has_more_than_one_card(self):
    game_state = get_game_state_with_multiple_cards_in_the_talon_for_tests()

    first_talon_card = game_state.talon[0]
    second_talon_card = game_state.talon[1]

    queen_hearts = game_state.cards_in_hand[PlayerId.ONE][0]
    action = PlayCardAction(PlayerId.ONE, queen_hearts)
    game_state = action.execute(game_state)
    self.assertEqual(queen_hearts, game_state.current_trick[PlayerId.ONE])
    self.assertEqual(PlayerId.TWO, game_state.next_player)

    queen_diamonds = game_state.cards_in_hand[PlayerId.TWO][0]
    action = PlayCardAction(PlayerId.TWO, queen_diamonds)
    game_state = action.execute(game_state)
    self.assertEqual(PlayerPair(None, None), game_state.current_trick)
    self.assertEqual(PlayerPair(28, 33), game_state.trick_points)
    self.assertEqual(PlayerPair(queen_hearts, queen_diamonds),
                     game_state.won_tricks[PlayerId.ONE][-1])
    self.assertFalse(queen_hearts in game_state.cards_in_hand[PlayerId.ONE])
    self.assertFalse(queen_diamonds in game_state.cards_in_hand[PlayerId.TWO])
    self.assertTrue(first_talon_card in game_state.cards_in_hand[PlayerId.ONE])
    self.assertTrue(second_talon_card in game_state.cards_in_hand[PlayerId.TWO])
    self.assertEqual([Card(Suit.CLUBS, CardValue.TEN)], game_state.talon)
    self.assertEqual(PlayerId.ONE, game_state.next_player)
  def test_actions_when_player_is_to_lead_talon_is_empty(self):
    game_state = get_game_state_with_empty_talon_for_tests()

    actions = get_available_actions(game_state)
    self.assertEqual(set(actions),
                     set(get_available_actions(game_state.next_player_view())))
    expected_actions = [
      PlayCardAction(PlayerId.ONE, Card(Suit.CLUBS, CardValue.ACE)),
      PlayCardAction(PlayerId.ONE, Card(Suit.HEARTS, CardValue.KING)),
      PlayCardAction(PlayerId.ONE, Card(Suit.HEARTS, CardValue.TEN)),
      PlayCardAction(PlayerId.ONE, Card(Suit.SPADES, CardValue.TEN)),
    ]
    self.assertSetEqual(set(expected_actions), set(actions))

    game_state = get_game_state_with_empty_talon_for_tests()
    with GameStateValidator(game_state):
      game_state.next_player = PlayerId.TWO

    actions = get_available_actions(game_state)
    self.assertEqual(set(actions),
                     set(get_available_actions(game_state.next_player_view())))
    expected_actions = [
      PlayCardAction(PlayerId.TWO, Card(Suit.DIAMONDS, CardValue.JACK)),
      AnnounceMarriageAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.KING)),
      PlayCardAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.JACK)),
      AnnounceMarriageAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.QUEEN)),
    ]
    self.assertSetEqual(set(expected_actions), set(actions))
    def test_the_last_trump_puzzle(self):
        game_view = get_game_view_for_the_last_trump_puzzle()
        action = self._mcts_player.request_next_action(game_view)
        print(f"Selected action: {action}")
        self.assertEqual(
            PlayCardAction(PlayerId.ONE, Card(Suit.HEARTS, CardValue.TEN)),
            action)

        game_state = populate_game_view(game_view, get_unseen_cards(game_view))
        game_state = action.execute(game_state)
        game_state = self._play_against_another_mcts_player_until_the_end(
            game_state)
        self.assertEqual(0, game_state.game_points.two)
Beispiel #20
0
 def test_can_close_talon(self):
   self._run_test_cases_with_option("can_close_talon", [False, True], [
     # The talon is already closed. Discard the smallest trump card.
     {
       "cards_in_hand": (["ts", "qs"], ["as", None]),
       "trump": Suit.SPADES,
       "trump_card": "ks",
       "talon": [None, None, None, None, None, None, None, None, None],
       "won_tricks": ([("qh", "qd")], [("tc", "ac"), ("jh", "jc")]),
       "player_that_closed_the_talon": PlayerId.ONE,
       "opponent_points_when_talon_was_closed": 0,
       "expected_action": [
         PlayCardAction(PlayerId.ONE, Card.from_string("qs")),
         PlayCardAction(PlayerId.ONE, Card.from_string("qs")),
       ]
     },
     # There is a high chance the opponent has a Heart or a Club.
     {
       "cards_in_hand": (["qh", "ah", "ad", "kc", "kd"],
                         [None, None, None, None, None]),
       "trump": Suit.SPADES,
       "trump_card": "as",
       "talon": [None],
       "won_tricks": ([("qs", "ac"), ("ks", "jd")],
                      [("tc", "js"), ("jh", "jc")]),
       "marriage_suits": ([Suit.SPADES], []),
       "expected_action": [
         PlayCardAction(PlayerId.ONE, Card.from_string("qh")),
         CloseTheTalonAction(PlayerId.ONE),
       ]
     },
     # There is a small chance to win if we close the talon.
     {
       "cards_in_hand": (["qh", "qd", "ac", "ks", "tc"],
                         [None, None, None, None, None]),
       "trump": Suit.HEARTS,
       "trump_card": "ah",
       "talon": [None, None, None, None, None, None, None, None, None],
       "expected_action": [
         PlayCardAction(PlayerId.ONE, Card.from_string("qd")),
         PlayCardAction(PlayerId.ONE, Card.from_string("qd")),
       ]
     },
     # Make sure the player computes the winning probabilities as if suits must
     # be followed.
     {
       "cards_in_hand": (["qc", "ts", "ah", "as", "ad"],
                         [None, None, None, None, None]),
       "trump": Suit.SPADES,
       "trump_card": "js",
       "talon": [None, None, None],
       "won_tricks": ([("td", "kd"), ("qd", "jc")], [("jh", "kh")]),
       "expected_action": [
         PlayCardAction(PlayerId.ONE, Card.from_string("qc")),
         CloseTheTalonAction(PlayerId.ONE),
       ]
     },
   ])
 def test_must_follow_trump_can_discard_any_card(self):
   game_state = get_game_state_for_tests()
   with GameStateValidator(game_state):
     game_state.next_player = PlayerId.TWO
     game_state.close_talon()
   action = PlayCardAction(PlayerId.TWO,
                           game_state.cards_in_hand[PlayerId.TWO][0])
   game_state = action.execute(game_state)
   for card in game_state.cards_in_hand[PlayerId.ONE]:
     action = PlayCardAction(PlayerId.ONE, card)
     self.assertTrue(action.can_execute_on(game_state))
     self.assertTrue(action.can_execute_on(game_state.next_player_view()))
Beispiel #22
0
 def test_non_trump_marriages_are_preferred_randomly(self):
   self.assertIn(get_best_marriage(
     [
       PlayCardAction(PlayerId.ONE, Card.from_string("jh")),
       PlayCardAction(PlayerId.ONE, Card.from_string("ad")),
       PlayCardAction(PlayerId.ONE, Card.from_string("js")),
       PlayCardAction(PlayerId.ONE, Card.from_string("ts")),
       PlayCardAction(PlayerId.ONE, Card.from_string("qc")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("kh")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("qh")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("ks")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("qs")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("kc")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("qc")),
     ], Suit.DIAMONDS),
     {
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("kh")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("qh")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("ks")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("qs")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("kc")),
       AnnounceMarriageAction(PlayerId.ONE, Card.from_string("qc")),
     })
Beispiel #23
0
  def test(self):
    action = PlayCardAction(PlayerId.ONE, Card(Suit.SPADES, CardValue.ACE))

    class TestPlayer(AIPlayer):
      def request_next_action(self, game_view: GameState, game_points: Optional[
        PlayerPair[int]] = None) -> PlayerAction:
        return action

    ai_player = TestPlayer(PlayerId.ONE, True)
    player = ComputerPlayer(ai_player)
    self.assertTrue(player.is_cheater())
    game_state = get_game_state_for_tests()
    callback = Mock()
    player.request_next_action(game_state, callback)
    callback.assert_called()
    self.assertEqual(action, callback.call_args.args[0])
Beispiel #24
0
    def _on_lead_follow_suit(self, game_view: GameState) -> PlayerAction:
        # If talon is depleted, the probabilities here would be either 0 or 1. If
        # we have any card with 100% winning prob, play it. If the talon is closed,
        # play the card with the highest probability to win (can be smaller than 1).
        probabilities = self._get_winning_prob(game_view)
        logging.debug("HeuristicPlayer: Card win probabilities:\n%s",
                      _pprint(probabilities))
        max_prob = max(probabilities.values())
        logging.debug(
            "HeuristicPlayer: The maximum winning probability is %.2f",
            max_prob)
        if max_prob > 0:  # TODO: Set a threshold here.
            # If we have a marriage and the king has the same winning chance as the
            # maximum among all the other cards in hand, prefer to announce the
            # marriage.
            if self._marriage_suit is not None:
                king = Card(self._marriage_suit, CardValue.KING)
                king_prob = probabilities.get(king, 0)
                logging.debug("HeuristicPlayer: %s probability: %.2f", king,
                              king_prob)
                if king_prob == max_prob:
                    logging.debug(
                        "HeuristicPlayer: Announcing the marriage for %s",
                        king)
                    return AnnounceMarriageAction(self.id, king)

            # Play a random card among the ones with the highest chance to win the
            # next trick.
            card_to_play = random.choice([
                card for card, prob in probabilities.items()
                if prob == max_prob
            ])
            logging.debug(
                "HeuristicPlayer: Play a card with the maximum win probability %s",
                card_to_play)
            return self._play_card_or_marriage(card_to_play)

        # If there is no chance we win the next trick and we have a marriage,
        # announce it.
        if self._marriage_suit is not None:
            return AnnounceMarriageAction(
                self.id, Card(self._marriage_suit, CardValue.KING))

        # Discard one of the small cards.
        card_to_play = self._best_discard(game_view)
        return PlayCardAction(self.id, card_to_play)
Beispiel #25
0
 def test(self):
   self.render(None)
   event = Event()
   player = OutOfProcessComputerPlayer(_OutOfProcessTestPlayer,
                                       (PlayerId.ONE, True, event))
   self.assertTrue(player.is_cheater())
   game_state = get_game_state_for_tests()
   callback = Mock()
   player.request_next_action(game_state, callback, PlayerPair(2, 3))
   callback.assert_not_called()
   self.advance_frames(5)
   callback.assert_not_called()
   event.set()
   self.wait_for_mock_callback(callback, 5)
   self.assertEqual(
     PlayCardAction(PlayerId.ONE, Card(Suit.SPADES, CardValue.ACE)),
     callback.call_args.args[0])
   player.cleanup()
 def test_must_follow_suit_must_use_trump(self):
   """Player.TWO has no hearts, so they must use one of the trump cards."""
   game_state = get_game_state_for_tests()
   game_state.close_talon()
   self.assertTrue(game_state.must_follow_suit())
   action = PlayCardAction(PlayerId.ONE,
                           game_state.cards_in_hand[PlayerId.ONE][0])
   self.assertTrue(action.can_execute_on(game_state))
   game_state = action.execute(game_state)
   num_legal_cards = 0
   for card in game_state.cards_in_hand[PlayerId.TWO]:
     action = PlayCardAction(PlayerId.TWO, card)
     is_legal_card = action.can_execute_on(game_state)
     self.assertEqual(card.suit == game_state.trump, is_legal_card,
                      msg=f"{card}")
     self.assertEqual(is_legal_card,
                      action.can_execute_on(game_state.next_player_view()))
     if is_legal_card:
       num_legal_cards += 1
   self.assertEqual(3, num_legal_cards)
Beispiel #27
0
 def test_avoid_direct_loss(self):
   self._run_test_cases_with_option("avoid_direct_loss", [False, True], [
     # Play a trump card instead of discarding the smallest non trump card.
     {
       "cards_in_hand": (["jh", "td", "th", "kh", "ad"],
                         [None, None, None, None, None]),
       "trump": Suit.HEARTS,
       "trump_card": "ah",
       "talon": [None],
       "won_tricks": ([],
                      [("kd", "tc"), ("js", "qs"), ("ts", "as"),
                       ("jc", "ac")]),
       "current_trick": (None, "qc"),
       "expected_action": [
         PlayCardAction(PlayerId.ONE, Card.from_string("td")),
         PlayCardAction(PlayerId.ONE, Card.from_string("jh")),
       ]
     },
     # Play the smallest card instead of discarding a card from an exhausted
     # suit.
     {
       "cards_in_hand": (["jh", "td", "th", "tc", "ad"],
                         [None, None, None, None, None]),
       "trump": Suit.SPADES,
       "trump_card": "as",
       "talon": [None],
       "won_tricks": ([],
                      [("jc", "qc"), ("kc", "ts"), ("ac", "js"),
                       ("jd", "kh")]),
       "marriage_suits": ([], [Suit.HEARTS]),
       "current_trick": (None, "ks"),
       "expected_action": [
         PlayCardAction(PlayerId.ONE, Card.from_string("tc")),
         PlayCardAction(PlayerId.ONE, Card.from_string("jh")),
       ]
     },
     # There is no direct loss; discard a small card.
     {
       "cards_in_hand": (["jh", "td", "ts", "tc", "ad"],
                         [None, None, None, None, None]),
       "trump": Suit.SPADES,
       "trump_card": "as",
       "talon": [None, None, None, None, None, None, None, None, None],
       "current_trick": (None, "kh"),
       "expected_action": [
         PlayCardAction(PlayerId.ONE, Card.from_string("jh")),
         PlayCardAction(PlayerId.ONE, Card.from_string("jh")),
       ]
     },
   ])
  def test_must_follow_suit_cannot_play_lower_card_same_suit(self):
    """
    Player.ONE has two cards of the same suit as the card played by Player.TWO,
    one lower and one higher. Player.ONE also has a trump card. The only valid
    card is the higher card having the same suit as the card played by
    Player.TWO.
    """
    game_state = get_game_state_for_tests()

    with GameStateValidator(game_state):
      ten_spades = game_state.cards_in_hand.one[3]
      jack_spades = game_state.cards_in_hand.two[3]
      game_state.cards_in_hand.two[3] = ten_spades
      game_state.cards_in_hand.one[3] = jack_spades

      queen_hearts = game_state.cards_in_hand.one[0]
      queen_clubs = game_state.cards_in_hand.two[4]
      game_state.cards_in_hand.two[4] = queen_hearts
      game_state.cards_in_hand.one[0] = queen_clubs

      game_state.close_talon()
      game_state.next_player = PlayerId.TWO

    self.assertTrue(game_state.must_follow_suit())
    action = PlayCardAction(PlayerId.TWO, ten_spades)
    self.assertTrue(action.can_execute_on(game_state))
    game_state = action.execute(game_state)
    ace_spades = Card(Suit.SPADES, CardValue.ACE)
    num_legal_cards = 0
    for card in game_state.cards_in_hand[PlayerId.ONE]:
      action = PlayCardAction(PlayerId.ONE, card)
      is_legal_card = action.can_execute_on(game_state)
      self.assertEqual(card == ace_spades, is_legal_card, msg=f"{card}")
      self.assertEqual(is_legal_card,
                       action.can_execute_on(game_state.next_player_view()))
      if is_legal_card:
        num_legal_cards += 1
    self.assertEqual(1, num_legal_cards)
Beispiel #29
0
 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_play_trick_talon_closed_opponent_cannot_follow_suit(self):
   game_state = get_game_state_for_tests()
   with GameStateValidator(game_state):
     trick = game_state.won_tricks.two.pop(0)
     game_state.talon.append(trick.one)
     game_state.talon.append(trick.two)
     trick = game_state.won_tricks.two.pop(0)
     game_state.talon.append(trick.one)
     game_state.talon.append(trick.two)
     game_state.trick_points.two = 0
   game_state.close_talon()
   self.assertEqual([False, False, False, False, False],
                    [card.public for card in game_state.talon])
   action = PlayCardAction(PlayerId.ONE, Card(Suit.HEARTS, CardValue.TEN))
   self.assertTrue(action.can_execute_on(game_state))
   game_state = action.execute(game_state)
   self.assertEqual([False, False, False, False, False],
                    [card.public for card in game_state.talon])
   action = PlayCardAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.JACK))
   self.assertTrue(action.can_execute_on(game_state))
   game_state = action.execute(game_state)
   self.assertEqual([False, True, True, False, False],
                    [card.public for card in game_state.talon])