Skip to content

Cascade & scoring

A winning hand doesn’t pay chips directly. It produces a cascade — a deterministic 7-step sequence of scoring events that the resolver emits in order. The cascade animator renders them at 400ms beats (800ms in slow-mode), and the harness asserts compliance against this canonical event list.

The resolver is pure: same HandSpec → same events. Run state inspection happens in the engine, not here.

#EventWhat it does
1PipScorePer card, hard-pip chips (Ace = 1).
2StickerScoreSticker glued to the card (foil / holo / poly / negative).
3HandArchetypeScoreArchetype contribution — chips and additive mult.
3aLongGameApplied(If hits > 0.) Trace beat for the Long-Game scaling.
4HouseRuleScoreDeputy / Pale-Jack signature mult-factor.
5ArcanumAdditivePass A: arcanum chip + additive mult, in tray order.
5bArcanumMultiplicativePass B: arcanum ×mult, in tray order. Sticker ×mults fire here too.
6MercyCapFireIf mult > mercyCap, clamp and emit.
6aDeathsHesitationFire(If a face-card bust w/ softener on.) Halves the score.
7FinalScorechips × mult, rounded.

Archetype mult is scaled by 1 + 0.3 × min(hitCount, 3) — clamped at 3 hits, factor curve 1.0 / 1.3 / 1.6 / 1.9 / 1.9. Applied to the archetype mult only; house rule and arcanum mult contributions are post-LG.

Long-Game Multiplier →

Bust on a face card (J/Q/K), softener on → run the full cascade as if cleared, then halve the FinalScore. Other busts still zero.

Death’s Hesitation →

When 2+ ×mult contributions queue AND chips ≥ engineMomentMinChips, the cascade tags the first multiplicative event as the engine moment. The animator slows down at that beat — the dealer notices, the player breathes. The dealer voice fires a special engineMoment line.

It’s the same shape as the harness. Decision-impact tests build explicit HandSpec instances and assert against the List<ScoringEvent> output. If a charm’s behavior changed, the test would fail. If the cascade rendered differently in the UI than the harness measured, the golden tests would diverge.

  • lib/sim/cascade_resolver.dart — the resolver.
  • lib/sim/scoring_event.dart — the sealed event types.
  • lib/ui/cascade_animator.dart — the 400ms-beat renderer.
  • lib/sim/harness/batch_runner.dart — Monte Carlo entry point.