Katan: Cities & Knights docs, knight menu for any own knight, tidier player card

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016eTor2tpxKb4dXbd8RqnvZ
This commit is contained in:
Claude
2026-10-17 14:40:49 +00:00
parent e344d1d817
commit c8368416c4
11 changed files with 328 additions and 15 deletions
@@ -2,6 +2,7 @@ package org.prolibertate.games.ui.game.catan
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.prolibertate.games.game.GameCatalog
@@ -261,4 +262,26 @@ class CatanCkInteractionTest {
listOf("setup", "road", "build SETTLEMENT", "build CITY", "knightMenu", "improve", "bankTrade", "roll", "endTurn")
.forEach { assertTrue("never exercised: $it in $total", (total[it] ?: 0) > 0) }
}
@Test
fun `a sleeping knight with nothing to do can still be tapped for its menu`() {
val base = CatanRules.initialState(config(3, 5L))
.copy(phase = CatanPhase.PLAYING, turn = 0, turnNumber = 1)
val state = base.copy(
ck = base.ck!!.copy(knights = listOf(org.prolibertate.games.game.catan.Knight(10, 0, 1))),
)
val legal = CatanRules.legalMoves(state, 0)
assertTrue("no grain, so nothing to do", CatanInteraction.knightActions(legal, 10).isEmpty())
val targets = CatanInteraction.targets(state, legal, null, null, localSeat = 0)
assertTrue(10 in targets.idleKnights)
assertTrue("no tap ring for a knight with nothing to do", 10 !in targets.knights)
assertTrue(10 in targets.tappableVertices)
assertEquals(
TapOutcome.PickKnight(10),
CatanInteraction.onVertexTap(10, legal, null, null, ownKnights = setOf(10)),
)
// On somebody else's turn the legal list is empty and nothing is offered.
assertTrue(CatanInteraction.targets(state, emptyList(), null, null, localSeat = 0).idleKnights.isEmpty())
}
}