Adds settlement/city/dev-card build options to the personal panel, shown
when the local seat's resources meet the build costs. Follows the same
tap-to-commit ≥48dp pattern as the rest of the panel.
Co-Authored-By: Paperclip <[email protected]>
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]>
The bootstrap rebranded the app to Pilgrims of Katan (WALA-118 review);
the decision is to keep the upstream's own identity instead.
- Title and splash: the upstream originals restored exactly — the Wallace
tartan splash under the "Pro Libertate Games" uncial wordmark
(SplashScreen.kt, Tartan.kt), the tartan launcher icon, and the
Theme.ProLibertateGames window theme. The game screens go back to the
upstream WallaceGold/WallaceRed accents the tartan is woven from.
- Names and colours: launcher names back to "Pro Libertate Games" /
"Pro Libertate Games DEV"; the channel colours back to the clan red /
hunting green setts (resValue tartan_field and friends). The installed
identity stays ca.wallacenet.pilgrimsofkatan (+ .dev) — that is the
package, not the brand.
- Catalogue: Katan is listed under Board Games (3-4 players, original
blurb, no third-party marks) with available = false, so dev builds show
it as "Coming soon" and a production build hides it until its engine
and screen land.
- Docs: README/CLAUDE.md/docs/CI.md updated to the restored identity;
CatalogTest's invariant now names Katan as the one deliberate exception
rather than asserting nothing is unfinished.
Structural bootstrap untouched: applicationId, OTA repointed at the Gitea
releases, CI workflows, version stamping.
Verified: ./gradlew assembleDebug and testDebugUnitTest green — 628 tests,
0 failures.
Co-Authored-By: Paperclip <[email protected]>
A live publish on git.wallacenet.ca kept coming back invisible to the updater:
the create accepted "draft": false, and the release was still stored as a
draft once the APK was attached — so the anonymous list the app reads came
back empty even though every publish step reported success.
The script now attaches first, then reads the release back and PATCHes the
state if it did not stick, failing loudly if the correction is refused. A
draft is not a channel a preview build can silently become.
Also lists all 22 catalogue games in the README's table; seven were missing,
which read as "the app has 15 games".
Verified against the live instance: anonymous list shows
v1.4.1001-dev as a published prerelease with a tag-named asset, the
production /releases/latest correctly returns 404 while only a prerelease
exists, and an anonymous download through the URL the app builds matches the
built APK byte for byte.
Co-Authored-By: Paperclip <[email protected]>
Two things the first live release check on git.wallacenet.ca showed:
- The publish script uploaded the APK under whatever the build called it
(app-debug.apk), which is the name the updater only finds by its fallback
rule. The script now names the asset after its tag, so the primary rule —
"the asset whose name contains the tag" — is the one that fires.
- The instance answers for two host names and reports asset URLs on the one
it treats as canonical, so the app would have fetched its release list from
git.wallacenet.ca and its APK from elsewhere. onReportedHost() now keeps the
path the server chose and puts the download on the host the app already
trusts, tested in UpdatePolicyTest.
Co-Authored-By: Paperclip <[email protected]>
Import of ProLibertateGames (upstream main, GPL-3.0) rebranded for
Wallacenet and repointed at git.wallacenet.ca.
- Identity: applicationId ca.wallacenet.pilgrimsofkatan (+ .dev for the dev
channel), launcher names "Pilgrims of Katan" / "Pilgrims of Katan DEV",
neutral hexagon branding replacing the Wallace tartan. Uncial Antiqua keeps
its OFL licence, and the GPL-3.0 LICENSE plus upstream attribution stay.
- OTA: Updater.kt now reads this repo's own Gitea releases
(/api/v1/repos/devadmin/PilgrimsOfKatan/releases...) and BuildConfig.
OTA_ENABLED is on; Gitea answers the same JSON shape the code already parsed.
- Build numbers: versionCode = CI run number + plgVersionRunOffset (1000),
with the tag and versionName derived from the same figure. The offset is
permanent, because Gitea Actions restarts run numbers at 1 and a reset would
otherwise make Android reject the next build as a downgrade.
- CI: ci.yml publishes a dev prerelease from dev, release.yml a production
release from main, both through scripts/publish-release.sh (Gitea REST API,
runnable by hand until an Actions runner is registered).
- Docs: docs/CI.md records the channel, numbering and runner decisions;
docs/README.md seeds the per-game RULES-* conventions; CLAUDE.md carries the
agent ground rules.
Verified: ./gradlew assembleDebug and testDebugUnitTest green on JDK 17 /
compileSdk 34, both variants stamped, installing side by side under the new
identity.
Co-Authored-By: Paperclip <[email protected]>