- Offers can go to the whole table (asked in seat order, empty hands skipped) or one seat.
- The asked seat may accept (trade happens at once), decline, or counter with new terms.
- If nobody accepts and there are counters, the offerer takes one or turns them all down (new TRADE_COUNTERS phase).
- AI: fixes an inverted accept test (it weighed what it gives against what it gets backwards), picks the best counter.
- UI: Everyone option in the offer dialog, Counter… in the reply dialog, a counter-choice dialog.
- Tests and docs updated.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018njn2eMPAYqAoE49hGRg2X
Rules
- A road may only start from a crossing where the player has a building, or
where one of their roads ends AND no opponent's settlement or city stands.
roadConnects ignored opponents' buildings, so a road (the computer's included)
could be laid straight past a settlement. Also applies to Road Building.
- Enforce the piece supply: 15 roads, 5 settlements, 4 cities. It was
unlimited.
- Tests: building past a settlement and a city, free roads, own settlement not
blocking, and running out of each piece.
UI
- The layout rescaled the board whenever it became the player's turn, because
the action buttons only existed then. Everything outside the board now has a
fixed height: the action bar always shows every button (disabled, not absent),
the prompt is pinned to two lines, player cards always draw every line, and
the dice total is always present. Rule recorded in docs/UI-catan.md.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JdMNbY5hLR7FjtfEE712xG
Adds the Katan screen on top of the WALA-119 engine, built in separable layers
so the look, wording, layout and interaction can each be changed alone:
- CatanStyle: every colour and proportion (light/dark), via LocalCatanStyle
- CatanText: every word on screen (pure functions of state)
- CatanGeometry: lattice -> pixels and tap hit-testing (pure, unit-tested)
- CatanInteraction: what is tappable and what a tap means, derived only from the
engine's legal-move list (pure, unit-tested)
- CatanBoardView / CatanPanels / CatanDialogs: stateless composables
- CatanScreen: wiring to MatchController, portrait and landscape layouts
- CatanPreviews: Android Studio previews of real positions
- docs/UI-catan.md: how to adapt each layer, rules of the road, known gaps
Wiring: PlayScreen branch, GameSetupScreen options (3-4 players, game to
5/8/10/12), and a GameDescriptor.devPreview flag so dev builds can open Katan
while production still hides it until two-device play is verified.
Tests: CatanGeometryTest, CatanInteractionTest, CatanTextTest, CatalogTest.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JdMNbY5hLR7FjtfEE712xG
The island game as a pure-Kotlin state machine under game/catan/, wired to
the upstream GameRules / GameAi contract and fully unit-tested on the JVM.
- game/catan/: CatanModel (state, moves, phases), CatanBoard (19-hex
geometry, seeded island generation with the 6/8 separation rule, shared
vertex/edge graph), CatanRules (setup, production, the seven and the
robber, domestic and maritime trade, building, development cards,
Longest Road, Largest Army, win detection), CatanAi (a heuristic opponent
that reads only public information).
- GameRules.isLegalMove: a defaulted structural legality check so a game
with a combinatorial move space (Catan's trade offers) is gated the same
way as one with an enumerated move list; MatchController uses it.
- GameCatalog.CATAN: the catalogue entry, listed but not yet available
(descriptor and screen land with the screen task).
- Tests: 51 across CatanBoardTest, CatanRulesTest and CatanAiTest —
geometry invariants, generation balance, setup, production, the
seven/robber, both trade types, development-card timing, Longest Road
edge cases, Largest Army, win detection, and AI games played to a result.
- docs/RULES-catan.md, in the per-game style, with the rule choices and
the known gaps called out.
Two real engine bugs found and fixed while getting the suite green:
VERTEX_EDGES counted each shared edge once per adjacent hex, so an
interior vertex looked like it had six edges (which also double-counted
segments in the Longest Road search and duplicated setup moves); and the
applyRoll seven-transition was a discarded expression, so a seven never
left AWAIT_ROLL. Three test fixtures rolled from the PLAYING phase and two
assumed a two-seat rotation; corrected to the phases and seat order the
engine actually uses.
Verified: ./gradlew :app:testDebugUnitTest --offline — 679 tests, 0 failures.
Co-Authored-By: Paperclip <[email protected]>