Two more games on the existing framework — no changes were needed to the
lobby, networking, settings or update layers, which is what the shared
GameRules/GameAi contract was for.
President
- Threes low, twos high. Lead any number of one rank; follow with the
same count of a higher rank, or pass. When everyone has passed the
pile comes down and the last player to play leads again.
- Toggles: player count, rounds, twos clear the pile, four of a kind
bombs, and the between-round card exchange.
- Plays are offered as whole sets rather than by selecting cards. A set
is the unit of the game, so choosing from the legal sets is both
easier to operate and impossible to get wrong.
Golf
- 4, 6 or 9 card grids. Draw from stock or discard, then either swap the
card in or — only if it came off the stock — throw it and turn one of
your own over. A card taken from the discard pile has to be used.
- Matching columns cancel to nothing; on the 3x3 board rows do too, but
not on the shallower grids where three cards are not a line.
- Face-down cards are hidden from everyone including their owner, which
is the point of the game: viewFor masks them with a fixed placeholder
so the real card never reaches the device that has not turned it over.
Both engines are pure Kotlin and unit tested — 71 tests now, covering
ranking, legal moves, pile and hole resolution, scoring, redaction, wire
round-trips, and full random and AI playthroughs. The Golf test also
checks the AI actually beats random play rather than merely being legal.
Also widened the setup screen's option chips to wrap: the reveal-count
row carries up to ten, and a chip off the edge of the screen is a
setting that cannot be changed — the same failure as the Euchre Pass
button.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qjfMiPUDshdKEUa6vxqzN
- The launcher icon is a single square of the tartan, drawn as a vector
so it stays sharp at any density and ships no PNGs. The adaptive
icon's foreground is deliberately empty: the cloth is the icon.
- Tartan.kt draws the sett as warp, then as weft at half opacity. That
overlap is what gives the blended squares and reads as woven cloth
rather than a printed grid, and it is reused by both the icon and the
splash.
- The app opens on the tartan under "Pro Libertate Games" in Uncial
Antiqua, holds two seconds, then fades. It is an overlay rather than a
destination, so the menu is already composed behind it and the fade
reveals a live screen. The window background is set to a dark red so
launch does not flash white before Compose draws.
Two things to be aware of:
- WallaceSett is an approximation. It reads as Wallace — bold red and
black check with a narrow gold overstripe — but the registered
threadcount could not be verified here, so the counts were chosen to
look right. They are plain data and can be swapped for the registered
ones without touching anything else.
- Uncial Antiqua is bundled under the SIL Open Font License 1.1, with
the full licence at docs/licenses/UncialAntiqua-OFL.txt. The OFL
requires that to be distributed with the font, so it must not be
separated from it.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qjfMiPUDshdKEUa6vxqzN
A release listed all eleven games with nine of them marked "Coming
soon", so most of the menu was a dead end for anyone installing from the
production channel. Production now lists only what can be played; dev
builds still show everything, which is where seeing the roadmap is
useful.
The menu reads the installed APK's own version name, so this follows the
build rather than the update channel selected for the future — a dev
build shows the full list even if its owner has switched back to
production for updates.
CatalogTest pins both views, including that filtering never empties a
category and strands its heading.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qjfMiPUDshdKEUa6vxqzN
Update channels
- ci.yml now publishes each green push to dev as a prerelease tagged
v1.0.<n>-dev, so the dev channel has something to install. Workflow
artifacts could not serve this: downloading one needs authentication,
which the app does not have.
- Prereleases specifically, because GitHub's "latest release" endpoint
skips them — a production install can never be handed a dev build.
Pull requests build and check but never publish.
- Settings gains a channel picker. The two channels are numbered by
separate workflow run counters, so versions are only compared within a
channel; the app reads the -dev suffix in its own versionName to know
where it stands, and treats a channel change as an explicit switch. The
screen warns that such a switch can be a downgrade Android will refuse.
- PLG_RELEASE becomes PLG_CHANNEL, naming the channel rather than a flag.
Euchre
- Cards in a trick now sit on the side of the table belonging to whoever
played them, rotated to face them, labelled You / Left / Partner /
Right. Previously they were a flat row tagged with seat numbers, which
made it hard to tell who had played what.
- Bidding says what it will actually do. As dealer the button reads "Pick
it up" rather than "Order up", since the turn card comes to your hand,
and a line of explanatory text spells out the consequence either way.
Sequence
- Playable squares get a much heavier outline, scaled off cell size and
in a fixed amber that reads against a white card, a green corner and a
chip alike. The old 2dp theme-coloured border was hard to see.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qjfMiPUDshdKEUa6vxqzN
Two ways the updater could have served or blocked the wrong build:
- release.yml also triggers on workflow_dispatch, which can be aimed at
any branch from the Actions UI. That would have built dev code and
published it as a real Release, which every install would then offer to
download. The job now refuses to run off anything but main.
- versionCode came from GITHUB_RUN_NUMBER, but that counter is per
workflow, so the dev pipeline had its own independent sequence. A debug
APK installed from a CI artifact already carried a higher versionCode
than the first several releases would, and the updater's check is
latest <= installed, so those users would have been told they were up
to date indefinitely. Only release.yml now sets PLG_RELEASE, and only
that stamps a real version; everything else stays at 1.0.0-dev.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qjfMiPUDshdKEUa6vxqzN
First vertical slice: the whole shell plus two games playable end to end,
so every layer is exercised before the other nine games are built on it.
Games
- Euchre: bowers, ordering up, dealer discard, going alone, stick the
dealer, and full scoring. Rule variants (deck size, points to win,
stick the dealer, going alone) are toggles in game setup.
- Sequence: two-eyed and one-eyed jacks, free corners, locked sequences,
the shared-chip limit, and dead-card exchange. Teams, players per team
and the sequence target are toggles.
- The board layout in SequenceBoard is generated, not the commercial
board — it holds every structural property the rules need, but does not
match a physical board. Documented in docs/RULES-sequence.md.
Multiplayer
- One transport abstraction over newline-delimited JSON, implemented
twice: LAN via NSD discovery and TCP, Bluetooth via Classic RFCOMM.
A lobby advertises on both at once, so a table can mix them.
- Host-authoritative: clients send move intents, the host re-validates
every one against the rules, and each client receives a state redacted
for its own seat so hidden information never crosses the wire.
- Seats start as AI and are handed to people as they join, which is what
makes any mix of humans and AI work without a separate code path.
Shell
- Main menu lists all eleven games; the nine without engines are marked
coming soon and are driven entirely by GameCatalog.
- Settings: sound, animation speed (one multiplier drives card movement
and AI thinking time), and OTA updates from the latest GitHub release.
- Layouts measure available space rather than assuming an orientation.
The game package is free of Android types, so the rules engines and AI
run under plain JUnit; 43 tests cover ranking, following suit, scoring,
sequence detection, redaction, wire round-trips and full random and AI
playthroughs.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qjfMiPUDshdKEUa6vxqzN