Files
tavolo/server/packages/tavolo-scopone
woggioni cc0b31ce6b Let the asso pigliatutto ace capture itself on a bare table
With the rule enabled, an ace played on an empty table goes straight to
the player's capture pile instead of staying on the table: it counts as
the last capture but never scores a scopa. An empty capture request now
matches only that self-capture option, so requesting nothing still can't
satisfy a real capture.
2026-09-23 23:53:40 +08:00
..

tavolo-scopone

Scopone scientifico — the four-player, fixed-partnership Italian card game — as a tavolo-platform game implementation.

Contents

  • state.py — ScoponeState (pure game data: phases, players, hands, table, scores, deadlines), PlayerState, Card, Move, with JSON (de)serialization. No session envelope, no transport, no I/O.
  • engine.py — the pure rules engine: deck, legal captures, plays, auto-play, hand scoring (carte, denara, settebello, primiera, scope, napola), the optional asso pigliatutto capture, hand-end acknowledgements. Deterministic and I/O-free apart from logging, so the whole rule set is unit-testable.
  • errors.py — scopone-specific errors (CardNotInHand); every other failure mode is a shared tavolo.platform.errors subclass.
  • plugin.py — ScoponeEngine(GameEngine): the platform-facing adapter. It translates create/join/websocket actions/deadlines into rules-engine calls and back, validates the target_score/napola/asso_pigliatutto creation options, and extracts the MatchResult (teams, winner, per-player scores and the match summary persisted as the match's JSON result).

Timeouts are constructor arguments (turn_timeout_seconds, hand_ack_timeout_seconds), wired from the environment by the application composition root.

Development (from server/)

.venv/bin/python -m unittest discover -s packages/tavolo-scopone/tests
.venv/bin/python -m mypy -p tavolo.scopone

test_engine.py covers the pure rules; test_plugin.py covers the platform contract (actions, deadlines, serialization, results).