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_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_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_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_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_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_both_cards_must_be_in_hand(self):
   game_state = get_game_state_for_tests()
   with GameStateValidator(game_state):
     game_state.next_player = PlayerId.TWO
   queen_diamonds = Card(Suit.DIAMONDS, CardValue.QUEEN)
   action = AnnounceMarriageAction(PlayerId.TWO, queen_diamonds)
   self.assertFalse(action.can_execute_on(game_state))
   self.assertFalse(action.can_execute_on(game_state.next_player_view()))
   # Swap the queen of spades with the trump card
   with GameStateValidator(game_state):
     queen_spades = game_state.cards_in_hand[PlayerId.TWO].pop()
     game_state.cards_in_hand[PlayerId.TWO].append(game_state.trump_card)
     game_state.trump_card = queen_spades
     game_state.trump_card.public = True
   action = AnnounceMarriageAction(PlayerId.TWO, queen_spades)
   self.assertFalse(action.can_execute_on(game_state))
   self.assertFalse(action.can_execute_on(game_state.next_player_view()))
Example #9
0
def get_game_state_with_multiple_cards_in_the_talon_for_tests() -> GameState:
  game_state = get_game_state_for_tests()
  with GameStateValidator(game_state):
    trick = game_state.won_tricks[PlayerId.TWO].pop()
    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])
  return 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_no_actions_available_when_game_is_over(self):
   game_state = get_game_state_with_all_tricks_played()
   self.assertEqual([], get_available_actions(game_state))
   self.assertEqual([], get_available_actions(game_state.next_player_view()))
   with GameStateValidator(game_state):
     game_state.next_player = PlayerId.TWO
   self.assertEqual([], get_available_actions(game_state))
   self.assertEqual([], get_available_actions(game_state.next_player_view()))
Example #12
0
def _get_game_state_with_one_card_left() -> GameState:
    game_state = get_game_state_with_all_tricks_played()
    with GameStateValidator(game_state):
        trick = game_state.won_tricks.one.pop(-1)
        game_state.trick_points.one -= trick.one.card_value
        game_state.trick_points.one -= trick.two.card_value
        game_state.cards_in_hand.one.append(trick.one)
        game_state.cards_in_hand.two.append(trick.two)
        game_state.next_player = PlayerId.ONE
    return game_state
 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_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_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)
  def test_announce_marriage_without_scoring_any_trick(self):
    game_state = get_game_state_for_tests()
    with GameStateValidator(game_state):
      for trick in game_state.won_tricks[PlayerId.ONE]:
        game_state.talon.extend([trick.one, trick.two])
      for trick in game_state.won_tricks[PlayerId.TWO]:
        game_state.talon.extend([trick.one, trick.two])
      game_state.won_tricks = PlayerPair([], [])
      game_state.trick_points = PlayerPair(0, 0)
      game_state.marriage_suits[PlayerId.TWO] = []

    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(0, 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_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)
 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])
 def test_no_changes():
     game_state = get_game_state_for_tests()
     with GameStateValidator(game_state):
         pass
 def test_invalid_when_exiting(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)
 def test_valid_when_exiting_other_exception_is_raised(self):
     game_state = get_game_state_for_tests()
     with self.assertRaisesRegex(ValueError, "This should be reraised"):
         with GameStateValidator(game_state):
             game_state.next_player = game_state.next_player.opponent()
             raise ValueError("This should be reraised")
 def test_valid_changes():
     game_state = get_game_state_for_tests()
     with GameStateValidator(game_state):
         game_state.next_player = game_state.next_player.opponent()