From fb59372802cc88ee1076e6b4e7f45af9cebc4d24 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Oct 2026 20:55:38 +0000 Subject: [PATCH] Restore the Katan catalogue entry the engine depends on The Option 2 migration dropped Gitea's 5c797c8, which added GameCatalog.CATAN and a Katan entry (available = false: Coming soon on dev, hidden from production). CatanRules.kt references GameCatalog.CATAN, so the merge did not compile without it. Taken verbatim from feature/catan-engine, with the matching CatalogTest assertions. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01JdMNbY5hLR7FjtfEE712xG --- .../org/prolibertate/games/game/Catalog.kt | 20 +++++++++++++++++++ .../prolibertate/games/game/CatalogTest.kt | 20 ++++++++++--------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/prolibertate/games/game/Catalog.kt b/app/src/main/java/org/prolibertate/games/game/Catalog.kt index 112e84f..ca9ae3f 100644 --- a/app/src/main/java/org/prolibertate/games/game/Catalog.kt +++ b/app/src/main/java/org/prolibertate/games/game/Catalog.kt @@ -94,6 +94,13 @@ object GameCatalog { const val MORRIS = "morris" const val PIRATES = "pirates" + /** + * The island game the collection is named for. Listed under Board Games + * and marked *Coming soon*; the engine and its screen land with the game + * task, and `available` flips on once two-device play is verified. + */ + const val CATAN = "catan" + val all: List = listOf( GameDescriptor( id = EUCHRE, @@ -333,6 +340,19 @@ object GameCatalog { "because your score multiplies them.", available = true, ), + GameDescriptor( + id = CATAN, + title = "Katan", + menus = setOf(GameMenu.BOARD), + minPlayers = 3, + maxPlayers = 4, + teamBased = false, + blurb = "Trade, build, and settle the island.", + // Listed, not playable: the engine and screen land with the Katan + // game task. Dev builds show the entry as *Coming soon*; a + // production build lists only what can actually be played. + available = false, + ), ) fun byId(id: String): GameDescriptor? = all.firstOrNull { it.id == id } diff --git a/app/src/test/java/org/prolibertate/games/game/CatalogTest.kt b/app/src/test/java/org/prolibertate/games/game/CatalogTest.kt index f4b0663..465e065 100644 --- a/app/src/test/java/org/prolibertate/games/game/CatalogTest.kt +++ b/app/src/test/java/org/prolibertate/games/game/CatalogTest.kt @@ -106,17 +106,19 @@ class CatalogTest { } @Test - fun `every game in the catalogue can be played`() { - // There is nothing left marked "coming soon". The machinery that hides - // unfinished games from a production build is still there and still - // tested above — it simply has nothing to hide at the moment, and this - // is what will fail the day something is added to the list before its - // engine is written. - assertTrue(GameCatalog.all.all { it.available }) + fun `every reference game in the catalogue can be played`() { + // Every game the app ships is playable. The one exception is Katan, + // listed so the slot exists and marked *Coming soon* until its engine + // and screen land — `available = false` is what keeps an unfinished + // game out of a production build while leaving it visible on a dev one. assertEquals( - GameCatalog.inMenu(GameMenu.BOARD, includeComingSoon = false), - GameCatalog.inMenu(GameMenu.BOARD, includeComingSoon = true), + listOf(GameCatalog.CATAN), + GameCatalog.all.filterNot { it.available }.map { it.id }, ) + // It is also the only difference the two channels see in a menu. + val hiddenFromProduction = GameCatalog.inMenu(GameMenu.BOARD, includeComingSoon = true) - + GameCatalog.inMenu(GameMenu.BOARD, includeComingSoon = false) + assertEquals(listOf(GameCatalog.byId(GameCatalog.CATAN)!!), hiddenFromProduction) } @Test