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 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Urn6eEBA6XzrnfoibL7faC
This commit is contained in:
Claude
2026-08-08 16:14:06 +00:00
parent deaf85938c
commit 4e7aa98b61
@@ -128,20 +128,37 @@ class SolitaireRulesTest {
} }
@Test @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( val state = FreeCellRules.initialState(
soloConfig("freecell", json.encodeToString(FreeCellOptions())), soloConfig("freecell", json.encodeToString(FreeCellOptions())),
) )
val toCell = FreeCellRules.legalMoves(state, 0) val toCell = FreeCellRules.legalMoves(state, 0)
.filterIsInstance<MoveTo>() .filterIsInstance<MoveTo>()
.first { it.to.kind == org.prolibertate.games.game.freecell.CellKind.CELL } .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) val parked = FreeCellRules.applyMove(state, 0, toCell)
assertEquals(3, parked.freeCellCount) 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( assertTrue(
"the parked card must be playable again", "an ace is the one card a cell can never strand",
FreeCellRules.legalMoves(parked, 0) FreeCellRules.legalMoves(held, 0).contains(
.filterIsInstance<MoveTo>() MoveTo(Place.cell(0), Place.foundation(Suit.SPADES.ordinal), 1),
.any { it.from == Place.cell(toCell.to.index) }, ),
) )
} }