Concepts → CoC sanity as gambler's ruin
Call of Cthulhu sanity as gambler's ruin — when the math says you're going to zero
An Investigator's sanity pool is mathematically identical to an HP pool with per-encounter damage and slow trickle healing. The same engine machinery that answers "how many strikes until the monster dies?" answers "how many sessions until the investigator breaks?" — because both questions are the same Markov walk on cumulative loss vs. pool depth. The narrative wrapper is different; the math is identical. And in nearly every published CoC scenario, the cure ratio is set so the walk drifts to zero with probability one. The interesting question isn't whether your investigator will go insane — it's how long it'll take, and what's in the survivors curve.
The short answer
Map sanity onto HP and CoC's sanity-loss problem becomes a vanilla rounds-to-kill chain:
| HP-side concept | CoC sanity equivalent |
|---|---|
| Starting HP | Starting sanity (typically POW × 5) |
| Per-round damage roll | Per-encounter sanity loss (e.g. 1d6 for a Mythos shock) |
| Per-round healing | Per-downtime recovery (e.g. +1 per week of psychotherapy) |
| Max rounds | Number of in-game intervals to simulate |
| "Killed by round N" | "Insane by encounter N" |
Hand this to the engine's existing
rounds_to_kill and it returns the full
"rounds-until-zero" distribution — not just the mean.
{:ok, r} = Diceplots.Engine.rounds_to_kill(
["1d6"], # per-encounter sanity loss
["1"], # per-encounter recovery (off-table)
50, # starting sanity
20 # max encounters to simulate
)
r.expected_rounds # E[encounters until insanity]
r.cumulative # P(insane by encounter N) for N = 1..max
The cure ratio decides whether the chain converges
Same dichotomy as the HP problem (covered in expected strikes to kill):
- E[recovery] ≥ E[loss]: the chain doesn't absorb at zero in finite expectation. The investigator's sanity wanders around or trends back up. Player can take unlimited Mythos exposure in the long run.
-
E[recovery] < E[loss]: strict drift toward
zero. The chain absorbs at insanity with probability 1; the
only question is when. The expected time to insanity is
bounded by
(starting sanity) / (E[loss] − E[recovery]).
Most published CoC scenarios pace per-investigation sanity loss
at 1d6 or 1d10 per scene of Mythos
contact, and per-downtime recovery at +1 per week of
psychotherapy. Investigation pacing typically front-loads
Mythos contact and back-loads downtime. The cure ratio rarely
favours the player. The walk drifts; the only design lever is
how long the player has before the descent.
Variance changes the whole picture
Two investigators, same starting sanity 50, both facing
15 sanity-loss encounters with the same expected loss per
encounter (3.5). One faces 1d6 per encounter; the
other faces 2d4 − 1.5 for the same mean but lower
variance. Same expected total loss (52.5). Same expected ending
sanity (-2.5).
But the
distributions are different. The high-variance
investigator (1d6) has a longer tail in both
directions — they might stagger out at sanity 12 if the dice
run cold, or hit zero by encounter 9 if they run hot. The
low-variance investigator (2d4 − 1.5) clusters
tightly around the mean — they reliably hit zero between
encounters 14-15, with very little chance of finishing on
either side of that band.
For a published scenario, the variance picture matters more than the mean. The "this scenario is rough on sanity" warning that authors put on adventures usually translates to "the variance of per-encounter loss is high enough that some investigators will absorb early". A scenario with the same mean sanity loss but lower variance gives every investigator a more similar experience; high variance is what produces "the table of investigators ended in vastly different mental states" stories. The variance and kill probability pillar covers this for HP — the same math applies, just relabeled.
The Mythos cap and the temporary insanity carousel
Two CoC-specific wrinkles the basic gambler's-ruin model doesn't capture out of the box:
The Cthulhu Mythos cap. Maximum sanity is
99 − Cthulhu Mythos skill. As an investigator
learns more about the Mythos to fight cultists, their
maximum sanity drops — even healthy recovery hits a
hard ceiling. So the gambler's ruin chain has a shrinking pool
ceiling over time. Compose this by chunking: run the chain
one segment per Mythos-acquisition milestone (each segment
uses the ceiling-of-the-moment as the starting sanity for the
next), then compose the per-segment survivor distributions
together. Standard pattern: a sequence of independent
gambler's-ruin chains with input distributions tracked across
segment boundaries.
Temporary vs. indefinite vs. permanent insanity. The "absorbed at zero" event in the HP analogy isn't a single thing in CoC. Hitting 0 sanity = permanent insanity (the character is retired). But losing 5+ sanity in one scene = temporary insanity (player loses control of the character for a few rounds). Losing 1/5 of starting sanity in a single day = indefinite insanity. The basic gambler's-ruin model treats all sanity loss uniformly. For richer modelling, split the input into "shock loss" and "drain loss" expressions and run two parallel chains — temporary insanity events become a separate per-round Bernoulli on top of the cumulative-loss Markov, composed via the same multi-track pattern.
What the engine ships today
The same call that computes strikes-to-kill against a target answers the sanity question:
# A 5-scenario campaign arc, sanity 50, 1d6 loss per scenario,
# +1d4 recovery per scenario (downtime woven in):
{:ok, r} = Diceplots.Engine.rounds_to_kill(["1d6"], ["1d4"], 50, 5)
r.converged # true if the player makes it through all 5
r.expected_rounds # if converged is false: E[rounds until insanity]
r.cumulative # P(insane by round N) for each N
# An arc with 2d6 loss (heavier Mythos density) and no recovery —
# strict drift to zero:
{:ok, r} = Diceplots.Engine.rounds_to_kill(["2d6"], [], 50, 10)
r.expected_rounds # ~ 50 / 7 ≈ 7.14 by linearity, exact value via engine
Multi-pool sanity questions (e.g., the party splits into two
investigation tracks; one faces Mythos contact, the other
recovers; recombine sanity at the end) compose by running
separate rounds_to_kill evaluations per track
and joining the marginal end-state distributions — same
pattern used for chunked Mythos-cap segments above.
Where this matters in practice
The gambler's-ruin frame surfaces design and play decisions that the "did my investigator survive?" binary lens hides.
Scenario length tuning. If your sanity-loss /
recovery cure ratio is 2:1, expected sessions to insanity is
(starting sanity) / (loss − recovery). A POW 50
character (sanity ~70) with 1d6 loss / 1 recovery per scenario
hits insanity at ~28 scenarios in expectation. A 6-session arc
is well-within survival territory; a 12-session campaign with
the same pacing is on the cusp. Variance still matters —
the 95th-percentile time to insanity is much shorter than the
mean for high-variance loss distributions.
The "down for the count" cliff. Once an
investigator drops below
(starting sanity − 20) they're at risk of
indefinite insanity from any moderate shock. So the practical
"broken" threshold isn't zero — it's about 20 below starting,
where the next significant Mythos contact has a ~50% chance of
crossing the indefinite line. Keepers tuning the late-game
should compute "P(reach 20-below) by session N" rather than
"P(reach zero) by session N" — the former captures when the
player effectively loses control.
Cross-system: any drift-to-absorption mechanic. The same shape applies to Eclipse Phase stress, Delta Green's sanity track, Trail of Cthulhu's stability, Vampire's Hunger die — anywhere a finite pool drains via per-encounter loss against trickle recovery, the engine's rounds_to_kill substrate computes the survivors curve. You don't need a sanity-specific module; the framing transfers.
Common questions
- Why is sanity loss a gambler's ruin walk and not just averaging?
- Because the per-encounter sanity loss isn't a constant — it's a distribution. A 1d6 loss has expected value 3.5, but its variance creates a fat-tailed survivors curve. Two investigators starting at sanity 50 and facing 15 1d6 encounters: averaging says they end at 50 - 15·3.5 = -2.5, both broken. But variance means investigator A might end at 8 (six low rolls in a row) while investigator B might hit zero on encounter 11. The engine's rounds_to_kill machinery computes the full distribution of 'rounds until zero' so you can answer 'what's my chance of finishing this 5-scenario arc with sanity ≥ 10?', not just the mean.
- When does the chain converge vs. drift to zero forever?
- The same answer as for HP-vs-healing: when E[per-round healing] ≥ E[per-round damage], the Markov chain doesn't kill you in finite expectation; the long-run behaviour wanders or recovers. When E[healing] < E[damage], you're on a strict drift toward zero with probability 1 — gambler's ruin. Most published CoC scenarios have per-scenario sanity loss in the 1d6–1d10 range and per-downtime recovery in the 1–1d6/week range, with downtime typically much shorter than the in-game investigation pace. The cure ratio rarely favours the investigator. Telling the player 'in expectation you have N sessions before insanity' is what rounds_to_kill computes.
- How does this compose with the success-bands pillar?
- Sanity tests are themselves percentile checks (current sanity is the skill). A failed roll triggers per-encounter sanity loss (often '0/1d4' meaning 0 on success, 1d4 on fail). Compose Diceplots.Engine.percentile_test(sanity, ...) with rounds_to_kill: P(failed sanity check at S=current) gives the conditional probability of triggering the loss; rounds_to_kill takes the loss distribution. As sanity drains, P(fail) rises (the skill drops), accelerating the drift. The full state-carrying chain is more elaborate than the engine ships today; the gambler's-ruin framing here uses a fixed loss distribution per round as a useful upper bound.
- Is this just rounds_to_kill with relabelled inputs?
- Yes — that's the point of the framing. The engine doesn't know you're modelling sanity vs. HP; it computes the cumulative-loss-vs-pool Markov chain regardless of the narrative wrapper. The pillar makes the mapping explicit so keepers and players can drive existing site machinery to answer sanity-pool questions: HP slider = starting sanity, damage expression = per-scenario loss distribution, healing expression = per-downtime recovery, max rounds = number of in-game intervals. The rest is the same exact-rational Markov walk that powers /concepts/expected-strikes-to-kill.