def test_countess_playPrinceOrKing_raises(current_player, other_card_type): give_card(current_player, cards.Countess(), replace=True) give_card(current_player, card := card_from_card_type(other_card_type)) with assert_state_is_preserved(current_player.round) as mocked_round: with pytest.raises(valid8.ValidationError): autofill_move(mocked_round.current_player.play_card(card))
def test_chooseCardToPlay_checksMoveWithOtherCard(current_player: RoundPlayer): card_mock = CardMockCases.case_generic() give_card(current_player, card_mock) other_card = next(c for c in current_player.hand if c is not card_mock) event = loveletter.round.ChooseCardToPlay(current_player) event.choice = other_card card_mock.check_move.assert_called_once_with(current_player, other_card)
def test_countess_choosePrinceOrKing_raises(current_player, other_card_type): give_card(current_player, cards.Countess(), replace=True) give_card(current_player, other_card := card_from_card_type(other_card_type)) event = loveletter.round.ChooseCardToPlay(current_player) with pytest.raises(valid8.ValidationError): event.choice = other_card
def test_prince_emptyDeck_dealsSetAsideCard(current_player: RoundPlayer, target: RoundPlayer, set_aside: cards.Card): current_player.round.deck = Deck([], set_aside=set_aside) give_card(target, CardMockCases().case_generic(), replace=True) move = play_card(current_player, cards.Prince()) target_step = next(move) target_step.choice = target send_gracious(move, target_step) assert target.hand.card is set_aside assert current_player.round.deck.set_aside is None assert not current_player.round.deck
def test_baron_equalOpponent_noneEliminated(started_round: Round, card): player = started_round.current_player opponent = started_round.next_player(player) give_card(player, card, replace=True) give_card(opponent, card, replace=True) move = play_card(player, cards.Baron()) target_step = next(move) target_step.choice = opponent comparison, *_ = send_gracious(move, target_step) move.close() assert len(_) == 0 assert isinstance(comparison, mv.CardComparison) assert player.alive assert opponent.alive
def test_roundEnd_totalTie_allContendersWin(started_round: Round, loser): losers = {loser} if loser is not None else set() winners = set(started_round.players) - losers started_round.deck.stack.clear() for player in winners: give_card(player, cards.Princess(), replace=True) player.discarded_cards = [cards.Guard()] for loser in losers: give_card(loser, cards.Guard(), replace=True) end: loveletter.round.RoundEnd = force_next_turn(started_round) assert end.type == RoundState.Type.ROUND_END assert end.tie_contenders == winners assert end.winners == winners if len(winners) > 1: with pytest.raises(valid8.ValidationError): # noinspection PyStatementEffect end.winner
def test_advanceTurn_emptyDeck_roundEndsWithLargestCardWinner( started_round: Round, set_aside): started_round.deck = Deck([], set_aside=set_aside) increasing_cards = [ cards.Guard(), cards.Priest(), cards.Baron(), cards.Princess() ] for player, card in zip(started_round.players, increasing_cards): give_card(player, card, replace=True) # noinspection PyUnboundLocalVariable winner = player state: loveletter.round.RoundEnd = force_next_turn(started_round) assert state.type == RoundState.Type.ROUND_END assert state.reason == loveletter.round.RoundEnd.Reason.EMPTY_DECK assert state.winners == frozenset({winner}) assert state.winner is winner
def test_countess_playNotPrinceOrKing_noOp(current_player: RoundPlayer, card_type): target = current_player.round.next_player(current_player) with assert_state_is_preserved(current_player.round, allow_mutation={current_player, target}) as mocked_round: player, target = mocked_round.current_player, mocked_round.players[ target.id] give_card(player, cards.Countess(), replace=True) move = play_card(player, card := card_from_card_type(card_type), autofill=False) step = None for _ in card.steps: step = move.send(step) if isinstance(step, mv.PlayerChoice): step.choice = target else: step = autofill_step(step) send_gracious(move, step)
def test_baron_strongerOpponent_selfEliminated(started_round: Round, card1, card2): player = started_round.current_player opponent = started_round.next_player(player) give_card(player, card1, replace=True) give_card(opponent, card2, replace=True) move = play_card(player, cards.Baron()) target_step = next(move) target_step.choice = opponent comparison, elimination, *_ = send_gracious(move, target_step) move.close() assert len(_) == 0 assert isinstance(comparison, mv.CardComparison) assert isinstance(elimination, mv.PlayerEliminated) assert comparison.opponent is opponent assert elimination.eliminated is player assert not player.alive assert opponent.alive
def test_prince_againstPrincess_kills(started_round: Round): player = started_round.current_player victim = started_round.next_player(player) give_card(victim, cards.Princess(), replace=True) victim_card = victim.hand.card deck_before = list(started_round.deck) move = play_card(player, cards.Prince()) target_step = next(move) target_step.choice = victim results = send_gracious(move, target_step) assert tuple(map(type, results)) == ( mv.CardDiscarded, mv.PlayerEliminated, ) assert results[0].target is victim assert results[0].discarded is victim_card assert results[1].eliminated is victim assert not victim.alive assert CardType(victim.discarded_cards[-1]) == CardType.PRINCESS assert list(started_round.deck) == deck_before
def test_prince_againstNonPrincess_dealsCard(started_round: Round, target: RoundPlayer, card_type): player = started_round.current_player give_card(target, card_from_card_type(card_type), replace=True) target_card = target.hand.card deck_before = list(started_round.deck) move = play_card(player, cards.Prince()) target_step = next(move) target_step.choice = target results = send_gracious(move, target_step) assert tuple(map(type, results)) == ( mv.CardDiscarded, mv.CardDealt, ) assert results[0].target is target assert target.alive assert target.hand.card is deck_before[-1] assert target.discarded_cards[ -1 if target is not player else -2] is target_card # Checking second-to-last as last is the Prince card: assert list(started_round.discard_pile)[-2] is target_card assert list(started_round.deck) == deck_before[:-1]
def test_roundEnd_cardTie_maxDiscardedValueWins(started_round: Round, from_player): discard_piles = ( [cards.Priest(), cards.Prince()], # total value: 7 [cards.Guard(), cards.Countess()], # total value: 8 -- best; offset=1 [cards.Guard(), cards.Spy()], # total value: 1 [cards.Spy()], # total value: 0 ) winner = started_round.get_player(from_player, offset=1) card_in_common = CardType.GUARD # everyone will have this card in hand started_round.deck.stack.clear() for player, discard_pile in zip( cycle_from(started_round.players, from_item=from_player, times=1), discard_piles, ): give_card(player, card_from_card_type(card_in_common), replace=True) player.discarded_cards = discard_pile end: loveletter.round.RoundEnd = force_next_turn(started_round) assert end.type == RoundState.Type.ROUND_END assert end.winner is winner assert end.tie_contenders == frozenset(started_round.players) # everyone
def test_playType_present_works(player: RoundPlayer): give_card(player, cards.Prince()) give_card(player, cards.Prince()) autofill_move(player.play_type(card_type := CardType.PRINCE))
def test_playType_notPresent_raises(player: RoundPlayer): give_card(player, cards.Guard()) give_card(player, cards.Princess()) with pytest.raises(valid8.ValidationError): send_gracious(player.play_type(CardType.PRINCE), None)