def test_actions_when_player_is_to_lead_talon_is_closed(self): game_state = get_game_state_for_tests() game_state = CloseTheTalonAction(PlayerId.ONE).execute(game_state) actions = get_available_actions(game_state) self.assertEqual(set(actions), set(get_available_actions(game_state.next_player_view()))) expected_actions = [ AnnounceMarriageAction(PlayerId.ONE, Card(Suit.HEARTS, CardValue.QUEEN)), AnnounceMarriageAction(PlayerId.ONE, Card(Suit.HEARTS, CardValue.KING)), PlayCardAction(PlayerId.ONE, Card(Suit.HEARTS, CardValue.TEN)), PlayCardAction(PlayerId.ONE, Card(Suit.SPADES, CardValue.TEN)), PlayCardAction(PlayerId.ONE, Card(Suit.SPADES, CardValue.ACE)), ] self.assertSetEqual(set(expected_actions), set(actions)) game_state = get_game_state_for_tests() with GameStateValidator(game_state): game_state.next_player = PlayerId.TWO game_state = CloseTheTalonAction(PlayerId.TWO).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.DIAMONDS, CardValue.QUEEN)), AnnounceMarriageAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.KING)), PlayCardAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.JACK)), AnnounceMarriageAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.QUEEN)), PlayCardAction(PlayerId.TWO, Card(Suit.SPADES, CardValue.JACK)), ] self.assertSetEqual(set(expected_actions), set(actions))
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_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])
def test_equals(self): # given card_a = Card(Card.Suit.DIAMOND, Card.Face.SEVEN) card_b = Card(Card.Suit.DIAMOND, Card.Face.SEVEN) # then self.assertEquals(card_a, card_b)
def test_notEquals_differentFace(self): # given card_a = Card(Card.Suit.DIAMOND, Card.Face.SEVEN) card_b = Card(Card.Suit.DIAMOND, Card.Face.EIGHT) # then self.assertNotEquals(card_a, card_b)
def test_aspect_ratio_is_set_in_constructor(self): card_widget = CardWidget(Card(Suit.SPADES, CardValue.ACE), aspect_ratio=0.5) self.assertEqual([50, 100], card_widget.children[0].size) card_widget = CardWidget(Card(Suit.SPADES, CardValue.ACE), aspect_ratio=0.25) self.assertEqual([25, 100], card_widget.children[0].size)
def test_actions_after_the_opponent_played_one_card_talon_is_closed(self): game_state = get_game_state_for_tests() game_state = CloseTheTalonAction(PlayerId.ONE).execute(game_state) 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.SPADES, CardValue.JACK)), ] self.assertSetEqual(set(expected_actions), set(actions)) game_state = get_game_state_for_tests() with GameStateValidator(game_state): game_state.next_player = PlayerId.TWO game_state = CloseTheTalonAction(PlayerId.TWO).execute(game_state) action = PlayCardAction(PlayerId.TWO, Card(Suit.SPADES, 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.SPADES, CardValue.TEN)), PlayCardAction(PlayerId.ONE, Card(Suit.SPADES, CardValue.ACE)), ] self.assertSetEqual(set(expected_actions), set(actions))
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_init_args_order_and_type(self): # Swaps the order of the arguments. with self.assertRaisesRegex(TypeError, "suit must be an instance of Suit"): Card(CardValue.ACE, Suit.DIAMONDS) with self.assertRaisesRegex(TypeError, "card_value must be an instance of CardValue"): Card(Suit.DIAMONDS, Suit.DIAMONDS)
def test_reset_withoutDealer(self): # given self.game.bid_value = 24 self.game.dealer = 2 self.game.skat.append(Card(Card.Suit.DIAMOND, Card.Face.SEVEN)) self.game.players[0].cards.append( Card(Card.Suit.DIAMOND, Card.Face.EIGHT)) self.game.players[1].cards.append( Card(Card.Suit.DIAMOND, Card.Face.NINE)) self.game.players[2].cards.append( Card(Card.Suit.DIAMOND, Card.Face.TEN)) self.game.passed_bid_players.append(self.game.players[0]) # when self.game.reset() # then # clear cards had to be called self.assertEquals(len(self.game.skat), 0) self.assertEquals(len(self.game.players[0].cards), 0) self.assertEquals(len(self.game.players[1].cards), 0) self.assertEquals(len(self.game.players[2].cards), 0) # reset bid value self.assertEquals(self.game.bid_value, -1) # reset game variant self.assertEquals(self.game.game_variant, None) # reset passed bid player list self.assertEquals(len(self.game.passed_bid_players), 0) # untouched dealer self.assertEquals(self.game.dealer, 2)
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_reset_witDealer(self): # given self.game.bid_value = 24 self.game.dealer = 2 self.game.skat.append(Card(Card.Suit.DIAMOND, Card.Face.SEVEN)) self.game.players[0].cards.append( Card(Card.Suit.DIAMOND, Card.Face.EIGHT)) self.game.players[1].cards.append( Card(Card.Suit.DIAMOND, Card.Face.NINE)) self.game.players[2].cards.append( Card(Card.Suit.DIAMOND, Card.Face.TEN)) # when self.game.reset(True) # then # cleared cards self.assertEquals(len(self.game.skat), 0) self.assertEquals(len(self.game.players[0].cards), 0) self.assertEquals(len(self.game.players[1].cards), 0) self.assertEquals(len(self.game.players[2].cards), 0) # reset bid value self.assertEquals(self.game.bid_value, -1) # reset game variant self.assertEquals(self.game.game_variant, None) # reset dealer self.assertEquals(self.game.dealer, -1)
def test_compareJacks_invalidJacksFails(self): # given no_jack_a = Card(Card.Suit.CLUB, Card.Face.TEN) no_jack_b = Card(Card.Suit.DIAMOND, Card.Face.NINE) # when/then self.assertRaises(TypeError, self.game_variant.compare_jacks, no_jack_a, no_jack_b)
def test_compareJacks_invalidLowerJackFails(self): # given higher_jack = Card(Card.Suit.CLUB, Card.Face.JACK) no_jack = Card(Card.Suit.CLUB, Card.Face.TEN) # when/then self.assertRaises(TypeError, self.game_variant.compare_jacks, higher_jack, no_jack)
def test_marriage_pair(self): for suit in Suit: king = Card(suit, CardValue.KING) queen = Card(suit, CardValue.QUEEN) self.assertEqual(king, queen.marriage_pair) self.assertEqual(queen, king.marriage_pair) with self.assertRaises(AssertionError): _ = Card(Suit.DIAMONDS, CardValue.TEN).marriage_pair
def test_cancel_two_cards_animation_with_callback(self): card_widget_1 = CardWidget(Card(Suit.SPADES, CardValue.QUEEN)) card_widget_1.pos = 0, 0 card_widget_2 = CardWidget(Card(Suit.SPADES, CardValue.KING)) card_widget_2.pos = self.window.size[0], 0 float_layout = FloatLayout() float_layout.add_widget(card_widget_1) float_layout.add_widget(card_widget_2) self.render(float_layout) self.assert_pixels_almost_equal([0, 0], card_widget_1.pos) self.assert_pixels_almost_equal([self.window.size[0], 0], card_widget_2.pos) animation_controller = AnimationController() animation_1 = Animation(x=self.window.size[0], y=self.window.size[1], duration=5) on_complete_callback_1 = Mock() animation_1.bind(on_complete=on_complete_callback_1) animation_controller.add_card_animation(card_widget_1, animation_1) animation_2 = Animation(x=0, y=self.window.size[1], duration=2 * animation_1.duration) on_complete_callback_2 = Mock() animation_2.bind(on_complete=on_complete_callback_2) animation_controller.add_card_animation(card_widget_2, animation_2) on_both_animations_complete_callback = Mock() self.assertFalse(animation_controller.is_running) animation_controller.start(on_both_animations_complete_callback) self.assertTrue(animation_controller.is_running) on_complete_callback_1.assert_not_called() on_complete_callback_2.assert_not_called() on_both_animations_complete_callback.assert_not_called() # Advance a couple of frames to move the cards a little bit, but not # complete any animation. self.advance_frames(5) self.assertNotEqual(0, card_widget_1.x) self.assertNotEqual(0, card_widget_1.y) self.assertNotEqual(self.window.size[0], card_widget_2.x) self.assertNotEqual(0, card_widget_2.y) # No callback should be called. on_complete_callback_1.assert_not_called() on_complete_callback_2.assert_not_called() on_both_animations_complete_callback.assert_not_called() # Cancel the animations. self.assertTrue(animation_controller.is_running) animation_controller.cancel() self.assertFalse(animation_controller.is_running) # All callbacks should be called. on_complete_callback_1.assert_called_once() on_complete_callback_2.assert_called_once() on_both_animations_complete_callback.assert_called_once() # Verify that the AnimationController can be reused. animation_controller.add_card_animation(card_widget_1, animation_1)
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)
def test_isTrump_TrumpTrue(self): # when/then for suit in Card.Suit: self.assertTrue( self.game_variant.is_trump(Card(suit, Card.Face.JACK))) for face in Card.Face: self.assertTrue( self.game_variant.is_trump(Card(Card.Suit.CLUB, face)))
def test_getHighestCard_differentFaceAndSuit(self): # given diamonds_seven = Card(Card.Suit.DIAMOND, Card.Face.SEVEN) hearts_eight = Card(Card.Suit.HEARTS, Card.Face.EIGHT) spade_nine = Card(Card.Suit.SPADE, Card.Face.NINE) # when/then result = self.game_variant.get_highest_card( [spade_nine, hearts_eight, diamonds_seven]) self.assertEquals(Card(Card.Suit.SPADE, Card.Face.NINE), result)
def test_getCurrentTurnPlayer_thirdHand(self): # given self.trick.add(self.player2, Card(Card.Suit.DIAMOND, Card.Face.SEVEN)) self.trick.add(self.player3, Card(Card.Suit.DIAMOND, Card.Face.EIGHT)) # when result = self.trick.get_current_player() # then self.assertEqual(self.player1, result)
def test_isComplete_False(self): # given self.trick.add(self.player1, Card(Card.Suit.DIAMOND, Card.Face.SEVEN)) self.trick.add(self.player2, Card(Card.Suit.DIAMOND, Card.Face.EIGHT)) # when result = self.trick.is_complete() # then self.assertFalse(result)
def test_card_value_and_suit_cannot_be_none(self): with self.assertRaisesRegex(ValueError, "card_value and suit cannot be None"): print(Card(None, CardValue.ACE)) with self.assertRaisesRegex(ValueError, "card_value and suit cannot be None"): print(Card(Suit.DIAMONDS, None)) with self.assertRaisesRegex(ValueError, "card_value and suit cannot be None"): print(Card(None, None))
def test_compareCards_sameSuit(self): # given diamond_seven = Card(Card.Suit.DIAMOND, Card.Face.SEVEN) diamond_eight = Card(Card.Suit.DIAMOND, Card.Face.EIGHT) # when/then self.assertEquals( self.game_variant.compare_cards(diamond_eight, diamond_seven), 1) self.assertEquals( self.game_variant.compare_cards(diamond_seven, diamond_eight), -1)
def test_getHighestCard_sameSuit(self): # given diamonds_ten = Card(Card.Suit.DIAMOND, Card.Face.TEN) diamonds_queen = Card(Card.Suit.DIAMOND, Card.Face.QUEEN) diamonds_king = Card(Card.Suit.DIAMOND, Card.Face.KING) # when/then result = self.game_variant.get_highest_card( [diamonds_queen, diamonds_king, diamonds_ten]) self.assertEquals(Card(Card.Suit.DIAMOND, Card.Face.TEN), result)
def test_getHighestCard_sameFace(self): # given diamonds_seven = Card(Card.Suit.DIAMOND, Card.Face.SEVEN) hearts_seven = Card(Card.Suit.HEARTS, Card.Face.SEVEN) spade_seven = Card(Card.Suit.SPADE, Card.Face.SEVEN) # when/then result = self.game_variant.get_highest_card( [hearts_seven, spade_seven, diamonds_seven]) self.assertEquals(Card(Card.Suit.HEARTS, Card.Face.SEVEN), result)
def test_getHighestCard_jackAndSuit(self): # given diamonds_jack = Card(Card.Suit.DIAMOND, Card.Face.JACK) diamonds_king = Card(Card.Suit.DIAMOND, Card.Face.KING) club_ace = Card(Card.Suit.CLUB, Card.Face.ACE) # when/then result = self.game_variant.get_highest_card( [diamonds_king, club_ace, diamonds_jack]) self.assertEquals(Card(Card.Suit.DIAMOND, Card.Face.JACK), result)
def test_getHighestCard_jacks(self): # given diamonds_jack = Card(Card.Suit.DIAMOND, Card.Face.JACK) hearts_jack = Card(Card.Suit.HEARTS, Card.Face.JACK) spade_jack = Card(Card.Suit.SPADE, Card.Face.JACK) # when/then result = self.game_variant.get_highest_card( [spade_jack, hearts_jack, diamonds_jack]) self.assertEquals(Card(Card.Suit.SPADE, Card.Face.JACK), result)
def test_getHighestCard_TrumpAndSuit(self): # given diamond_ace = Card(Card.Suit.DIAMOND, Card.Face.ACE) diamond_king = Card(Card.Suit.DIAMOND, Card.Face.KING) club_seven = Card(Card.Suit.CLUB, Card.Face.SEVEN) # when/then result = self.game_variant.get_highest_card( [diamond_king, club_seven, diamond_ace]) self.assertEquals(Card(Card.Suit.CLUB, Card.Face.SEVEN), result)
def test_compareCards_sameFace(self): # given diamonds_seven = Card(Card.Suit.DIAMOND, Card.Face.SEVEN) heats_seven = Card(Card.Suit.HEARTS, Card.Face.SEVEN) # when/then self.assertEquals( self.game_variant.compare_cards(heats_seven, diamonds_seven), 0) self.assertEquals( self.game_variant.compare_cards(diamonds_seven, heats_seven), 0)
def can_execute_on(self, game_state: GameState) -> bool: if not game_state.is_to_lead(self.player_id): return False queen = Card(self._card.suit, CardValue.QUEEN) king = Card(self._card.suit, CardValue.KING) if queen not in game_state.cards_in_hand[self.player_id]: return False if king not in game_state.cards_in_hand[self.player_id]: return False return True