- Deal the hands from the shuffled stack and draw the trump card from it, so the trump card is in nobody's hand and cannot be played - A wizard or jester as trump card means no trump suit (previously a wizard let the dealer choose); remove the trump selection phase, the ChooseTrump action, the trump picker UI and the AI trump actions - Completed tricks carry their round's trump card, so the table keeps showing the matching trump card while the last trick of a round is displayed - Card corners are no longer rotated, so 6 and 9 cannot be confused - Trump label explains why there is no trump (wizard, jester, last round) - Tests: trump card never dealt, special cards give no trump, tricks keep their trump card Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
89 lines
2.6 KiB
Python
89 lines
2.6 KiB
Python
from wizard_game import Suit, card_by_id
|
|
from wizard_game.cards import JESTER_ID_OFFSET, WIZARD_ID_OFFSET
|
|
from wizard_game.rules import lead_suit, legal_cards, round_score, total_rounds, trick_winner
|
|
|
|
|
|
def num(suit: Suit, rank: int):
|
|
return card_by_id(suit.index * 13 + rank - 1)
|
|
|
|
|
|
WIZ1 = card_by_id(WIZARD_ID_OFFSET)
|
|
WIZ2 = card_by_id(WIZARD_ID_OFFSET + 1)
|
|
JES1 = card_by_id(JESTER_ID_OFFSET)
|
|
JES2 = card_by_id(JESTER_ID_OFFSET + 1)
|
|
|
|
|
|
def test_total_rounds():
|
|
assert [total_rounds(n) for n in (3, 4, 5, 6)] == [20, 15, 12, 10]
|
|
|
|
|
|
def test_card_ids_are_consistent():
|
|
card = num(Suit.GREEN, 7)
|
|
assert card.suit is Suit.GREEN and card.rank == 7
|
|
assert WIZ1.is_wizard and JES1.is_jester
|
|
|
|
|
|
def test_lead_suit():
|
|
assert lead_suit([]) is None
|
|
assert lead_suit([num(Suit.RED, 3), num(Suit.BLUE, 5)]) is Suit.RED
|
|
assert lead_suit([JES1, num(Suit.BLUE, 5)]) is Suit.BLUE
|
|
assert lead_suit([JES1, JES2]) is None
|
|
assert lead_suit([WIZ1, num(Suit.BLUE, 5)]) is None
|
|
assert lead_suit([JES1, WIZ1, num(Suit.BLUE, 5)]) is None
|
|
|
|
|
|
def test_must_follow_suit():
|
|
hand = [num(Suit.RED, 1), num(Suit.BLUE, 2), WIZ1, JES1]
|
|
assert set(legal_cards(hand, [num(Suit.RED, 9)])) == {num(Suit.RED, 1), WIZ1, JES1}
|
|
|
|
|
|
def test_free_play_without_lead_suit_cards():
|
|
hand = [num(Suit.GREEN, 1), num(Suit.BLUE, 2), JES1]
|
|
assert set(legal_cards(hand, [num(Suit.RED, 9)])) == set(hand)
|
|
|
|
|
|
def test_free_play_after_wizard_lead():
|
|
hand = [num(Suit.RED, 1), num(Suit.BLUE, 2)]
|
|
assert set(legal_cards(hand, [WIZ1])) == set(hand)
|
|
|
|
|
|
def test_first_wizard_wins():
|
|
trick = [num(Suit.RED, 13), WIZ1, WIZ2]
|
|
assert trick_winner(trick, Suit.RED) == 1
|
|
|
|
|
|
def test_trump_beats_lead_suit():
|
|
trick = [num(Suit.RED, 13), num(Suit.BLUE, 2), num(Suit.BLUE, 5)]
|
|
assert trick_winner(trick, Suit.BLUE) == 2
|
|
|
|
|
|
def test_highest_lead_suit_wins_without_trump():
|
|
trick = [num(Suit.RED, 3), num(Suit.GREEN, 13), num(Suit.RED, 10)]
|
|
assert trick_winner(trick, None) == 2
|
|
assert trick_winner(trick, Suit.YELLOW) == 2
|
|
|
|
|
|
def test_jester_lead_then_suit():
|
|
trick = [JES1, num(Suit.GREEN, 2), num(Suit.RED, 13)]
|
|
assert trick_winner(trick, None) == 1
|
|
|
|
|
|
def test_only_jesters_first_wins():
|
|
assert trick_winner([JES1, JES2], Suit.RED) == 0
|
|
|
|
|
|
def test_round_score():
|
|
assert round_score(0, 0) == 20
|
|
assert round_score(3, 3) == 50
|
|
assert round_score(2, 0) == -20
|
|
assert round_score(1, 4) == -30
|
|
|
|
|
|
def test_trump_suit_from_trump_card():
|
|
from wizard_game.rules import trump_suit
|
|
|
|
assert trump_suit(num(Suit.YELLOW, 4)) is Suit.YELLOW
|
|
assert trump_suit(WIZ1) is None
|
|
assert trump_suit(JES1) is None
|
|
assert trump_suit(None) is None
|