예제 #1
0
def test_1_prince_victory():
    """
    player1 has a countess, player0 uses a prince to discard himself and get the
    princess and win.
    """
    game_round = start_round_from_player_cards(
        [cards.Prince(), cards.Handmaid(),
         cards.Guard()],
        [cards.Countess(), cards.Priest()],
        set_aside=cards.Princess(),
        first_player=0,
    )
    player0, player1 = game_round.players
    assert tuple(map(CardType,
                     player0.hand)) == (CardType.PRINCE, CardType.HANDMAID)
    assert tuple(map(CardType, player1.hand)) == (CardType.COUNTESS, )
    assert max(game_round.players, key=lambda p: p.hand.card.value) is player1

    (immunity, ) = play_with_choices(player0, CardType.HANDMAID)
    assert immunity.player is player0

    results = play_with_choices(player1, CardType.PRIEST,
                                mv.OpponentChoice.NO_TARGET)
    assert results == ()

    discarded, dealt = play_with_choices(player0, CardType.PRINCE, player0)
    assert CardType(discarded.discarded) == CardType.GUARD
    assert CardType(dealt.dealt) == CardType.PRINCESS

    end = game_round.state
    assert end.type == RoundState.Type.ROUND_END
    assert max(game_round.players, key=lambda p: p.hand.card.value) is player0
    assert end.winner is player0
예제 #2
0
def test_start_emptyDeckUponStart_raises(new_round: Round):
    new_round.deck = Deck(
        [cards.Guard() for _ in range(new_round.num_players + 1)],
        set_aside=cards.Princess(),
    )
    with pytest.raises(valid8.ValidationError):
        new_round.start()
예제 #3
0
def start_round_from_player_cards(*player_cards: Sequence[cards.Card],
                                  first_player: int,
                                  set_aside=None):
    """
    Create a round that will deal to each player the specified sequence of cards.

    The deck is built in a way so that player i starts with player_cards[i][0] and
    is dealt the cards in player_cards[i][1:] in order at each successive turn.
    This assumes that no player is eliminated before the last card in player_cards[i]
    is dealt to them.

    :param player_cards: A varargs sequence of card sequences that each player
                         will receive during the round. The first list corresponds
                         to player 0, then player 1, and so on.
    :param first_player: ID (index) of the first player to play in the round. This is
                         (also) needed to build the deck so that player_cards[i] always
                         corresponds to player i (*not* the i-th player to play).
    :param set_aside: Which card to set aside in the deck. Default is a new instance of
                      :class:`cards.Princess`.
    :return: A round with the number of players and deck deduced from ``player_cards``.
    """
    player_cards = player_cards[first_player:] + player_cards[:first_player]
    stack = list(mitt.roundrobin(*player_cards))[::-1]
    deck = Deck(stack, set_aside=set_aside or cards.Princess())
    round = Round(len(player_cards), deck=deck)
    round.start(first_player=round.players[first_player])
    return round
예제 #4
0
def test_chancellor_oneCardInDeck_onlyUsesOneCard(started_round: Round):
    deck_card, set_aside = cards.Spy(), cards.Princess()
    started_round.deck = Deck([deck_card], set_aside=set_aside)
    player = started_round.current_player
    move = play_card(player, cards.Chancellor())
    card_choice = next(move)
    assert len(card_choice.options) == 2
    assert set(card_choice.options) == {player.hand.card, deck_card}
    assert started_round.deck.set_aside is set_aside

    # cleanup to avoid exception when .close() is called
    autofill_move(move, start_step=card_choice)
예제 #5
0
    def round_runner(g):
        game_round = start_round_from_player_cards(
            [cards.Guard(), cards.Baron()],
            [cards.King(), cards.Princess()],
            first_player=0,
        )
        object.__setattr__(g.state, "round", game_round)  # work around frozen dataclass
        player0, player1 = game_round.players

        play_with_choices(player0, CardType.GUARD, player1, cards.Princess)
        play_random_move(player1)

        end = game_round.state
        assert end.type == RoundState.Type.ROUND_END
        assert end.winner is player0
예제 #6
0
def test_3_king_win():
    """
    player1 draws the Princess but is forced to relinquish it because they have a King.
    """
    game_round = start_round_from_player_cards(
        [cards.Guard(), cards.Baron()],
        [cards.King(), cards.Princess()],
        first_player=0,
    )
    player0, player1 = game_round.players

    play_with_choices(player0, CardType.GUARD, player1, cards.Princess)
    play_random_move(player1)

    end = game_round.state
    assert end.type == RoundState.Type.ROUND_END
    assert end.winner is player0
예제 #7
0
def test_5_baron_suicide():
    """
    player0 has Baron-Baron and everyone else has higher cards, so they die.
    """
    game_round = start_round_from_player_cards(
        [cards.Baron(), cards.Baron()],
        [cards.Countess(), cards.Handmaid(),
         cards.Guard()],
        [cards.Handmaid(), cards.Princess(),
         cards.Guard()],
        first_player=0,
    )
    player0, player1, player2 = game_round.players

    play_random_move(player0)
    assert not game_round.ended
    assert not player0.alive
    assert player1.alive
    assert player2.alive
예제 #8
0
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
예제 #9
0
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
예제 #10
0
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
예제 #11
0
def test_4_princess_suicide():
    """
    player1 holds a Princess but has to eliminate themselves because they draw a Prince
    and the opponent is immune.
    """
    game_round = start_round_from_player_cards(
        [cards.Handmaid(), cards.Baron(),
         cards.Guard()],
        [cards.Princess(), cards.Prince(),
         cards.Countess()],
        first_player=0,
    )
    player0, player1 = game_round.players

    play_with_choices(player0, CardType.HANDMAID)
    play_random_move(player1)

    assert game_round.ended
    assert game_round.state.winner is player0
    assert CardType(
        game_round.deck.take()) == CardType.GUARD  # assert no card dealt
예제 #12
0
def test_6_guard_win():
    """A chain of Guard eliminations that ends in player 3 winning"""
    game_round = start_round_from_player_cards(
        [cards.King()],
        [cards.Countess(), cards.Guard()],
        [cards.Princess(), cards.Guard()],
        [cards.Guard(), cards.Guard()],
        first_player=1,
    )
    player0, player1, player2, player3 = game_round.players

    play_with_choices(player1, CardType.GUARD, player0, CardType.KING)
    play_with_choices(player2, CardType.GUARD, player1, CardType.COUNTESS)
    play_with_choices(player3, CardType.GUARD, player2, CardType.PRINCESS)

    assert game_round.ended
    assert not player0.alive
    assert not player1.alive
    assert not player2.alive
    assert player3.alive
    assert game_round.state.winner is player3
예제 #13
0
def test_princess_eliminatesSelf(current_player: RoundPlayer):
    player_mock = mock_player(current_player)
    play_card(player_mock, cards.Princess())
    player_mock.eliminate.assert_called_once()
    assert not current_player.alive
예제 #14
0
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)
예제 #15
0
def test_deck_containsSetAside():
    deck = Deck([], set_aside=(set_aside := cards.Princess()))