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_won_tricks(self): # Cannot win with the same suit, but smaller card. trick = self.game_state.won_tricks.one[0] # K♠, Q♠ swapped_trick = PlayerPair(one=trick.two, two=trick.one) self.game_state.won_tricks.one[0] = swapped_trick with self.assertRaisesRegex(InvalidGameStateError, "ONE cannot win this trick: Q♠, K♠"): validate(self.game_state) # Cannot win with non-trump card against a trump card. self.game_state = get_game_state_for_tests() self.game_state.won_tricks.one.append( self.game_state.won_tricks.two.pop()) self.game_state.trick_points = PlayerPair(42, 33) with self.assertRaisesRegex(InvalidGameStateError, "ONE cannot win this trick: X♦, X♣"): validate(self.game_state) # Different suits, no trump. Could be valid wins for both players, since we # don't know who played the first card. self.game_state = get_game_state_for_tests() card = self.game_state.won_tricks.two[-1].two self.game_state.won_tricks.two[-1].two = \ self.game_state.cards_in_hand.one[3] self.game_state.cards_in_hand.one[3] = card validate(self.game_state) self.game_state.won_tricks.one.append( self.game_state.won_tricks.two.pop()) self.game_state.trick_points = PlayerPair(42, 33) validate(self.game_state)
def test_actions_after_the_opponent_played_one_card(self): game_state = get_game_state_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.DIAMONDS, CardValue.QUEEN)), PlayCardAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.KING)), PlayCardAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.JACK)), PlayCardAction(PlayerId.TWO, Card(Suit.CLUBS, CardValue.QUEEN)), 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 action = PlayCardAction(PlayerId.TWO, Card(Suit.DIAMONDS, CardValue.QUEEN)) 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.HEARTS, CardValue.QUEEN)), PlayCardAction(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))
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 test_cards_missing_in_both_hands(self): game_state = get_game_state_for_tests() game_view = game_state.next_player_view() game_view.cards_in_hand[PlayerId.ONE][0] = None unseen_cards = get_unseen_cards(game_view) with self.assertRaisesRegex(AssertionError, "Cards missing in both hands"): populate_game_view(game_view, unseen_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_function_with_valid_changes(self): @validate_game_states def func(game_state: GameState) -> int: game_state.next_player = game_state.next_player.opponent() return 42 self.assertEqual(42, func(get_game_state_for_tests()))
def _generate_data(cheater: bool, options: MctsPlayerOptions, constant_budget: bool): dataframes = [] fully_simulated_game_states = { "You first. No, you first": get_game_state_for_you_first_no_you_first_puzzle(), "Elimination play": get_game_state_for_elimination_play_puzzle(), "Playing to win the last trick": get_game_state_for_playing_to_win_the_last_trick_puzzle(), "Tempo": get_game_state_for_tempo_puzzle(), "Who laughs last": get_game_state_for_who_laughs_last_puzzle(), "Forcing the issue": get_game_state_for_forcing_the_issue_puzzle(), "Game state for tests": get_game_state_for_tests(), } dataframes.extend( _run_simulations(fully_simulated_game_states, cheater, options, constant_budget)) partially_simulated_game_states = {} for seed in [0, 20, 40, 60, 100]: partially_simulated_game_states[f"Random GameState (seed={seed})"] = \ GameState.new(dealer=PlayerId.ONE, random_seed=seed) dataframes.extend( _run_simulations(partially_simulated_game_states, cheater, options, constant_budget)) dataframes.extend( _run_simulations(same_game_state_after_each_trick_scenarios(20), cheater, options, constant_budget)) dataframe = pandas.concat(dataframes, ignore_index=True) # noinspection PyTypeChecker dataframe.to_csv(_get_csv_path(cheater), index=False)
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_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_cannot_execute_illegal_action(self): game_state = get_game_state_for_tests() queen_clubs = Card(Suit.CLUBS, CardValue.QUEEN) action = AnnounceMarriageAction(PlayerId.TWO, queen_clubs) self.assertFalse(action.can_execute_on(game_state)) with self.assertRaises(AssertionError): action.execute(game_state)
def test_invalid_when_exiting_other_exception_is_raised(self): game_state = get_game_state_for_tests() with self.assertRaisesRegex(InvalidGameStateError, "Invalid trick points"): with GameStateValidator(game_state): game_state.trick_points = PlayerPair(0, 0) raise ValueError( "This will be replaced by InvalidGameStateError")
def test_cannot_exchange_trump_if_not_in_players_hand(self): game_state = get_game_state_for_tests() trump_jack = Card(suit=game_state.trump, card_value=CardValue.JACK) self.assertFalse(trump_jack in game_state.cards_in_hand[PlayerId.ONE]) self.assertTrue(game_state.is_to_lead(PlayerId.ONE)) self.assertFalse(game_state.is_talon_closed) action = ExchangeTrumpCardAction(PlayerId.ONE) self.assertFalse(action.can_execute_on(game_state)) self.assertFalse(action.can_execute_on(game_state.next_player_view()))
def test_cannot_exchange_trump_when_talon_is_closed(self): game_state = get_game_state_for_tests() action = ExchangeTrumpCardAction(PlayerId.TWO) game_state.next_player = PlayerId.TWO self.assertTrue(action.can_execute_on(game_state)) self.assertTrue(action.can_execute_on(game_state.next_player_view())) game_state.close_talon() self.assertFalse(action.can_execute_on(game_state)) self.assertFalse(action.can_execute_on(game_state.next_player_view()))
def test_marriage_card_not_played(self): # One card is in the talon, one card is in the player's hand. card = self.game_state.won_tricks.one[-1].two self.game_state.won_tricks.one[-1].two = self.game_state.talon[0] self.game_state.talon[0] = card with self.assertRaisesRegex(InvalidGameStateError, "♦ was announced, but no card was played"): validate(self.game_state) # Both cards are still in the player's hand. self.game_state = get_game_state_for_tests() self.game_state.marriage_suits.one.append(Suit.HEARTS) with self.assertRaisesRegex(InvalidGameStateError, "♥ was announced, but no card was played"): validate(self.game_state) # Both cards are still in the player's hand, but they just announced it and # played one card. self.game_state = get_game_state_for_tests() king_hearts = self.game_state.cards_in_hand.one[1] self.game_state.current_trick.one = king_hearts self.game_state.marriage_suits.one.append(Suit.HEARTS) self.game_state.trick_points.one += 20 self.game_state.next_player = PlayerId.TWO with self.assertRaisesRegex(InvalidGameStateError, "Marriage card should be public: Q♥"): validate(self.game_state) self.game_state.cards_in_hand.one[0].public = True validate(self.game_state) # Both cards were played, but by different players. self.game_state = get_game_state_for_tests() self.game_state.marriage_suits.one.append(Suit.SPADES) with self.assertRaisesRegex(InvalidGameStateError, "ONE announced .* ♠ and played one card"): validate(self.game_state) # The other player announced the marriage. self.game_state = get_game_state_for_tests() self.game_state.marriage_suits.one.append( self.game_state.marriage_suits.two.pop()) with self.assertRaisesRegex(InvalidGameStateError, "♦ was announced, but no card was played"): validate(self.game_state)
def test_game_view_with_public_talon_cards(self): game_state = get_game_state_for_tests() game_state.talon[0].public = True game_view = game_state.next_player_view() unseen_cards = get_unseen_cards(game_view) self.assertEqual([Card(Suit.SPADES, CardValue.JACK), Card(Suit.CLUBS, CardValue.JACK), Card(Suit.CLUBS, CardValue.QUEEN), Card(Suit.CLUBS, CardValue.KING)], unseen_cards)
def test_function_with_invalid_changes(self): @validate_game_states def func(game_state: GameState) -> int: game_state.trick_points = PlayerPair(0, 0) return 42 self.assertEqual(42, func(GameState.new(PlayerId.ONE))) with self.assertRaisesRegex(InvalidGameStateError, "Invalid trick points"): func(get_game_state_for_tests())
def test_generate_all_permutations(self): game_state = get_game_state_for_tests() game_view = game_state.next_player_view() unseen_cards = get_unseen_cards(game_view) all_game_states = [populate_game_view(game_view, list(permutation)) for permutation in itertools.permutations(unseen_cards)] all_game_states = set(all_game_states) self.assertEqual(120, # factorial(5) len(all_game_states)) self.assertIn(game_state, all_game_states)
def test_game_view(self): game_state = get_game_state_for_tests() game_view = game_state.next_player_view() unseen_cards = get_unseen_cards(game_view) self.assertEqual([Card(Suit.SPADES, CardValue.JACK), Card(Suit.DIAMONDS, CardValue.JACK), Card(Suit.CLUBS, CardValue.JACK), Card(Suit.CLUBS, CardValue.QUEEN), Card(Suit.CLUBS, CardValue.KING)], unseen_cards)
def test_execute(self): game_state = get_game_state_for_tests() next_player = game_state.next_player action = CloseTheTalonAction(next_player) self.assertTrue(action.can_execute_on(game_state)) game_state = action.execute(game_state) self.assertEqual(next_player, game_state.next_player) self.assertTrue(game_state.is_talon_closed) self.assertEqual(next_player, game_state.player_that_closed_the_talon) self.assertEqual(53, game_state.opponent_points_when_talon_was_closed)
def test_too_many_cards_in_permutation(self): game_state = get_game_state_for_tests() game_view = game_state.next_player_view() permutation = [Card(Suit.SPADES, CardValue.JACK), Card(Suit.DIAMONDS, CardValue.JACK), Card(Suit.CLUBS, CardValue.JACK), Card(Suit.CLUBS, CardValue.QUEEN), Card(Suit.CLUBS, CardValue.KING), Card(Suit.DIAMONDS, CardValue.QUEEN)] with self.assertRaisesRegex(AssertionError, "Too many cards in permutation"): populate_game_view(game_view, permutation)
def test_invalid_when_entering(self): game_state = get_game_state_for_tests() game_state.trick_points = PlayerPair(0, 0) with self.assertRaisesRegex(InvalidGameStateError, "Invalid trick points"): with GameStateValidator(game_state): pass with self.assertRaisesRegex(InvalidGameStateError, "Invalid trick points"): with GameStateValidator(game_state): # This would make the game_state valid. game_state.trick_points = PlayerPair(22, 53)
def test_can_only_execute_before_leading_a_trick(self): # Other player is to lead, cannot exchange trump. game_state = get_game_state_for_tests() self.assertTrue(game_state.is_to_lead(PlayerId.ONE)) action = ExchangeTrumpCardAction(PlayerId.TWO) self.assertFalse(action.can_execute_on(game_state)) self.assertFalse(action.can_execute_on(game_state.next_player_view())) # PlayerId.TWO is to lead, can exchange trump. game_state.next_player = PlayerId.TWO self.assertTrue(action.can_execute_on(game_state)) self.assertTrue(action.can_execute_on(game_state.next_player_view()))
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()))
def test_announce_non_trump_marriage(self): game_state = get_game_state_for_tests() queen_hearts = Card(Suit.HEARTS, CardValue.QUEEN) action = AnnounceMarriageAction(PlayerId.ONE, queen_hearts) self.assertTrue(action.can_execute_on(game_state)) game_state = action.execute(game_state) self.assertEqual(42, game_state.trick_points[PlayerId.ONE]) self.assertEqual(queen_hearts, game_state.current_trick[PlayerId.ONE]) self.assertEqual([Suit.HEARTS], game_state.marriage_suits[PlayerId.ONE]) self.assertEqual(PlayerId.TWO, game_state.next_player) king_hearts = game_state.cards_in_hand[PlayerId.ONE][1] self.assertTrue(king_hearts.public)
def test_announcing_marriage_is_enough_to_win_the_game(self): game_state = get_game_state_for_tests() with GameStateValidator(game_state): game_state.next_player = PlayerId.TWO king_clubs = Card(Suit.CLUBS, CardValue.KING) action = AnnounceMarriageAction(PlayerId.TWO, king_clubs) self.assertTrue(action.can_execute_on(game_state)) game_state = action.execute(game_state) queen_clubs = game_state.cards_in_hand[PlayerId.TWO][4] self.assertTrue(queen_clubs.public) self.assertEqual(93, game_state.trick_points[PlayerId.TWO]) self.assertTrue(game_state.is_game_over)
def test_execute(self): game_state = get_game_state_for_tests() action = ExchangeTrumpCardAction(PlayerId.TWO) game_state.next_player = PlayerId.TWO self.assertTrue(action.can_execute_on(game_state)) trump_card = game_state.trump_card trump_jack = Card(suit=game_state.trump, card_value=CardValue.JACK) game_state = action.execute(game_state) self.assertEqual(game_state.trump_card, trump_jack) self.assertTrue(trump_card in game_state.cards_in_hand[PlayerId.TWO]) index = game_state.cards_in_hand[PlayerId.TWO].index(trump_card) self.assertTrue(game_state.cards_in_hand[PlayerId.TWO][index].public) self.assertEqual(PlayerId.TWO, game_state.next_player)
def test_can_only_execute_before_leading_a_trick(self): game_state = get_game_state_for_tests() queen_hearts = Card(Suit.HEARTS, CardValue.QUEEN) action = AnnounceMarriageAction(PlayerId.ONE, queen_hearts) self.assertTrue(action.can_execute_on(game_state)) self.assertTrue(action.can_execute_on(game_state.next_player_view())) king_clubs = Card(Suit.CLUBS, CardValue.KING) action = AnnounceMarriageAction(PlayerId.TWO, king_clubs) self.assertFalse(action.can_execute_on(game_state)) self.assertFalse(action.can_execute_on(game_state.next_player_view())) game_state.next_player = PlayerId.TWO self.assertTrue(action.can_execute_on(game_state)) self.assertTrue(action.can_execute_on(game_state.next_player_view()))
def test_can_only_execute_on_players_turn(self): game_state = get_game_state_for_tests() card = game_state.cards_in_hand[PlayerId.ONE][0] action_one = PlayCardAction(PlayerId.ONE, card) self.assertTrue(action_one.can_execute_on(game_state)) self.assertTrue(action_one.can_execute_on(game_state.next_player_view())) action_two = PlayCardAction(PlayerId.TWO, game_state.cards_in_hand[PlayerId.TWO][0]) self.assertFalse(action_two.can_execute_on(game_state)) self.assertFalse(action_two.can_execute_on(game_state.next_player_view())) game_state = action_one.execute(game_state) self.assertFalse(action_one.can_execute_on(game_state)) self.assertFalse(action_one.can_execute_on(game_state.next_player_view())) self.assertTrue(action_two.can_execute_on(game_state)) self.assertTrue(action_two.can_execute_on(game_state.next_player_view()))
def test_announce_trump_marriage(self): game_state = get_game_state_for_tests() with GameStateValidator(game_state): game_state.next_player = PlayerId.TWO queen_clubs = Card(Suit.CLUBS, CardValue.QUEEN) action = AnnounceMarriageAction(PlayerId.TWO, queen_clubs) self.assertTrue(action.can_execute_on(game_state)) game_state = action.execute(game_state) self.assertEqual(93, game_state.trick_points[PlayerId.TWO]) self.assertEqual(queen_clubs, game_state.current_trick[PlayerId.TWO]) self.assertEqual([Suit.DIAMONDS, Suit.CLUBS], game_state.marriage_suits[PlayerId.TWO]) self.assertEqual(PlayerId.ONE, game_state.next_player) king_clubs = game_state.cards_in_hand[PlayerId.TWO][1] self.assertTrue(king_clubs.public)