Plenty of tabletop systems use success-counting dice pools: roll a handful of dice, count every die at or above a threshold as one success, check the count against a target. As a probability question this is comfortable territory — "at least 5 successes on 10d6, counting 5 or higher" is a binomial distribution with a closed form.
Then the house rules arrive. "Reroll your 1s once." And the fun one: "a die showing its maximum explodes — roll an extra die, and if that one shows the maximum too, keep going." The chain has no upper bound, so the outcome space is infinite. At this point the standard instinct (mine included) is to stop doing math and start simulating: roll the pool 100,000 times in a loop and count.
I wanted the exact distribution instead — recomputed live in the browser on every slider move. It turns out exploding dice don't need simulation at all. The whole problem collapses into one geometric series and a convolution.
One die is a geometric chain
Look at a single roll against threshold T on an s-sided die. Only three outcomes matter:
- fail (below T): probability
f - terminal success (T or above, but not the max face):
t - exploding success (the max face — one success plus a fresh roll):
e
For a d6 counting 5+, that's f = 4/6, t = 1/6, e = 1/6.
For a chain to produce exactly n successes there are only two shapes: n−1 explosions followed by a plain success, or n explosions followed by a fail — the fail ends the chain, but the n max faces already counted. So:
P(0) = f
P(n) = e^(n-1) · t + e^n · f (n ≥ 1)
An infinite series, but e < 1, so it decays geometrically. The calculator cuts the tail once e^n drops below 1e-12 (with a hard cap of 80 successes per die) and renormalizes at the end. A d6 needs about 16 terms. "Infinite" was never scary — it just meant "geometric".
Rerolls are a face-probability problem, not a new case
"Reroll 1s once" looks like it demands its own case analysis. It doesn't, if you push it one layer down: it only changes the probability of each face. A kept result of 1 now requires rolling 1 twice, and every other face is reached either directly or via the reroll:
P(face 1) = 1/s²
P(face k≥2) = (s+1)/s²
Feed those weights into the same f/t/e split and everything above goes through untouched.
One semantic consequence is worth stating out loud: because the face weights apply to every roll, chained explosion dice get their 1s rerolled too. Some tables may rule it differently — but the model forces you to pick an interpretation, which is itself a point in favor of doing the math over eyeballing a simulator.
A pool is N convolutions
Ten independent dice = the single-die distribution convolved with itself ten times.
function convolve(a, b) {
const result = Array.from({ length: a.length + b.length - 1 }, () => 0);
a.forEach((left, i) => {
b.forEach((right, j) => {
result[i + j] += left * right;
});
});
return result;
}
That's the actual production code. Naive quadratic convolution, no FFT — the pool maxes out at 30 dice and the per-die array at a few dozen entries, so the full distribution recomputes on every input event without breaking a sweat.
The mean is a free sanity check
Geometric chains have a closed-form mean: each die is expected to produce p / (1 − e) successes, where p is the per-roll success probability. That gives an independent check on the numeric distribution.
Take 10d6, threshold 5+, with both reroll-1s and explosion on. Per die, p = 14/36 and e = 7/36, so the pool expects 10 × (14/36)/(29/36) ≈ 4.83 successes. The computed distribution's mean agrees. So does a 2-million-trial simulation I ran as a cross-check: 52.63% for "at least 5 successes" against the exact 52.6%. Monte Carlo demoted from engine to test harness — a fair trade.
What it changes at the table
Here is the calculator all of this lives in:
Same pool, 10d6 counting 5+, target of 5 successes. Under flat rules the odds are 21.3%:
Turn on reroll-1s and exploding maximums: 52.6%. Two house rules turn a long shot into a coin flip, and you can see where it comes from — the distribution grows a tail, which the chart compacts into a final "14+" bucket once 99.95% of the probability is on screen:
Everything recomputes exactly on every change — pool size (1–30), die type (d4 through d20), threshold — and clicking any bar moves the target there. If you're tuning house rules or balancing a pool-based system, exact beats simulated: the interesting decisions live in the tail, which is precisely where Monte Carlo is noisiest.
Part of a small collection of free browser tools I'm building: Utilities Web


Top comments (0)