From 4e7aa98b61cf067af6b66b8ca9093a9f9f81b2ed Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 8 Aug 2026 16:14:06 +0000 Subject: [PATCH] A cell can strand a card, and the test said otherwise The test asserted that a card parked in a free cell can always be played again. It cannot. A cell holds a card nothing on the tableau will take and that is not yet ready for a foundation, and it stays there -- that is the whole danger of the cells rather than a fault in them, and the reason four of them is a game worth playing. What is worth pinning is what parking actually does: the card leaves the column and is in the cell afterwards. The one card a cell can never strand is an ace, since a foundation will always have it, so that gets a test of its own. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Urn6eEBA6XzrnfoibL7faC --- .../game/solitaire/SolitaireRulesTest.kt | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/app/src/test/java/org/prolibertate/games/game/solitaire/SolitaireRulesTest.kt b/app/src/test/java/org/prolibertate/games/game/solitaire/SolitaireRulesTest.kt index 135b479..c4d2d48 100644 --- a/app/src/test/java/org/prolibertate/games/game/solitaire/SolitaireRulesTest.kt +++ b/app/src/test/java/org/prolibertate/games/game/solitaire/SolitaireRulesTest.kt @@ -128,20 +128,37 @@ class SolitaireRulesTest { } @Test - fun `a card in a cell can come back out`() { + fun `parking a card takes it off the column and into the cell`() { val state = FreeCellRules.initialState( soloConfig("freecell", json.encodeToString(FreeCellOptions())), ) val toCell = FreeCellRules.legalMoves(state, 0) .filterIsInstance() .first { it.to.kind == org.prolibertate.games.game.freecell.CellKind.CELL } + val column = toCell.from.index + val card = state.tableau[column].last() + val parked = FreeCellRules.applyMove(state, 0, toCell) assertEquals(3, parked.freeCellCount) + assertEquals(card, parked.cells[toCell.to.index]) + assertEquals(state.tableau[column].size - 1, parked.tableau[column].size) + // Deliberately not asserting the card can come back out. A parked card + // that nothing will take is stranded, and that is the whole danger of + // the cells rather than a fault in them. + } + + @Test + fun `an ace in a cell can always go home`() { + val base = FreeCellRules.initialState( + soloConfig("freecell", json.encodeToString(FreeCellOptions())), + ) + val ace = c(Rank.ACE, Suit.SPADES) + val held = base.copy(cells = listOf(ace, null, null, null)) assertTrue( - "the parked card must be playable again", - FreeCellRules.legalMoves(parked, 0) - .filterIsInstance() - .any { it.from == Place.cell(toCell.to.index) }, + "an ace is the one card a cell can never strand", + FreeCellRules.legalMoves(held, 0).contains( + MoveTo(Place.cell(0), Place.foundation(Suit.SPADES.ordinal), 1), + ), ) }