Commit Graph
5 Commits
Author SHA1 Message Date
Claude 7939395c3c Install dev and production side by side, in the hunting sett
A dev build now installs under its own applicationId, org.prolibertate.games.dev,
so it is a separate app to Android and sits beside the production copy instead
of replacing it. Each channel still updates itself normally, because an update
within a channel keeps the same package.

Three things move together off one isDevBuild flag, because a dev package
wearing the production name and colours is exactly the mix-up that having both
installed is meant to prevent:

  - applicationId gets a .dev suffix;
  - the launcher label becomes "Pro Libertate Games DEV";
  - the cloth becomes Wallace Hunting, the same threadcount with green where
    the clan sett has red.

The name and the colours reach the resources through resValue, so app_name,
tartan_field, splash_background and ic_launcher_background are generated by the
build rather than declared in res/values. The icon vectors reference
@color/tartan_field instead of a literal, which is how one set of vectors serves
both colourways without a second copy of the paths. BuildConfig.DEV_BUILD
carries the same flag into Kotlin, where AppSett picks the Compose sett for the
splash, and WallaceHuntingSett is derived from the same threadcount builder as
WallaceSett so the two cannot drift.

versionName now tracks isDevBuild rather than the CI stamp alone, so an
unstamped local build cannot claim a channel its applicationId contradicts.

Separate packages also mean a channel switch can no longer be refused as a
downgrade; the settings copy and the README said it could, and now say what
actually happens.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JDuAayWXLRoUNTsfE79Mg1
2026-08-06 22:07:32 +00:00
Claude 43394b8d45 Remove Bluetooth from multiplayer
Multiplayer now runs over Wi-Fi (LAN) only.

- Delete BluetoothTransport and drop it from LobbyController's transport
  list, leaving LanTransport as the sole transport.
- Drop TransportKind.BLUETOOTH and the now-unused RFCOMM_UUID constant.
- Remove the BLUETOOTH/BLUETOOTH_ADMIN/BLUETOOTH_CONNECT permissions and
  the android.hardware.bluetooth feature from the manifest, along with
  the runtime permission request in MainActivity and the
  requestBluetoothPermissions hook on AppEnv.
- Update lobby copy so an empty transport list and an empty host list
  talk about Wi-Fi rather than pairing, and refresh the comments and
  README sections that described two transports.

The transport abstraction itself is kept: everything after the handshake
was already transport independent, so adding another one later needs no
changes above LanTransport.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YEsqYAMJKUJoM7UAavm169
2026-08-06 21:38:35 +00:00
Claude 1bcd2a951e Add dev/production update channels, clearer Euchre table, bolder Sequence highlight
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
2026-08-06 00:18:59 +00:00
Claude 80ff178437 Pin OTA releases to main and stop dev builds outranking them
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
2026-08-05 23:47:20 +00:00
Claude 487c68419e Add app shell with Euchre and Sequence, LAN/Bluetooth play
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
2026-08-05 22:37:05 +00:00