Files
fool-cardgame/docs/DECISIONS.md
T
ftcandClaude Opus 5 c980440856 M0: план разработки, техническая структура, каркас проекта
- docs/PLAN.md — план по этапам, обновляется по мере работы
- docs/TECHNICAL.md — слои, карта папок, контракты, рабочие процессы
- docs/DECISIONS.md — журнал решений, принятых самостоятельно
- разрешение 1080x1920, fit-width (портрет, 4:3..21:9)
- каркас assets/scripts (core / modules / app / ui)
- headless-тесты на vitest + strict typecheck + защита чистоты core
- Rng: детерминированный генератор и перемешивание

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 10:28:49 +03:00

4.5 KiB
Raw Blame History

Decision log

Choices made while implementing the specs, recorded so they can be challenged later. Each entry states what the specs left open, what was chosen and why.

Format: YYYY-MM-DD · area · decision.


2026-09-13 · Rules · Turn passes past a defender who took

GAMEPLAY.md says "after drawing cards move is passed to next player in clockwise order", but does not say what happens when the defender took the cards.

Decision. The defender who took is skipped: the next attacker is the player after the defender. In 1v1 this means the same player attacks again — the standard rule, and the one that makes taking a real cost.

2026-09-13 · Rules · Interpretation of the add-card limits

GAMEPLAY.md gives three limits on attacking cards. The second one ("there should not be more attacking cards than card amount in defending player's hand") is ambiguous about when it is measured.

Decision. A card may be added only if all three hold at the moment of adding:

  1. table.length < 6 (< 5 on the very first turn of the game);
  2. unbeatenCount < defenderHandSize — where unbeatenCount counts attack cards with no defence on them, and defenderHandSize is the defender's hand at that moment. Once the defender has declared a take, their hand no longer shrinks, so this freezes naturally;
  3. its rank matches the rank of some card already on the table, attack or defence alike.

The first attacking card of a turn is exempt from (3) — there is nothing on the table to match.

2026-09-13 · Rules · Attack order is serialised

In a real game attackers may throw cards in at any moment, concurrently with the defender thinking. Modelling genuine concurrency buys nothing for 1v1 against a bot and makes the state machine much harder to test.

Decision. The core is a strict turn-based state machine with an explicit "who may act now" set. Attackers are polled for additions only when there are no unbeaten cards on the table, or after a take has been declared. This is behaviourally identical for 1v1 and extends cleanly to N players.

2026-09-13 · Architecture · Rules core is engine-independent

Decision. Everything under assets/scripts/core/ is plain TypeScript with no cc import, no Component, no scene access, and no wall-clock time. The state machine is a pure reducer apply(state, action) -> { state, events } over a seeded RNG.

Why. It makes the entire rule set verifiable with npm test in a second, on any machine, with no editor running — which is the only practical way to build this unattended. It also leaves the door open for server-authoritative multiplayer later without a rewrite.

2026-09-13 · Architecture · Bots consume a restricted PlayerView

Decision. A bot never receives GameState. It receives a PlayerView: its own hand, the table, the trump card, counts (deck size, each opponent's hand size) and the discard count.

Why. It makes cheating structurally impossible rather than a matter of discipline, and a PlayerView is exactly the payload a future network protocol would send to a client.

2026-09-13 · Architecture · Savegame sections are self-registering

ARCHITECTURE.md asks for a save composed of independent classes, keyed by class name.

Decision. Sections implement ISaveSection { readonly key; save(); load(data) } and register with SaveManager. The key is an explicit string constant, not constructor.name, because minification in release builds renames classes and would silently orphan every existing save.

2026-09-13 · Presentation · 1080×1920 design resolution, fit-width

UI.md requires portrait, 4:3 to 21:9. ART.md fixes the art budget at 1080 px wide.

Decision. Design resolution 1080×1920 with fitWidth = true, fitHeight = false, so the width is always exactly 1080 design units and taller screens simply reveal more vertical space. Layout is anchored with widgets to top/bottom, the play area centred, and the safe-area inset respected on the top and bottom bars.

2026-09-13 · Art · Vector deck from local/, licence recorded

local/Playing Cards holds the Chris Aguilar "Vector Playing Cards" set (also mirrored on Wikimedia Commons), which is LGPL-3.0.

Decision. Use the 36 faces needed for a durak deck, rendered from the SVG sources so the downscale to the 1080-wide budget stays sharp. Attribution and licence text are recorded in assets/art/cards/ATTRIBUTION.md. The card back, table surface and UI chrome are not in that set and are authored for this project.