Play onto the pile rather than instead of it
President drew only the set on top. Everything played before it was in the state and simply not on the screen, so beating a pair looked like the previous pair being taken away and replaced rather than covered. The pile is the point of the game — what is under the top set is the history of the round — and it was invisible. The whole pile is now drawn in one loop keyed by position in it. The top set is laid out square and side by side, because that is the set that has to be beaten and the only one that has to be readable; everything under it is pushed out towards the rim of the ground the top set covers, so a corner shows. Buried dead centre is buried, and then drawing it achieves nothing. Keying by position is what makes the transition work. A superseded set is the same composable it always was, so when its target moves from a row slot to the rim it animates from wherever it actually is — no bookkeeping about where it used to sit, and no card vanishing from the row to reappear under the heap a frame later. The throw stays relative to wherever a card belongs, so the two compose: a card lands in its slot, and is shoved aside from it later without the landing having to know. The heap scatter is also now its own pair of bounds, looser than the table's: eight degrees and fifteen per cent of a card width against four and a half and five. This was not cosmetic. At the tight bounds a discard pile of five cards was five cards hidden to within a twentieth of a card width of each other, which reads as one card — Crazy 8s and Golf were technically stacking and visibly not. A card keeps whichever scatter it was given for as long as it lies there, since a card that shuffled sideways the moment something landed on it would be a card moving on its own. Cribbage's series is the same shape of thing and was already keeping its cards, so it gains the landing to match; its hand gains the tilt the other hands have. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_0132V9gE6DF9itz2z3Hn7BK9
This commit is contained in:
@@ -98,6 +98,60 @@ class CardPhysicsTest {
|
||||
assertNotEquals(cardRest(cardSeed(card, 0)), cardRest(cardSeed(card, 1)))
|
||||
}
|
||||
|
||||
/**
|
||||
* A heap is untidier than a card laid in front of a player, and has to be:
|
||||
* at the tight bounds five cards on a discard pile are hidden to within a
|
||||
* twentieth of a card width of each other and the pile looks like one card.
|
||||
*/
|
||||
@Test
|
||||
fun `a heap lies looser than a table but still within bounds`() {
|
||||
deck.forEach { card ->
|
||||
val seed = cardSeed(card)
|
||||
val heap = heapRest(seed)
|
||||
val table = cardRest(seed)
|
||||
assertTrue(abs(heap.tiltDegrees) <= HEAP_TILT_DEGREES)
|
||||
assertTrue(abs(heap.driftX) <= HEAP_DRIFT_FRACTION)
|
||||
assertTrue(abs(heap.driftY) <= HEAP_DRIFT_FRACTION)
|
||||
assertTrue(abs(heap.tiltDegrees) >= abs(table.tiltDegrees))
|
||||
assertTrue(abs(heap.driftX) >= abs(table.driftX))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The two have to agree about everything except how far the card strayed,
|
||||
* or a card would jump when it was drawn one way rather than the other.
|
||||
*/
|
||||
@Test
|
||||
fun `a heap and a table agree about the throw`() {
|
||||
deck.take(6).forEach { card ->
|
||||
val seed = cardSeed(card)
|
||||
assertEquals(cardRest(seed).spinDegrees, heapRest(seed).spinDegrees, 0f)
|
||||
assertEquals(cardRest(seed).lateness, heapRest(seed).lateness, 0f)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A buried card has to end up near the rim of whatever is covering it. One
|
||||
* left in the middle is one nobody can see, and then drawing the pile as a
|
||||
* pile achieves nothing.
|
||||
*/
|
||||
@Test
|
||||
fun `a buried card ends up out where a corner of it shows`() {
|
||||
deck.forEach { card ->
|
||||
val (x, y) = buriedOffset(cardSeed(card), halfWidth = 100f, halfHeight = 40f)
|
||||
val howFarOut = kotlin.math.hypot(x / 100f, y / 40f)
|
||||
assertTrue("$card sat at $howFarOut of the way out", howFarOut >= 0.719f)
|
||||
assertTrue(howFarOut <= 1.001f)
|
||||
}
|
||||
}
|
||||
|
||||
/** Two cards buried under the same set must not end up in the same place. */
|
||||
@Test
|
||||
fun `buried cards do not stack on each other`() {
|
||||
val places = (0 until 6).map { buriedOffset(cardSeed(deck[it], it), 100f, 40f) }
|
||||
assertEquals(places.size, places.toSet().size)
|
||||
}
|
||||
|
||||
/** Every seat's card arrives from that seat, and from a card-width or two out. */
|
||||
@Test
|
||||
fun `a card comes in from its own player's side`() {
|
||||
|
||||
Reference in New Issue
Block a user