# tavolo-briscola Briscola — the Italian trick-taking game — as a [`tavolo-platform`](../tavolo-platform/README.md) game implementation. Three variants share one rules core: - `briscola` — the classic two-player game; - `briscola_a_quattro` — four-player fixed-partnership briscola; - `briscola_chiamata` — five-player briscola with a calling auction and a secret partner. ## Contents - `state.py` — `BriscolaState` (pure game data: phases, players, hands, stock, face-up briscola, tricks, scores, deadlines), `PlayerState`, `Card`, `TrickCard`, `Trick`, with JSON (de)serialization. No session envelope, no transport, no I/O. - `engine.py` — the pure rules engine for two- and four-player briscola: deck, deals, trick resolution (trump first, then the led suit; strength ace > three > king > horse > jack > 7 > 6 > 5 > 4 > 2), the draw order (trick winner first, the face-up briscola last), card points (ace 11, three 10, king 4, horse 3, jack 2), patta re-deals and the target-score match end, deal-end acknowledgements and auto-play. Deterministic and I/O-free apart from logging, so the whole rule set is unit-testable. - `chiamata.py` — the pure rules engine for five-player briscola chiamata: `ChiamataState`/`ChiamataPlayer`/`Auction` (JSON round-trip), the 8-card deal with no stock, the descending calling auction with point raises, the winner's call (including calling one's own card, which means playing alone), the called-card reveal, single- deal scoring with the 60–60 patta and the auto-actions for timeouts. - `errors.py` — briscola-specific errors (`CardNotInHand`); every other failure mode is a shared `tavolo.platform.errors` subclass. - `plugin.py` — `BriscolaEngine`, `BriscolaQuattroEngine` and `BriscolaChiamataEngine` (`GameEngine`): the platform-facing adapters. The first two validate the `target_score` creation option (61–120, default 61) and extract the `MatchResult` (teams, winner, per-player scores and the match summary persisted as the match's JSON `result`). Briscola chiamata takes no creation options. Timeouts are constructor arguments (`turn_timeout_seconds`, `hand_ack_timeout_seconds`), wired from the environment by the application composition root. Briscola chiamata uses the turn timeout for its auction turns, the called-card choice and the plays: an absent bidder passes, the last player standing with no bid is made to bid the ace, and an absent winner's call names a random suit of the won rank. It never enters the between-deals acknowledgement phase (a single deal ends the match), so the hand-ack timeout is accepted but unused. ## Rules ### Briscola (two-player and four-player) - Three cards per player; the next card is turned face up: its suit is the trump (briscola) for the deal and it is the last card drawn. - The winner of a trick is the highest trump, or the highest card of the led suit when no trump was played. The winner takes the trick and leads the next one. - After each trick everyone draws back up to three cards, starting with the trick winner. - Card points total 120 per deal; a 60–60 deal is a *patta*, its points are discarded and the deal is replayed. The first team to the target score wins; a tie at or above the target is broken by another deal. - Between deals of an unfinished match every player acknowledges the summary (or the hand-end timeout deals on), exactly like scopone. ### Briscola chiamata (five-player) - The whole 40-card deck is dealt out, eight cards each: there is no stock and no face-up card. - Starting with the player after the dealer, each player either passes (leaving the auction for good) or bids a **lower** rank than the standing bid on the ladder *A > 3 > K > H > J > 7 > 6 > 5 > 4 > 2*; the first bidder may bid any rank. Once the standing bid is the two, the auction continues on points instead (62, 64, …): the calling side then has to reach the raised target. The last player standing must bid, so a deal always gets a caller. - The auction winner names any card of the winning rank. If the winner holds it, they **play alone** against the other four; otherwise its holder is the **secret partner** and the two form the calling side. The called card's suit is the trump for the deal. The partner's identity is hidden until the called card is played. - Play follows briscola: the player after the dealer leads, the highest trump (or highest led-suit card) takes the trick and leads the next one; eight tricks exhaust every hand. - The calling side (caller plus partner, or the lone caller) must reach the declared target — 61 unless the auction raised it. With the plain target a 60–60 deal is a patta and is replayed with the next dealer. A match is a single deal, so the two sides map onto the platform's two-team result (Elo rating, match history). ## Development (from `server/`) ```sh uv run python -m unittest discover -s packages/tavolo-briscola/tests uv run mypy -p tavolo.briscola ``` `test_engine.py`/`test_plugin.py` cover the two classic variants; `test_chiamata.py`/`test_chiamata_plugin.py` cover briscola chiamata.