Count the ace low in Klondike

Rank.order puts the ace at fourteen, which is right for the games this deck
was built for -- in Euchre, Kaiser and the rest it is the highest card there
is. Patience counts it the other way: foundations run ace upwards and columns
run down to an ace.

Using the raw order meant a two could never follow an ace home and an ace could
never be laid on a two, so no foundation could be built past its first card.
Nothing about the deal or the moves would have looked wrong; the game would
simply never have gone out.

patienceOrder is local to this game rather than a change to Rank, because ace
high is correct everywhere else in the app.

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 15:30:15 +00:00
parent 2b09bcdde8
commit 3dbc4b5557
2 changed files with 36 additions and 2 deletions
@@ -112,6 +112,30 @@ class KlondikeRulesTest {
// ---- building ----------------------------------------------------------
@Test
fun `the ace is low here, whatever the rest of the deck thinks`() {
// Rank.order puts the ace at fourteen, because the deck was built for
// trick-taking games where it is the highest card there is. Patience
// counts it as one, and every comparison in this game has to agree —
// otherwise a two can never follow an ace home and the game is
// unwinnable in a way nothing else would show.
assertEquals(14, Rank.ACE.order)
assertEquals(1, Rank.ACE.patienceOrder)
assertEquals(13, Rank.KING.patienceOrder)
var foundation = emptyList<Card>()
Rank.standard.sortedBy { it.patienceOrder }.forEach { rank ->
val card = c(rank, Suit.SPADES)
assertTrue("$rank should go home next", acceptsOnFoundation(foundation, card))
foundation = foundation + card
}
assertEquals(13, foundation.size)
// And a column runs the other way, down to an ace.
assertTrue(buildsDown(c(Rank.ACE, Suit.HEARTS), c(Rank.TWO, Suit.SPADES)))
assertTrue(buildsDown(c(Rank.QUEEN, Suit.HEARTS), c(Rank.KING, Suit.SPADES)))
}
@Test
fun `foundations run ace upwards in one suit`() {
assertTrue(acceptsOnFoundation(emptyList(), c(Rank.ACE, Suit.SPADES)))