Reference → Syntax
Dice expression syntax
Everything the engine accepts. Every example below links to its
live distribution at /strike/ — click any to see the
exact rationals.
Quick reference
| Form | Meaning | Example |
|---|---|---|
K |
integer constant | 5 |
NdM |
roll N M-sided dice, sum the faces | 2d6 |
NdM+K / NdM-K |
add or subtract a constant to the sum | 2d6+5 |
A + B + … |
mix any number of dice + constant terms | 1d8 + 1d6 + 3 |
X * K / K * X |
scalar multiplication — roll X once, multiply the result by integer K (one operand must be a constant; both-random is rejected) | (1d4+3)*3 |
(X) |
parenthesised group — overrides default precedence (+/- at the bottom, then *, then atoms) |
(1d6+1d4)*2 |
NdM! |
exploding dice — max face rolls again, sums in | 1d6! |
NdMrK |
reroll once if the first roll is ≤ K (GWF rule when K=1) | 2d6r1+5 |
NdMkh<K> |
roll N, keep the highest K and sum (advantage when N=2 K=1; ability-score gen at 4d6kh3) | 2d20kh1 · 4d6kh3 |
NdMkl<K> |
roll N, keep the lowest K and sum (disadvantage when N=2 K=1; drop-highest pattern at K>1) | 2d20kl1 · 4d6kl3 |
X @ AC<n> +/-<m> |
attack roll: deal X on a hit, 0 on a miss, doubled dice on a crit | 1d8+5 @ AC15 +9 |
… adv / disadv / elven |
attack roll with advantage / disadvantage / Elven Accuracy | 1d8+5 @ AC15 +9 adv |
… c<k> |
crit on natural ≥ k (Champion: c19) |
1d12+5 @ AC15 +9 c19 |
… dr<n> |
defender DR — flat reduction to base damage per hit, clamped at 0 (Heavy Armor Master: dr3) |
1d8+5 @ AC15 +9 dr3 |
… dr<n>:<type> |
per-type DR — only reduces the named damage type's bucket of base damage (RAW HAM: BPS only) | 1d8:slashing+1d6:fire @ AC15 +9 dr3:slashing |
… brutal<n> |
extra weapon damage dice on crit (Half-Orc Savage Attacks: brutal1; Barb 9 / 13 / 17: brutal1 / brutal2 / brutal3) |
1d12+5 @ AC15 +9 brutal1 |
… attacks N |
multi-attack — N independent attacks of this profile (Extra Attack: attacks 2) |
1d12+5 @ AC15 +9 attacks 2 |
X @ hit <p>[%] [crit <p>[%]] [graze <p>[%]] |
percentage attack (XCOM, Hard West, tactical games) — single hit roll against a flat probability; crit conditional on hit; graze halves damage and eats into miss | 1d3+4 @ hit 65 crit 10 graze 15 |
X save +<b> DC<n> |
save-for-half (Fireball) — full damage on fail, half on save | 8d6 save +5 DC15 |
… zero |
save-or-suck (Hold Person) — full damage on fail, zero on save | 1d6 save +1 DC13 zero |
… t<N> |
multi-target — N targets share the damage roll, each saves independently (Fireball-into-pod) | 8d6 save +5 DC15 t4 |
… rider <expr> |
extra damage on hit, doubled dice on a crit (Smite, Hex, Hunter's Mark, Divine Strike) | 1d8+5 @ AC15 +9 rider 2d8 |
… attacks N sneak <expr> |
once-per-chain rider on the first hit of a multi-attack — Sneak Attack semantics; doubled on crit | 1d6+3 @ AC15 +5 attacks 2 sneak 3d6 |
… attacks N oncrit <attack> |
once-per-chain bonus attack triggered by any crit in the chain — Great Weapon Master's bonus haft | 1d12+15 @ AC15 +4 attacks 2 oncrit 1d12+15 @ AC15 +4 |
… attacks N bonus <attack> |
unconditional bonus-action attack — Polearm Master haft, Crossbow Expert bonus shot, Two-Weapon Fighting offhand | 1d10+5 @ AC15 +9 attacks 2 bonus 1d4+5 @ AC15 +9 |
… attacks N bonus X oncrit Y |
mutually-exclusive bonus actions — PAM haft when no crit, GWM bonus replaces it on a crit (one bonus action per turn, RAW) | 1d10+15 @ AC15 +4 attacks 2 bonus 1d4+15 @ AC15 +4 oncrit 1d10+15 @ AC15 +4 |
Constants and dice
An expression is a sum of terms. Each term is either an integer
constant (K) or a dice term (NdM, possibly
with a modifier). Whitespace between tokens is optional and ignored;
the d can be uppercase (D) too.
5— a constant 5 (degenerate "distribution" with one outcome).1d6— one six-sided die. Six equally-likely faces, mean 3.5.2d6— two d6 summed. The classic triangular distribution: 36 outcomes, mean 7, mode 7.4d6— four d6, used in 5e ability score generation. The "drop the lowest" variant is4d6kh3— keep the highest 3 of 4.
Additive modifiers
The most common 5e weapon-damage form: NdM plus your
ability modifier. + and - are
left-associative; you can chain any number of terms.
1d8+3— longsword with +3 STR. Range 4–11, mean 7.5.2d6+5— greatsword with +5 STR. Range 7–17, mean 12.1d12+5— greataxe with +5 STR. Same modifier; very different shape.
For mixing different dice (e.g., weapon + sneak attack die, base damage + elemental rider), see the next section.
2d6+5
- 7 2.78%
- 8 5.56%
- 9 8.33%
- 10 11.11%
- 11 13.89%
- 12 16.67%
- 13 13.89%
- 14 11.11%
- 15 8.33%
- 16 5.56%
- 17 2.78%
Mixing dice and constants — the main reason to use the engine
Anyone can compute 2d6 alone. The interesting cases
combine different dice — weapon + sneak attack, base damage +
elemental rider, primary swing + bonus-action attack — and the resulting
distribution isn't an obvious shape. Convolving exact rationals is what
this engine does well.
Add as many dice and constant terms as you want, in any order, with
+ or - between them. Whitespace is optional.
-
2d6 + 1d4— pure dice mix, no constant. Range 3–16, mean 19/2 = 9.5. -
1d8 + 1d6 + 3— 5e rogue with a shortbow + sneak attack die + DEX modifier. Three independent terms. Range 5–17, mean 11. -
2d6 + 1d4 - 2— dice plus dice plus a negative constant. Useful for "deal 2d6 + 1d4 damage, target gains 2 temp HP" kind of net-damage scenarios. Range 1–14. -
1d8 + 3↔3 + 1d8— order doesn't matter for+terms; both produce the same distribution and the same slug encoding when you flip them through the parser.
The convolved shape is what you'd expect from the central limit theorem — adding more independent dice pulls the distribution toward a bell curve. Side by side: pure 1d8+1d6 (no modifier) vs the rogue pattern with +3 (same shape, shifted right by 3):
1d8+1d6
- 2 2.08%
- 3 4.17%
- 4 6.25%
- 5 8.33%
- 6 10.42%
- 7 12.50%
- 8 12.50%
- 9 12.50%
- 10 10.42%
- 11 8.33%
- 12 6.25%
- 13 4.17%
- 14 2.08%
1d8+1d6+3
- 5 2.08%
- 6 4.17%
- 7 6.25%
- 8 8.33%
- 9 10.42%
- 10 12.50%
- 11 12.50%
- 12 12.50%
- 13 10.42%
- 14 8.33%
- 15 6.25%
- 16 4.17%
- 17 2.08%
Exploding dice (!)
On a maximum-face roll, roll the die again and add. Recurses up to
depth 20 (truncation error ~M⁻²⁰, well below
floating-point noise for any practical M). Notation: append
! to the dice term.
1d6!— the canonical exploding die. Mean 21/5 = 4.2.1d8!— slightly tighter explosion rate.- Why this matters →
Constraint: a 1-sided die can't explode (it would loop forever).
Combining ! with r on the same die is
rejected — pick one modifier per die term.
1d6
- 1 16.67%
- 2 16.67%
- 3 16.67%
- 4 16.67%
- 5 16.67%
- 6 16.67%
1d6!
- 1 16.67%
- 2 16.67%
- 3 16.67%
- 4 16.67%
- 5 16.67%
- 6 0.00%
- 7 2.78%
- 8 2.78%
- 9 2.78%
- 10 2.78%
- 11 2.78%
- 12 0.00%
- 13 0.46%
- 14 0.46%
- 15 0.46%
- 16 0.46%
- 17 0.46%
- 18 0.00%
- 19 0.08%
- 20 0.08%
- 21 0.08%
- 22 0.08%
- 23 0.08%
- 24 0.00%
- 25 0.01%
- 26 0.01%
- 27 0.01%
- 28 0.01%
- 29 0.01%
- 30 0.00%
- 31 0.00%
- 32 0.00%
- 33 0.00%
- 34 0.00%
- 35 0.00%
- 36 0.00%
- 37 0.00%
- 38 0.00%
- 39 0.00%
- 40 0.00%
- 41 0.00%
- 42 0.00%
- 43 0.00%
- 44 0.00%
- 45 0.00%
- 46 0.00%
- 47 0.00%
- 48 0.00%
- 49 0.00%
- 50 0.00%
- 51 0.00%
- 52 0.00%
- 53 0.00%
- 54 0.00%
- 55 0.00%
- 56 0.00%
- 57 0.00%
- 58 0.00%
- 59 0.00%
- 60 0.00%
- 61 0.00%
- 62 0.00%
- 63 0.00%
- 64 0.00%
- 65 0.00%
- 66 0.00%
- 67 0.00%
- 68 0.00%
- 69 0.00%
- 70 0.00%
- 71 0.00%
- 72 0.00%
Reroll once (r<K>)
If the first roll is ≤ K, roll a second time and keep the second
result (whether it's higher or lower). The 5e Great Weapon Fighting
style is exactly NdMr1 — reroll any 1s and 2s once.
(Strict 5e GWF rerolls 1s AND 2s; the engine currently supports
only an inclusive ≤ K threshold, so r2 covers both.)
Keep-highest / keep-lowest (kh1 / kl1)
Roll N dice, keep only the single highest (kh1) or
single lowest (kl1). When N=2 this is exactly 5e
advantage and disadvantage.
2d20kh1— d20 with advantage. Mean 553/40 = 13.825.2d20kl1— d20 with disadvantage. Mean 287/40 = 7.175.- Why this matters →
Generic kh<K> / kl<K>
with K ≥ 1 is supported. The kept=1 case uses a closed-form
recursion (max-of-N / min-of-N); kept>1 brute-enumerates
sides^count outcomes (capped at 200K, which fits
4d6 / 4d20 / 5d6 / 6d6 — the realistic d-and-d ability-gen
cases plus a few homebrew variants).
2d20kh1
- 1 0.25%
- 2 0.75%
- 3 1.25%
- 4 1.75%
- 5 2.25%
- 6 2.75%
- 7 3.25%
- 8 3.75%
- 9 4.25%
- 10 4.75%
- 11 5.25%
- 12 5.75%
- 13 6.25%
- 14 6.75%
- 15 7.25%
- 16 7.75%
- 17 8.25%
- 18 8.75%
- 19 9.25%
- 20 9.75%
2d20kl1
- 1 9.75%
- 2 9.25%
- 3 8.75%
- 4 8.25%
- 5 7.75%
- 6 7.25%
- 7 6.75%
- 8 6.25%
- 9 5.75%
- 10 5.25%
- 11 4.75%
- 12 4.25%
- 13 3.75%
- 14 3.25%
- 15 2.75%
- 16 2.25%
- 17 1.75%
- 18 1.25%
- 19 0.75%
- 20 0.25%
Attack rolls (@ AC<n> +/-<m>)
The @ postfix wraps a damage expression with an
attack roll vs Armor Class. The result is a per-attempt
distribution that includes a zero-mass spike on miss and a
crit-doubled tail on natural-20 (or whatever crit range you set):
-
1d8+5 @ AC15 +9— a longsword swing with +9 to-hit against an AC 15 target. Per 5e RAW: nat 1 always misses, nat 20 always hits and crits, and the modified roll vs AC handles everything else. -
2d6+5 @ AC15 +9— a greatsword swing under the same conditions. Same hit rate, different damage shape. -
1d12+15 @ AC15 +4— a Greataxe Fighter using Great Weapon Master: −5 to-hit, +10 damage. The break-even AC sits at attack-bonus + 8.
Three optional flags can follow the AC and bonus, in any order:
-
adv/disadv/elven— advantage (2d20 keep highest), disadvantage (2d20 keep lowest), or Elven Accuracy (3d20 keep highest). With advantage, crit rate jumps to 1 − (19/20)² = 9.75%; with Elven Accuracy, to 1 − (19/20)³ ≈ 14.26%.1d8+5 @ AC15 +9 adv. -
c<k>— lower the crit range. Champion Fighter isc19(crits on 19 or 20).1d12+5 @ AC15 +9 c19. -
Combine flags:
1d8+5 @ AC15 +9 elven c19for the Elven Accuracy + Champion crit-fish stack.
Crit damage follows the 5e rule: roll the dice twice, add the
modifier once. So a crit on 1d12+5 becomes
2d12+5, not 2(d12+5). The engine handles
this automatically — you never write the doubled form by hand.
The @ postfix binds looser than
+ and -: 2d6+5 @ AC15 +9
parses as "the attack expression with damage = 2d6+5", not as
"the attack 5 @ AC15 plus 2d6 plus 9." The damage expression is
everything to the left of @.
1d8+5
- 6 12.50%
- 7 12.50%
- 8 12.50%
- 9 12.50%
- 10 12.50%
- 11 12.50%
- 12 12.50%
- 13 12.50%
1d8+5 @ AC15 +9
- 0 25.00%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 8.75%
- 7 8.83%
- 8 8.91%
- 9 8.98%
- 10 9.06%
- 11 9.14%
- 12 9.22%
- 13 9.30%
- 14 0.63%
- 15 0.55%
- 16 0.47%
- 17 0.39%
- 18 0.31%
- 19 0.23%
- 20 0.16%
- 21 0.08%
Multi-attack (attacks N)
Postfix attacks N on an attack expression replays the
same attack profile N times and convolves the per-attempt
distributions. The canonical 5e use case is Extra Attack at
level 5 (Fighter, Paladin, Ranger, Barbarian) — two swings
with the same weapon per round.
-
1d12+5 @ AC15 +9 attacks 2— a Greataxe Fighter at level 5 vs AC 15 with +9 to-hit. The per-round distribution is the convolution of two independent single-swing distributions: each one independently misses, hits, or crits. -
1d12+15 @ AC15 +4 attacks 2— same Fighter using GWM (−5 to-hit, +10 damage) on both swings. Compare to the base form to see the GWM trade across a full round, not just per-attack. -
1d12+5 @ AC15 +9 attacks 4— Action Surge round at level 5 (4 attacks). Mean and variance both quadruple; the distribution narrows toward normal as N grows (CLT in action).
Constraints: N must be in [1, 20].
Main-attack heterogeneity (e.g. Greatsword first attack +
Shortsword second attack) isn't expressible directly — write
those as a sum of separate Attack expressions, or use the
comparison tool's two-side form. The
bonus <attack> postfix DOES handle the
"homogeneous main + one different bonus" case (PAM haft, TWF
offhand, CBE bonus shot), and sneak composes with
bonus for Rogue/PAM and Rogue/TWF builds.
attacks N only applies after @ — it's
strictly the multi-attack convolution. For "roll once and
multiply the result", use the * infix operator
on a damage expression: (1d4+3)*3 is a single
1d4+3 roll multiplied by 3 (uniform over
{12, 15, 18, 21}), distinct from 3d4+9
which sums three independent rolls (same mean, tighter
distribution).
1d12+5 @ AC15 +9
- 0 25.00%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 5.83%
- 7 5.87%
- 8 5.90%
- 9 5.94%
- 10 5.97%
- 11 6.01%
- 12 6.04%
- 13 6.08%
- 14 6.11%
- 15 6.15%
- 16 6.18%
- 17 6.22%
- 18 0.42%
- 19 0.38%
- 20 0.35%
- 21 0.31%
- 22 0.28%
- 23 0.24%
- 24 0.21%
- 25 0.17%
- 26 0.14%
- 27 0.10%
- 28 0.07%
- 29 0.03%
1d12+5 @ AC15 +9 attacks 2
- 0 6.25%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 2.92%
- 7 2.93%
- 8 2.95%
- 9 2.97%
- 10 2.99%
- 11 3.00%
- 12 3.36%
- 13 3.72%
- 14 4.09%
- 15 4.46%
- 16 4.83%
- 17 5.21%
- 18 2.68%
- 19 3.03%
- 20 3.38%
- 21 3.74%
- 22 4.11%
- 23 4.47%
- 24 4.17%
- 25 3.85%
- 26 3.53%
- 27 3.19%
- 28 2.85%
- 29 2.51%
- 30 2.15%
- 31 1.80%
- 32 1.45%
- 33 1.08%
- 34 0.71%
- 35 0.33%
- 36 0.28%
- 37 0.24%
- 38 0.20%
- 39 0.16%
- 40 0.13%
- 41 0.10%
- 42 0.07%
- 43 0.05%
- 44 0.03%
- 45 0.02%
- 46 0.01%
- 47 0.00%
- 48 0.00%
- 49 0.00%
- 50 0.00%
- 51 0.00%
- 52 0.00%
- 53 0.00%
- 54 0.00%
- 55 0.00%
- 56 0.00%
- 57 0.00%
- 58 0.00%
Scalar multiplication and grouping (*, ())
The infix * operator multiplies the rolled value
of an expression by an integer constant. At least one operand
must be a constant — both-random (1d4*1d6) is
rejected because the meaning is ambiguous (scalar mult vs.
convolution). Use + to convolve independent rolls.
Grouping parentheses (…) override default
precedence. Precedence is +/-
(lowest), then *, then atoms — so
1d6 + 1d4*2 parses as 1d6 + (1d4*2).
Parens accept an optional :tag postfix for
type-tagging the whole group, equivalent to the bracket form
((1d6+5):slashing ↔ [1d6+5]:slashing;
brackets require the tag, parens make it optional).
-
(1d4+1)*3— the 2014 Magic Missile shape: roll one1d4+1and apply it to all three darts. Mean 10.5, uniform over{6, 9, 12, 15}(4 outcomes). -
3d4+3— the 2024 Magic Missile shape: each dart rolls independently. Same mean (10.5), but tighter — the convolution narrows the distribution by a factor of 3 in variance. -
1d6 + 1d4*2— illustrates precedence: parses as1d6 + (1d4*2), not(1d6 + 1d4)*2. Wrap in parens to force the other reading.
* is independent of the attacks N
multi-attack postfix. Multi-attack is convolution (sum of N
independent attack rolls); scalar mult is point-multiplication
of one rolled value. Both can appear in the same expression
when applicable.
(1d4+1)*3
- 6 25.00%
- 7 0.00%
- 8 0.00%
- 9 25.00%
- 10 0.00%
- 11 0.00%
- 12 25.00%
- 13 0.00%
- 14 0.00%
- 15 25.00%
3d4+3
- 6 1.56%
- 7 4.69%
- 8 9.38%
- 9 15.63%
- 10 18.75%
- 11 18.75%
- 12 15.63%
- 13 9.38%
- 14 4.69%
- 15 1.56%
Percentage attacks (@ hit <p>%)
The @ hit <p>% postfix is the alternative to
@ AC<n> +<m> — a single roll against a
flat hit probability instead of d20-vs-AC math. Models XCOM 2,
Hard West, Pillars of Eternity, Fire Emblem, and any other
tactical game where the player sees a "65%" tooltip rather
than a d20 attack roll. Trailing % is optional;
hit 65 and hit 65% parse identically.
Two optional postfix flags:
-
crit <p>%— conditional crit chance on a successful hit.P(crit) = P(hit) · crit_chance. Crit damage doubles the damage dice (same rule as the d20 path). Cannot fire on a graze. -
graze <p>%— partial-hit bucket.P(graze)eats into the miss probability, so a 65% hit / 15% graze build has 80% chance of dealing some damage. Graze damage =floor(dmg / 2)— samediv_euclid(2)as Save::Half. Invariant:hit + graze ≤ 100.
The four-way outcome split for 1d3+4 @ hit 65 crit 10 graze 15:
P(crit) = 0.65 · 0.10 = 39/400 = 9.75%P(non-crit hit) = 0.65 - 0.0975 = 221/400 = 55.25%P(graze) = 60/400 = 15%P(true miss) = 1 - 0.65 - 0.15 = 80/400 = 20%
What the d20 attack flags do NOT do here.
adv / disadv / elven
apply only to d20 to-hit ensembles — there's no d20 to roll
multiple of in the percentage path, so they're rejected by the
parser. Same for c<n> (crit range — replaced
by crit <p>%) and shield
(defender Shield is a d20 mechanic). What DOES carry over:
rider, dr, dr:type,
brutal, and attacks N all work
identically — they operate on the post-branch damage, not on
the to-hit math.
-
1d3+4 @ hit 65 crit 10— vanilla XCOM 2 assault rifle, no graze model. -
1d3+4 @ hit 65 crit 10 graze 15— same shot with graze enabled (default WotC ruleset). -
1d3+4 @ hit 95 crit 25— Squadsight overwatch chain, near-certain hit with high crit. -
1d3+7 @ hit 35 crit 15— low-percentage Sniper flank, long-tail Hail Mary. -
1d4+5 @ hit 50 crit 10 graze 30— Shotgun through half-cover, graze-heavy distribution.
Worked-out math, the variance picture, and what's out of scope (miss-streak protection, Hard West Luck pool) — see the XCOM 2 outcome model pillar. Pre-baked weapon panels live at /games/xcom/.
1d3+4 @ hit 65 crit 10
- 0 35.00%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 19.50%
- 6 20.22%
- 7 20.94%
- 8 2.17%
- 9 1.44%
- 10 0.72%
1d3+4 @ hit 65 crit 10 graze 15
- 0 20.00%
- 1 0.00%
- 2 5.00%
- 3 10.00%
- 4 0.00%
- 5 19.50%
- 6 20.22%
- 7 20.94%
- 8 2.17%
- 9 1.44%
- 10 0.72%
Saving throws (save +<b> DC<n> [half|zero])
The save postfix wraps a damage expression with a
target's saving throw. Per RAW, the result depends on the save:
-
Half on save (default — Fireball-style):
full damage on fail,
floor(damage/2)on success. The dice are rolled once; the same random variable is halved on save (a Fireball that rolls 30 deals 30 on fail and 15 on save — not "roll separately"). -
Zero on save (use
zeroflag — Hold Person-style "save-or-suck"): full damage on fail, nothing on success.
Examples:
-
8d6 save +5 DC15— Fireball at 3rd-level slot vs a CR-5 monster's DEX +5 save. P(save) = (21+5−15)/20 = 11/20 = 55%; expected damage drops from 28 (always full) to ~20.3 (55% half). -
8d6 save +0 DC15— same Fireball vs a target with no DEX save bonus (CR-1 humanoids, low-tier undead). P(save) = 6/20 = 30%. -
10d6 save +5 DC17— Fireball upcast to 5th-level slot, DC 17 (mid-tier caster). P(save) = 9/20 = 45%. -
1d6 save +1 DC13 zero— a save-or-suck cantrip-tier effect: the 1d6 is the "damage-or-control" payload;zeroflag means success means it does nothing.
5e RAW for saves: no nat-1 auto-fail or nat-20 auto-success
(those rules are for attack rolls; death saves are a separate
mechanic). Save probability is just
clamp((21 + bonus − DC) / 20, 0, 1). The engine
handles boundary cases — a save you can't make (DC 25 vs +0)
collapses to the unmodified damage distribution; a save you
can't fail collapses to all-zero (Zero) or all-half (Half).
8d6
- 8 0.00%
- 9 0.00%
- 10 0.00%
- 11 0.01%
- 12 0.02%
- 13 0.05%
- 14 0.10%
- 15 0.20%
- 16 0.37%
- 17 0.62%
- 18 1.00%
- 19 1.52%
- 20 2.18%
- 21 2.99%
- 22 3.92%
- 23 4.90%
- 24 5.88%
- 25 6.77%
- 26 7.48%
- 27 7.94%
- 28 8.09%
- 29 7.94%
- 30 7.48%
- 31 6.77%
- 32 5.88%
- 33 4.90%
- 34 3.92%
- 35 2.99%
- 36 2.18%
- 37 1.52%
- 38 1.00%
- 39 0.62%
- 40 0.37%
- 41 0.20%
- 42 0.10%
- 43 0.05%
- 44 0.02%
- 45 0.01%
- 46 0.00%
- 47 0.00%
- 48 0.00%
8d6 save +5 DC15
- 4 0.00%
- 5 0.01%
- 6 0.04%
- 7 0.17%
- 8 0.54%
- 9 1.39%
- 10 2.85%
- 11 4.86%
- 12 6.97%
- 13 8.50%
- 14 8.86%
- 15 7.93%
- 16 6.10%
- 17 4.08%
- 18 2.49%
- 19 1.58%
- 20 1.29%
- 21 1.43%
- 22 1.78%
- 23 2.21%
- 24 2.65%
- 25 3.05%
- 26 3.36%
- 27 3.57%
- 28 3.64%
- 29 3.57%
- 30 3.36%
- 31 3.05%
- 32 2.65%
- 33 2.21%
- 34 1.76%
- 35 1.35%
- 36 0.98%
- 37 0.68%
- 38 0.45%
- 39 0.28%
- 40 0.16%
- 41 0.09%
- 42 0.05%
- 43 0.02%
- 44 0.01%
- 45 0.00%
- 46 0.00%
- 47 0.00%
- 48 0.00%
Multi-target AOE (t<N>)
Postfix t<N> on a save expression extends to
multi-target: the SAME damage roll applies to N independent
saves. Per RAW, the dice are rolled once and each target
saves separately, taking either full damage on fail or
transformed damage on success. The per-cast total is the sum
across targets.
-
8d6 save +5 DC15 t4— Fireball (3rd-level slot) into a pod of 4 CR-5 monsters (DEX +5 save, P(save) = 55%). Per-cast mean ≈ 81 (4× the single-target ≈ 20). -
8d6 save +0 DC15 t8— Fireball into a swarm of 8 weak humanoids (no DEX save). Per-cast mean ≈ 190. This is the "DEX +0 minions are Fireball food" regime. -
8d8 save +5 DC17 t4— Cone of Cold (5th-level slot) into 4 mid-tier targets, DC bumped to 17.
Implementation: for each rolled damage value x
and number of failed saves k (where K ~ binomial(N,
P(fail))), the per-cast total is
x·k + transform(x)·(N − k). Independence of damage
roll and per-target save outcomes makes this a clean
product-of-distributions over the support — sub-millisecond
even for Cone-of-Cold-into-8 (8d8 × 9-bucket binomial = ~500
pre-mix outcomes).
Constraint: N must be in [1, 20].
t1 is the default and identical to omitting the
flag. The t flag composes with half /
zero in any order:
1d6 save +1 DC13 zero t3 (save-or-suck into 3
targets) parses fine.
8d6 save +5 DC15
- 4 0.00%
- 5 0.01%
- 6 0.04%
- 7 0.17%
- 8 0.54%
- 9 1.39%
- 10 2.85%
- 11 4.86%
- 12 6.97%
- 13 8.50%
- 14 8.86%
- 15 7.93%
- 16 6.10%
- 17 4.08%
- 18 2.49%
- 19 1.58%
- 20 1.29%
- 21 1.43%
- 22 1.78%
- 23 2.21%
- 24 2.65%
- 25 3.05%
- 26 3.36%
- 27 3.57%
- 28 3.64%
- 29 3.57%
- 30 3.36%
- 31 3.05%
- 32 2.65%
- 33 2.21%
- 34 1.76%
- 35 1.35%
- 36 0.98%
- 37 0.68%
- 38 0.45%
- 39 0.28%
- 40 0.16%
- 41 0.09%
- 42 0.05%
- 43 0.02%
- 44 0.01%
- 45 0.00%
- 46 0.00%
- 47 0.00%
- 48 0.00%
8d6 save +5 DC15 t4
- 16 0.00%
- 17 0.00%
- 18 0.00%
- 19 0.00%
- 20 0.00%
- 21 0.00%
- 22 0.00%
- 23 0.00%
- 24 0.01%
- 25 0.00%
- 26 0.00%
- 27 0.00%
- 28 0.03%
- 29 0.00%
- 30 0.01%
- 31 0.01%
- 32 0.09%
- 33 0.00%
- 34 0.00%
- 35 0.03%
- 36 0.30%
- 37 0.00%
- 38 0.02%
- 39 0.00%
- 40 0.58%
- 41 0.19%
- 42 0.04%
- 43 0.00%
- 44 0.88%
- 45 0.31%
- 46 0.45%
- 47 0.00%
- 48 1.29%
- 49 0.02%
- 50 0.88%
- 51 0.90%
- 52 1.45%
- 53 0.00%
- 54 0.37%
- 55 1.17%
- 56 3.57%
- 57 0.00%
- 58 0.00%
- 59 0.13%
- 60 3.88%
- 61 2.03%
- 62 1.10%
- 63 0.20%
- 64 1.00%
- 65 2.24%
- 66 4.12%
- 67 0.00%
- 68 2.46%
- 69 0.00%
- 70 2.86%
- 71 2.38%
- 72 2.54%
- 73 0.60%
- 74 2.49%
- 75 2.24%
- 76 2.24%
- 77 0.79%
- 78 2.75%
- 79 0.00%
- 80 5.80%
- 81 1.47%
- 82 0.00%
- 83 0.00%
- 84 4.29%
- 85 1.17%
- 86 3.81%
- 87 1.36%
- 88 0.16%
- 89 0.00%
- 90 3.40%
- 91 1.95%
- 92 2.69%
- 93 0.00%
- 94 1.59%
- 95 0.30%
- 96 2.59%
- 97 0.00%
- 98 3.43%
- 99 0.00%
- 100 0.39%
- 101 1.65%
- 102 1.44%
- 103 0.00%
- 104 1.41%
- 105 1.53%
- 106 0.01%
- 107 0.00%
- 108 2.49%
- 109 0.00%
- 110 0.56%
- 111 0.00%
- 112 1.51%
- 113 0.00%
- 114 0.37%
- 115 0.98%
- 116 0.55%
- 117 0.00%
- 118 0.00%
- 119 0.79%
- 120 0.44%
- 121 0.00%
- 122 0.67%
- 123 0.00%
- 124 0.28%
- 125 0.00%
- 126 0.48%
- 127 0.00%
- 128 0.26%
- 129 0.30%
- 130 0.00%
- 131 0.00%
- 132 0.21%
- 133 0.20%
- 134 0.00%
- 135 0.00%
- 136 0.29%
- 137 0.00%
- 138 0.00%
- 139 0.00%
- 140 0.20%
- 141 0.00%
- 142 0.00%
- 143 0.04%
- 144 0.09%
- 145 0.00%
- 146 0.00%
- 147 0.02%
- 148 0.06%
- 149 0.00%
- 150 0.01%
- 151 0.00%
- 152 0.04%
- 153 0.00%
- 154 0.00%
- 155 0.00%
- 156 0.03%
- 157 0.00%
- 158 0.00%
- 159 0.00%
- 160 0.02%
- 161 0.00%
- 162 0.00%
- 163 0.00%
- 164 0.01%
- 165 0.00%
- 166 0.00%
- 167 0.00%
- 168 0.00%
- 169 0.00%
- 170 0.00%
- 171 0.00%
- 172 0.00%
- 173 0.00%
- 174 0.00%
- 175 0.00%
- 176 0.00%
- 177 0.00%
- 178 0.00%
- 179 0.00%
- 180 0.00%
- 181 0.00%
- 182 0.00%
- 183 0.00%
- 184 0.00%
- 185 0.00%
- 186 0.00%
- 187 0.00%
- 188 0.00%
- 189 0.00%
- 190 0.00%
- 191 0.00%
- 192 0.00%
Rider damage (rider <expr>)
The rider postfix attaches an extra damage expression
that fires on every hit. On a normal hit the rider's value is
added to the base damage; on a crit the rider's dice are
doubled too (per RAW — the same rule that doubles the base
damage dice). On a miss, no rider — the rider only fires when
the swing connects.
Use this for any "extra dice on hit" mechanic that fires every time:
-
Smite — Paladin spending a 1st-level slot on a
longsword swing:
1d8+5 @ AC15 +9 rider 2d8. -
Hex / Hunter's Mark — flat 1d6 rider on every
hit while concentration holds:
1d8+5 @ AC15 +9 rider 1d6. -
Improved Divine Smite + Extra Attack — both
swings carry the same rider:
1d8+5 @ AC15 +9 rider 2d8 attacks 2.
Sneak Attack is not a rider — use sneak instead.
Sneak Attack triggers once per turn, on the first
qualifying hit. Using rider for it on a multi-attack
chain would double-count, since rider fires on every hit. The
sneak postfix on a multi-attack chain (next section)
models the once-per-chain semantics correctly.
1d8+5 @ AC15 +9 rider 2d8
- 0 25.00%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 0.00%
- 7 0.00%
- 8 0.14%
- 9 0.41%
- 10 0.82%
- 11 1.37%
- 12 2.05%
- 13 2.87%
- 14 3.83%
- 15 4.92%
- 16 5.75%
- 17 6.30%
- 18 6.58%
- 19 6.59%
- 20 6.33%
- 21 5.80%
- 22 5.00%
- 23 3.93%
- 24 3.01%
- 25 2.22%
- 26 1.57%
- 27 1.06%
- 28 0.69%
- 29 0.44%
- 30 0.33%
- 31 0.34%
- 32 0.35%
- 33 0.34%
- 34 0.33%
- 35 0.30%
- 36 0.27%
- 37 0.24%
- 38 0.21%
- 39 0.17%
- 40 0.13%
- 41 0.10%
- 42 0.08%
- 43 0.05%
- 44 0.04%
- 45 0.02%
- 46 0.02%
- 47 0.01%
- 48 0.00%
- 49 0.00%
- 50 0.00%
- 51 0.00%
- 52 0.00%
- 53 0.00%
1d8+5 @ AC15 +9 rider 2d8 attacks 2
- 0 6.25%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 0.00%
- 7 0.00%
- 8 0.07%
- 9 0.21%
- 10 0.41%
- 11 0.68%
- 12 1.03%
- 13 1.44%
- 14 1.91%
- 15 2.46%
- 16 2.87%
- 17 3.15%
- 18 3.29%
- 19 3.30%
- 20 3.19%
- 21 2.95%
- 22 2.59%
- 23 2.11%
- 24 1.74%
- 25 1.48%
- 26 1.32%
- 27 1.29%
- 28 1.36%
- 29 1.54%
- 30 1.82%
- 31 2.19%
- 32 2.55%
- 33 2.88%
- 34 3.17%
- 35 3.39%
- 36 3.53%
- 37 3.57%
- 38 3.53%
- 39 3.39%
- 40 3.18%
- 41 2.91%
- 42 2.60%
- 43 2.27%
- 44 1.94%
- 45 1.63%
- 46 1.35%
- 47 1.11%
- 48 0.92%
- 49 0.76%
- 50 0.64%
- 51 0.55%
- 52 0.48%
- 53 0.43%
- 54 0.38%
- 55 0.34%
- 56 0.31%
- 57 0.27%
- 58 0.24%
- 59 0.20%
- 60 0.17%
- 61 0.14%
- 62 0.12%
- 63 0.09%
- 64 0.07%
- 65 0.06%
- 66 0.04%
- 67 0.03%
- 68 0.03%
- 69 0.02%
- 70 0.02%
- 71 0.01%
- 72 0.01%
- 73 0.01%
- 74 0.01%
- 75 0.01%
- 76 0.00%
- 77 0.00%
- 78 0.00%
- 79 0.00%
- 80 0.00%
- 81 0.00%
- 82 0.00%
- 83 0.00%
- 84 0.00%
- 85 0.00%
- 86 0.00%
- 87 0.00%
- 88 0.00%
- 89 0.00%
- 90 0.00%
- 91 0.00%
- 92 0.00%
- 93 0.00%
- 94 0.00%
- 95 0.00%
- 96 0.00%
- 97 0.00%
- 98 0.00%
- 99 0.00%
- 100 0.00%
- 101 0.00%
- 102 0.00%
- 103 0.00%
- 104 0.00%
- 105 0.00%
- 106 0.00%
Sneak Attack chain (attacks N sneak <expr>)
The sneak postfix attaches to a multi-attack chain
(attacks N) and adds extra damage to the first
hit (or crit) of the chain — exactly once per round, regardless
of how many attacks land. Models 5e Sneak Attack, where a Rogue
gets their bonus dice once per turn on whichever swing connects
first.
On a crit the sneak dice are doubled too, just like the base damage. On a no-hit chain (every attack misses), no sneak is added — chain damage is zero.
The semantic difference from rider matters as soon
as N > 1:
-
1d6+3 @ AC15 +5 rider 3d6 attacks 2— Rogue with TWO attacks each carrying 3d6 sneak dice (incorrect: doubles up the per-turn limit). -
1d6+3 @ AC15 +5 attacks 2 sneak 3d6— Rogue with TWO attacks where the first hit triggers 3d6 sneak (correct: the per-turn limit is enforced at the chain level).
Composes with rider on the inner attack — a
Paladin/Rogue multiclass declares both, and both fire:
1d8+5 @ AC15 +9 rider 2d8 attacks 2 sneak 3d6
gives every hit Improved Divine Smite (2d8) and
pours sneak dice (3d6) into whichever swing lands
first.
Edge case: attacks 1 sneak X is mathematically equivalent
to rider X — there's only one attack, so "first
hit" and "every hit" are the same event. The engine recognises
this; both forms produce the same distribution.
1d6+3 @ AC15 +5 attacks 2 sneak 3d6
- 0 20.25%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 0.00%
- 7 0.03%
- 8 0.14%
- 9 0.35%
- 10 0.69%
- 11 1.22%
- 12 1.96%
- 13 2.83%
- 14 3.73%
- 15 4.57%
- 16 5.28%
- 17 5.75%
- 18 5.88%
- 19 5.75%
- 20 5.44%
- 21 5.01%
- 22 4.50%
- 23 3.98%
- 24 3.53%
- 25 3.11%
- 26 2.69%
- 27 2.29%
- 28 1.92%
- 29 1.58%
- 30 1.27%
- 31 1.01%
- 32 0.82%
- 33 0.68%
- 34 0.58%
- 35 0.50%
- 36 0.44%
- 37 0.39%
- 38 0.35%
- 39 0.30%
- 40 0.26%
- 41 0.22%
- 42 0.18%
- 43 0.14%
- 44 0.11%
- 45 0.09%
- 46 0.07%
- 47 0.05%
- 48 0.03%
- 49 0.02%
- 50 0.01%
- 51 0.01%
- 52 0.01%
- 53 0.00%
- 54 0.00%
- 55 0.00%
- 56 0.00%
- 57 0.00%
- 58 0.00%
- 59 0.00%
- 60 0.00%
- 61 0.00%
- 62 0.00%
- 63 0.00%
- 64 0.00%
- 65 0.00%
- 66 0.00%
1d6+3 @ AC15 +5 attacks 2 sneak 5d6
- 0 20.25%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 0.00%
- 7 0.00%
- 8 0.00%
- 9 0.00%
- 10 0.01%
- 11 0.02%
- 12 0.05%
- 13 0.12%
- 14 0.24%
- 15 0.44%
- 16 0.74%
- 17 1.14%
- 18 1.65%
- 19 2.25%
- 20 2.91%
- 21 3.56%
- 22 4.17%
- 23 4.67%
- 24 5.02%
- 25 5.19%
- 26 5.19%
- 27 5.02%
- 28 4.73%
- 29 4.35%
- 30 3.91%
- 31 3.45%
- 32 3.00%
- 33 2.55%
- 34 2.14%
- 35 1.76%
- 36 1.43%
- 37 1.14%
- 38 0.90%
- 39 0.72%
- 40 0.59%
- 41 0.50%
- 42 0.45%
- 43 0.43%
- 44 0.42%
- 45 0.42%
- 46 0.42%
- 47 0.42%
- 48 0.41%
- 49 0.40%
- 50 0.38%
- 51 0.36%
- 52 0.33%
- 53 0.29%
- 54 0.26%
- 55 0.23%
- 56 0.19%
- 57 0.16%
- 58 0.14%
- 59 0.11%
- 60 0.09%
- 61 0.07%
- 62 0.05%
- 63 0.04%
- 64 0.03%
- 65 0.02%
- 66 0.01%
- 67 0.01%
- 68 0.01%
- 69 0.00%
- 70 0.00%
- 71 0.00%
- 72 0.00%
- 73 0.00%
- 74 0.00%
- 75 0.00%
- 76 0.00%
- 77 0.00%
- 78 0.00%
- 79 0.00%
- 80 0.00%
- 81 0.00%
- 82 0.00%
- 83 0.00%
- 84 0.00%
- 85 0.00%
- 86 0.00%
- 87 0.00%
- 88 0.00%
- 89 0.00%
- 90 0.00%
Bonus attack on crit (attacks N oncrit <attack>)
The oncrit postfix attaches to a multi-attack chain
(attacks N) and adds a once-per-chain bonus attack
that triggers when at least one of the main attacks crits.
Models 5e Great Weapon Master's bonus haft attack: on a crit,
you get a free bonus-action swing with a melee weapon. The
kill-trigger half of GWM lives in the
GWM-on-kill
cascade pillar — that's the same bonus action wired into
the cascade machinery instead of the per-attack chain.
The bonus is a full attack — it has its own to-hit roll,
miss/hit/crit branches, and damage. Syntax requires the
@ AC<n> +/-<m> postfix on the bonus
expression so the parser can build a complete attack profile:
1d12+15 @ AC15 +4 attacks 2 oncrit 1d12+15 @ AC15 +4
Critical resource semantic: the bonus action is a per-turn resource, so even when both main attacks crit (a Champion's day out), the bonus fires once, not twice. This mirrors how Sneak Attack caps at one trigger per turn — and the analytic mean reflects it: bonus contribution = P(≥1 crit in N) × E[bonus per-attempt], not N × P(crit) × E[bonus per-attempt].
Composes with rider on the inner attack — Smite
(rider, every-hit) plus GWM (oncrit, once-per-chain bonus
attack) is a real Paladin/Fighter multiclass move:
1d12+5 @ AC15 +9 rider 2d8 attacks 2 oncrit 1d12+5 @ AC15 +9.
Each main hit gets Improved Divine Smite damage, and a crit on
either swing triggers a fresh bonus attack with its own to-hit.
sneak and oncrit are mutually
exclusive postfixes on the same chain — the parser rejects
that combination with an explicit error rather than silently
producing the wrong distribution. The realistic build that
would want both (Rogue / Fighter with GWM dipping) is rare
enough that the explicit error is the right surface.
1d12+15 @ AC15 +4 attacks 2 oncrit 1d12+15 @ AC15 +4
- 0 25.00%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 0.00%
- 7 0.00%
- 8 0.00%
- 9 0.00%
- 10 0.00%
- 11 0.00%
- 12 0.00%
- 13 0.00%
- 14 0.00%
- 15 0.00%
- 16 3.75%
- 17 3.77%
- 18 3.78%
- 19 3.80%
- 20 3.82%
- 21 3.84%
- 22 3.85%
- 23 3.87%
- 24 3.89%
- 25 3.91%
- 26 3.92%
- 27 3.94%
- 28 0.21%
- 29 0.19%
- 30 0.17%
- 31 0.16%
- 32 0.28%
- 33 0.41%
- 34 0.53%
- 35 0.67%
- 36 0.80%
- 37 0.94%
- 38 1.07%
- 39 1.22%
- 40 1.36%
- 41 1.53%
- 42 1.69%
- 43 1.86%
- 44 1.76%
- 45 1.64%
- 46 1.52%
- 47 1.40%
- 48 1.27%
- 49 1.14%
- 50 1.00%
- 51 0.86%
- 52 0.71%
- 53 0.55%
- 54 0.40%
- 55 0.23%
- 56 0.20%
- 57 0.18%
- 58 0.16%
- 59 0.14%
- 60 0.13%
- 61 0.12%
- 62 0.11%
- 63 0.11%
- 64 0.10%
- 65 0.10%
- 66 0.11%
- 67 0.11%
- 68 0.12%
- 69 0.12%
- 70 0.13%
- 71 0.13%
- 72 0.13%
- 73 0.12%
- 74 0.12%
- 75 0.11%
- 76 0.11%
- 77 0.10%
- 78 0.09%
- 79 0.08%
- 80 0.07%
- 81 0.06%
- 82 0.05%
- 83 0.04%
- 84 0.03%
- 85 0.03%
- 86 0.02%
- 87 0.02%
- 88 0.01%
- 89 0.01%
- 90 0.01%
- 91 0.01%
- 92 0.00%
- 93 0.00%
- 94 0.00%
- 95 0.00%
- 96 0.00%
- 97 0.00%
- 98 0.00%
- 99 0.00%
- 100 0.00%
- 101 0.00%
- 102 0.00%
- 103 0.00%
- 104 0.00%
- 105 0.00%
- 106 0.00%
- 107 0.00%
- 108 0.00%
- 109 0.00%
- 110 0.00%
- 111 0.00%
- 112 0.00%
- 113 0.00%
- 114 0.00%
- 115 0.00%
- 116 0.00%
- 117 0.00%
1d12+15 @ AC15 +4 c19 attacks 2 oncrit 1d12+15 @ AC15 +4 c19
- 0 25.00%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 0.00%
- 7 0.00%
- 8 0.00%
- 9 0.00%
- 10 0.00%
- 11 0.00%
- 12 0.00%
- 13 0.00%
- 14 0.00%
- 15 0.00%
- 16 3.33%
- 17 3.37%
- 18 3.40%
- 19 3.44%
- 20 3.47%
- 21 3.51%
- 22 3.54%
- 23 3.58%
- 24 3.61%
- 25 3.65%
- 26 3.68%
- 27 3.72%
- 28 0.42%
- 29 0.38%
- 30 0.35%
- 31 0.31%
- 32 0.39%
- 33 0.47%
- 34 0.56%
- 35 0.65%
- 36 0.74%
- 37 0.84%
- 38 0.95%
- 39 1.06%
- 40 1.17%
- 41 1.33%
- 42 1.49%
- 43 1.65%
- 44 1.60%
- 45 1.54%
- 46 1.48%
- 47 1.40%
- 48 1.31%
- 49 1.22%
- 50 1.12%
- 51 1.00%
- 52 0.88%
- 53 0.75%
- 54 0.61%
- 55 0.46%
- 56 0.41%
- 57 0.36%
- 58 0.33%
- 59 0.29%
- 60 0.26%
- 61 0.24%
- 62 0.22%
- 63 0.21%
- 64 0.20%
- 65 0.20%
- 66 0.20%
- 67 0.21%
- 68 0.22%
- 69 0.22%
- 70 0.23%
- 71 0.23%
- 72 0.23%
- 73 0.23%
- 74 0.22%
- 75 0.21%
- 76 0.20%
- 77 0.19%
- 78 0.18%
- 79 0.16%
- 80 0.15%
- 81 0.13%
- 82 0.11%
- 83 0.10%
- 84 0.08%
- 85 0.07%
- 86 0.06%
- 87 0.05%
- 88 0.04%
- 89 0.03%
- 90 0.02%
- 91 0.02%
- 92 0.02%
- 93 0.01%
- 94 0.01%
- 95 0.01%
- 96 0.01%
- 97 0.00%
- 98 0.00%
- 99 0.00%
- 100 0.00%
- 101 0.00%
- 102 0.00%
- 103 0.00%
- 104 0.00%
- 105 0.00%
- 106 0.00%
- 107 0.00%
- 108 0.00%
- 109 0.00%
- 110 0.00%
- 111 0.00%
- 112 0.00%
- 113 0.00%
- 114 0.00%
- 115 0.00%
- 116 0.00%
- 117 0.00%
Bonus action attack (attacks N bonus <attack>)
The bonus postfix attaches an unconditional bonus-
action attack to a multi-attack chain — the bonus always fires
once per chain, regardless of main-attack outcomes. Models any
"you always get one extra attack with X" feature: Polearm
Master's haft, Two-Weapon Fighting's offhand, Crossbow Expert's
hand-crossbow bonus shot, Monk Martial Arts.
Same parse shape as oncrit — the bonus is a full
attack expression with its own @ AC<n> +/-<m>
to-hit. PAM with a glaive (1d10+STR main, 1d4+STR haft) at
+9 vs AC 15:
1d10+5 @ AC15 +9 attacks 2 bonus 1d4+5 @ AC15 +9
Why a postfix when + would seem to suffice?
The grammar actually rejects attacks N + <attack>
(the multi-attack chain returns at the top level), so prior to
this construct PAM wasn't expressible at all. Stacking
bonus with oncrit on the same chain
builds an exclusive-mutex node — see the next section
(PAM + GWM with the per-turn-bonus-action constraint enforced).
Distribution-equivalent at the math layer to a hypothetical
attacks N main + bonus — both are an N-fold convolution
of the main per-attempt distribution, then convolved with the
bonus per-attempt. Linearity gives the closed-form mean:
N · E[main per-attempt] + E[bonus per-attempt].
1d10+5 @ AC15 +9 attacks 2 bonus 1d4+5 @ AC15 +9
- 0 1.56%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 1.97%
- 7 1.99%
- 8 2.02%
- 9 2.05%
- 10 0.98%
- 11 0.96%
- 12 1.69%
- 13 2.43%
- 14 3.18%
- 15 3.97%
- 16 3.30%
- 17 3.47%
- 18 3.73%
- 19 4.06%
- 20 4.47%
- 21 4.98%
- 22 4.65%
- 23 4.30%
- 24 3.94%
- 25 3.56%
- 26 3.78%
- 27 4.01%
- 28 4.08%
- 29 3.99%
- 30 3.73%
- 31 3.28%
- 32 2.92%
- 33 2.55%
- 34 2.17%
- 35 1.78%
- 36 1.39%
- 37 0.99%
- 38 0.66%
- 39 0.42%
- 40 0.27%
- 41 0.21%
- 42 0.16%
- 43 0.12%
- 44 0.08%
- 45 0.06%
- 46 0.04%
- 47 0.02%
- 48 0.01%
- 49 0.01%
- 50 0.00%
- 51 0.00%
- 52 0.00%
- 53 0.00%
- 54 0.00%
- 55 0.00%
- 56 0.00%
- 57 0.00%
- 58 0.00%
- 59 0.00%
- 60 0.00%
- 61 0.00%
- 62 0.00%
- 63 0.00%
1d10+15 @ AC15 +4 attacks 2 bonus 1d4+15 @ AC15 +4
- 0 12.50%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 0.00%
- 7 0.00%
- 8 0.00%
- 9 0.00%
- 10 0.00%
- 11 0.00%
- 12 0.00%
- 13 0.00%
- 14 0.00%
- 15 0.00%
- 16 5.06%
- 17 5.17%
- 18 5.27%
- 19 5.37%
- 20 2.66%
- 21 2.61%
- 22 2.56%
- 23 2.50%
- 24 2.45%
- 25 2.48%
- 26 0.25%
- 27 0.22%
- 28 0.20%
- 29 0.18%
- 30 0.15%
- 31 0.13%
- 32 0.71%
- 33 1.31%
- 34 1.94%
- 35 2.59%
- 36 2.75%
- 37 2.93%
- 38 3.10%
- 39 3.25%
- 40 3.40%
- 41 3.55%
- 42 2.99%
- 43 2.40%
- 44 1.78%
- 45 1.13%
- 46 0.96%
- 47 0.79%
- 48 0.66%
- 49 0.55%
- 50 0.49%
- 51 0.44%
- 52 0.50%
- 53 0.56%
- 54 0.64%
- 55 0.73%
- 56 0.83%
- 57 0.93%
- 58 1.00%
- 59 1.02%
- 60 0.99%
- 61 0.92%
- 62 0.84%
- 63 0.75%
- 64 0.65%
- 65 0.55%
- 66 0.44%
- 67 0.33%
- 68 0.24%
- 69 0.17%
- 70 0.12%
- 71 0.09%
- 72 0.07%
- 73 0.05%
- 74 0.04%
- 75 0.03%
- 76 0.02%
- 77 0.01%
- 78 0.01%
- 79 0.00%
- 80 0.00%
- 81 0.00%
- 82 0.00%
- 83 0.00%
- 84 0.00%
- 85 0.00%
- 86 0.00%
- 87 0.00%
- 88 0.00%
- 89 0.00%
- 90 0.00%
- 91 0.00%
- 92 0.00%
- 93 0.00%
Mutually-exclusive bonus actions (attacks N bonus X oncrit Y)
RAW you have a single bonus action per turn. Two feats that both grant a bonus-action attack — PAM (always available) and GWM (on a crit) — are mutually exclusive in practice: the optimal play uses the GWM bonus when at least one main attack crits (bigger weapon damage), and the PAM haft otherwise.
Stacking bonus and oncrit on the same
attacks N chain encodes exactly this. The two postfixes
can appear in either order; the engine builds the same
mixture distribution either way:
1d10+15 @ AC15 +4 attacks 2 bonus 1d4+15 @ AC15 +4 oncrit 1d10+15 @ AC15 +4
Closed-form mean is straightforward by linearity:
E[total] = N · E[main] + P(no crit) · E[PAM] + P(≥1 crit) · E[GWM]
where P(no crit) = (1 − p_crit)N. The
result sits strictly between the PAM-only number (lower bound;
no crit advantage taken) and the both-bonuses-fire upper bound
(which would over-count the bonus-action slot).
Stacking sneak with bonus on the same
chain (Rogue / PAM, Rogue / TWF — heterogeneous-chain Sneak)
is supported. The Sneak Attack rider attaches to the first
hit-or-crit anywhere in the (main_1, …, main_N, bonus)
sequence, doubled on crit per RAW. sneak with
oncrit on the same chain is mutually exclusive
— the parser rejects it with an explicit error rather than
silently producing the wrong distribution.
Rogue/PAM Glaive at level 5 (1d10+5 main + 1d4+5 haft + 3d6 Sneak), two main attacks vs AC 15 with +9 to hit:
1d10+5 @ AC15 +9 attacks 2 sneak 3d6 bonus 1d4+5 @ AC15 +9
- 0 1.56%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 0.00%
- 7 0.00%
- 8 0.00%
- 9 0.01%
- 10 0.04%
- 11 0.09%
- 12 0.18%
- 13 0.31%
- 14 0.49%
- 15 0.69%
- 16 0.90%
- 17 1.10%
- 18 1.30%
- 19 1.47%
- 20 1.65%
- 21 1.83%
- 22 2.04%
- 23 2.29%
- 24 2.56%
- 25 2.84%
- 26 3.12%
- 27 3.39%
- 28 3.62%
- 29 3.80%
- 30 3.93%
- 31 4.01%
- 32 4.04%
- 33 4.03%
- 34 3.99%
- 35 3.93%
- 36 3.85%
- 37 3.76%
- 38 3.65%
- 39 3.53%
- 40 3.36%
- 41 3.16%
- 42 2.92%
- 43 2.63%
- 44 2.33%
- 45 2.01%
- 46 1.70%
- 47 1.40%
- 48 1.14%
- 49 0.91%
- 50 0.72%
- 51 0.58%
- 52 0.46%
- 53 0.38%
- 54 0.32%
- 55 0.28%
- 56 0.25%
- 57 0.22%
- 58 0.20%
- 59 0.17%
- 60 0.15%
- 61 0.13%
- 62 0.11%
- 63 0.10%
- 64 0.08%
- 65 0.07%
- 66 0.05%
- 67 0.04%
- 68 0.03%
- 69 0.02%
- 70 0.02%
- 71 0.01%
- 72 0.01%
- 73 0.01%
- 74 0.00%
- 75 0.00%
- 76 0.00%
- 77 0.00%
- 78 0.00%
- 79 0.00%
- 80 0.00%
- 81 0.00%
- 82 0.00%
- 83 0.00%
- 84 0.00%
- 85 0.00%
- 86 0.00%
- 87 0.00%
- 88 0.00%
- 89 0.00%
- 90 0.00%
- 91 0.00%
- 92 0.00%
- 93 0.00%
- 94 0.00%
- 95 0.00%
- 96 0.00%
- 97 0.00%
- 98 0.00%
- 99 0.00%
1d10+15 @ AC15 +4 attacks 2 bonus 1d4+15 @ AC15 +4 oncrit 1d10+15 @ AC15 +4
- 0 12.50%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 0.00%
- 7 0.00%
- 8 0.00%
- 9 0.00%
- 10 0.00%
- 11 0.00%
- 12 0.00%
- 13 0.00%
- 14 0.00%
- 15 0.00%
- 16 5.06%
- 17 5.17%
- 18 5.27%
- 19 5.37%
- 20 2.66%
- 21 2.61%
- 22 2.56%
- 23 2.50%
- 24 2.45%
- 25 2.48%
- 26 0.25%
- 27 0.22%
- 28 0.20%
- 29 0.18%
- 30 0.15%
- 31 0.13%
- 32 0.71%
- 33 1.31%
- 34 1.93%
- 35 2.57%
- 36 2.72%
- 37 2.88%
- 38 3.04%
- 39 3.19%
- 40 3.33%
- 41 3.47%
- 42 2.91%
- 43 2.33%
- 44 1.72%
- 45 1.09%
- 46 0.94%
- 47 0.80%
- 48 0.69%
- 49 0.60%
- 50 0.55%
- 51 0.51%
- 52 0.56%
- 53 0.62%
- 54 0.69%
- 55 0.77%
- 56 0.85%
- 57 0.93%
- 58 0.98%
- 59 0.99%
- 60 0.95%
- 61 0.87%
- 62 0.79%
- 63 0.70%
- 64 0.61%
- 65 0.52%
- 66 0.43%
- 67 0.33%
- 68 0.25%
- 69 0.19%
- 70 0.15%
- 71 0.14%
- 72 0.12%
- 73 0.11%
- 74 0.09%
- 75 0.08%
- 76 0.06%
- 77 0.05%
- 78 0.04%
- 79 0.03%
- 80 0.02%
- 81 0.02%
- 82 0.01%
- 83 0.01%
- 84 0.01%
- 85 0.00%
- 86 0.00%
- 87 0.00%
- 88 0.00%
- 89 0.00%
- 90 0.00%
- 91 0.00%
- 92 0.00%
- 93 0.00%
- 94 0.00%
- 95 0.00%
- 96 0.00%
- 97 0.00%
- 98 0.00%
- 99 0.00%
- 100 0.00%
- 101 0.00%
- 102 0.00%
- 103 0.00%
- 104 0.00%
- 105 0.00%
1d10+15 @ AC15 +4 c19 attacks 2 bonus 1d4+15 @ AC15 +4 c19 oncrit 1d10+15 @ AC15 +4 c19
- 0 12.50%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 0.00%
- 7 0.00%
- 8 0.00%
- 9 0.00%
- 10 0.00%
- 11 0.00%
- 12 0.00%
- 13 0.00%
- 14 0.00%
- 15 0.00%
- 16 4.50%
- 17 4.71%
- 18 4.91%
- 19 5.12%
- 20 2.83%
- 21 2.72%
- 22 2.61%
- 23 2.51%
- 24 2.40%
- 25 2.45%
- 26 0.50%
- 27 0.45%
- 28 0.40%
- 29 0.35%
- 30 0.30%
- 31 0.25%
- 32 0.68%
- 33 1.14%
- 34 1.64%
- 35 2.17%
- 36 2.33%
- 37 2.53%
- 38 2.71%
- 39 2.87%
- 40 3.02%
- 41 3.18%
- 42 2.78%
- 43 2.35%
- 44 1.88%
- 45 1.37%
- 46 1.21%
- 47 1.07%
- 48 0.95%
- 49 0.85%
- 50 0.78%
- 51 0.71%
- 52 0.71%
- 53 0.72%
- 54 0.74%
- 55 0.77%
- 56 0.80%
- 57 0.85%
- 58 0.87%
- 59 0.88%
- 60 0.85%
- 61 0.80%
- 62 0.75%
- 63 0.70%
- 64 0.64%
- 65 0.57%
- 66 0.50%
- 67 0.43%
- 68 0.37%
- 69 0.32%
- 70 0.28%
- 71 0.26%
- 72 0.23%
- 73 0.21%
- 74 0.19%
- 75 0.16%
- 76 0.14%
- 77 0.12%
- 78 0.10%
- 79 0.08%
- 80 0.06%
- 81 0.05%
- 82 0.04%
- 83 0.03%
- 84 0.02%
- 85 0.02%
- 86 0.01%
- 87 0.01%
- 88 0.01%
- 89 0.00%
- 90 0.00%
- 91 0.00%
- 92 0.00%
- 93 0.00%
- 94 0.00%
- 95 0.00%
- 96 0.00%
- 97 0.00%
- 98 0.00%
- 99 0.00%
- 100 0.00%
- 101 0.00%
- 102 0.00%
- 103 0.00%
- 104 0.00%
- 105 0.00%
Defender Shield reaction (shield)
The shield postfix on an attack expression models
the 5e wizard / sorcerer Shield reaction: the defender, after
seeing the d20 roll, casts the 1st-level Shield spell and
gains +5 AC against this attack. The d20
faces in the band [ac − to-hit, ac − to-hit + 4]
flip from hits to misses; everything else is unchanged. A
natural 20 still hits and crits — RAW: nat 20 always hits
regardless of AC, so Shield doesn't stop a crit.
Single-attack model. The per-round Shield interaction (Shield
lasts a turn, so subsequent attacks in the same round face
+5 AC for free) isn't part of the surface grammar — every
attack with the shield postfix is modelled as
one independent Shield reaction against that attack alone.
1d8+5 @ AC15 +9
- 0 25.00%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 8.75%
- 7 8.83%
- 8 8.91%
- 9 8.98%
- 10 9.06%
- 11 9.14%
- 12 9.22%
- 13 9.30%
- 14 0.63%
- 15 0.55%
- 16 0.47%
- 17 0.39%
- 18 0.31%
- 19 0.23%
- 20 0.16%
- 21 0.08%
1d8+5 @ AC15 +9 shield
- 0 50.00%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 5.63%
- 7 5.70%
- 8 5.78%
- 9 5.86%
- 10 5.94%
- 11 6.02%
- 12 6.09%
- 13 6.17%
- 14 0.63%
- 15 0.55%
- 16 0.47%
- 17 0.39%
- 18 0.31%
- 19 0.23%
- 20 0.16%
- 21 0.08%
Same Longbow attack vs AC 15 with +9 to-hit. Without Shield
(left), per-attempt mean is 147/20 = 7.35.
With Shield (right) the effective AC becomes 20: faces
6-10 flip from hits to misses, which is 5 of 20 faces × the
~9.5 mean per hit, so the per-attempt mean drops by
~2.375 to ~4.975. The crit branch
(1/20 × 14) is identical in both panels.
Flat damage reduction (dr<n>)
The dr<n> postfix on an attack expression
models flat damage reduction on the defender — Heavy Armor
Master's DR 3 vs non-magical bludgeoning / piercing
/ slashing, magic-item DR, and similar mechanics.
Subtracted from the rolled per-hit base damage and clamped
to zero — a small roll reduced below zero just deals 0,
not negative.
Applied to base damage only; rider damage is not reduced. Riders are typically a different damage type (Smite radiant, Hex necrotic, Hunter's Mark force) and type-specific resistance via the Typed pipeline is the right tool for those cases. On crit the rule still holds: DR applies once to the doubled-dice base damage total (RAW: HAM reduces 3 from any qualifying damage instance, including crits — only one application per damage instance).
Worked example: 1d8+5 @ AC15 +9 dr3 on a Longbow
vs AC 15 with +9 to-hit. Without DR, per-attempt mean is
147/20 = 7.35. With DR 3, every per-hit base
damage gets 3 shaved off (clamped at 0); per-attempt mean
drops to ~5.6. Hit and crit branch probabilities
are unchanged — DR is a damage modifier, not an attack-roll
modifier. Try it at
/strike/1d8+5 @ AC15 +9 dr3.
Combine with shield for a defender wearing
heavy armor + casting Shield, with elven for
attacker advantage variants, with rider for
Smite-on-Heavy-Armor-Master matchups (note the rider
damage bypasses DR per the rule above).
Per-type DR (dr<n>:<type>)
The flat dr<n> applies to total per-hit
base damage. The typed form dr<n>:<type>
reduces only the named damage type's contribution to the
hit. RAW Heavy Armor Master is *"DR 3 vs non-magical
bludgeoning / piercing / slashing"* — explicitly typed —
so this is the right tool for HAM-vs-flaming-sword
matchups where the slashing portion gets reduced and the
fire portion passes through.
Multiple dr<n>:<type> clauses
stack (one per type). Untyped dr<n> and
typed clauses can coexist on the same attack — typed
buckets are reduced first (per type, clamped at 0), then
the resulting total is clamped by any flat dr.
Try
1d8:slashing+1d6:fire @ AC15 +9 dr3:slashing
— Longbow + flaming arrowhead vs HAM target.
Caveat: only explicitly-tagged components are reduced. In
1d8:slashing+5 the +5 is untyped, so
dr3:slashing reduces only the d8 portion. To
have HAM-shaped DR cover the modifier too, type it
explicitly with [1d8+5]:slashing or
1d8:slashing+5:slashing.
Brutal Critical / Savage Attacks (brutal<n>)
The brutal<n> postfix on an attack
expression adds N copies of the weapon's largest damage die
to the crit damage (on top of the existing crit-doubled
dice). Models 5e Half-Orc Savage Attacks (always +1 die on
melee crit) and Barbarian Brutal Critical (+1 at L9, +2 at
L13, +3 at L17). Hits are unaffected — brutal only fires on
crit.
The "weapon die" is the largest die in the damage subtree:
d10 for a Glaive (1d10+5), d12 for a Greataxe
(1d12+5), d6 for a Greatsword (2d6+5),
d8 for a Longsword (1d8+5). Heterogeneous-die
damage expressions take the largest die size present.
Applied to base damage only — rider damage (Smite radiant,
Hex necrotic, Hunter's Mark force) does not get extra brutal
dice. The flat dr still clamps the post-brutal
total normally; per-type dr<n>:<type>
treats brutal dice as untyped (documented v0.1 limitation —
use flat dr for HAM-vs-brutal-Greatsword
modeling).
Worked example: 1d12+5 @ AC15 +9 brutal1 for a
Half-Orc Greataxe Fighter. Without Brutal, crit damage =
2d12+5. With brutal1, crit damage
= 3d12+5. The mean shift is
P(crit) × E[1d12] = 0.05 × 6.5 = 0.325 DPR.
Stack with adv (Reckless Attack barbarian) and
that contribution doubles via the doubled crit chance.
Combination rules
-
One modifier per die term.
1d6!r1is rejected — pick exploding or reroll. -
Modifiers attach to the dice term, not to the sum.
2d6!+5means "exploding 2d6, then add 5", not "explode the whole sum". -
No multiplication, no parentheses. The grammar
is intentionally additive-only.
3 × 1d6is just3d6(which has the same distribution as one die's worth tripled in count, by linearity). -
Case-insensitive operators.
2D20KH1works the same as2d20kh1. -
Whitespace is ignored between tokens.
2d6 + 1d4 - 2and2d6+1d4-2are equivalent.
What's not supported
-
Multiplication (
3 × 1d6). Use3d6instead — the engine has no multiplication operator. -
Comparison / threshold operators (
≥,=, …). The kill-probability question is asked via the URL (/kill/<expr>/<hp>) or the per-page HP slider, not via expression syntax. -
Save-roll attack chains (Cleric Sacred Flame:
save DEXwith no damage on fail). The save layer ships the half / zero modes; rarer "negative save" effects (deal damage iff save succeeds) aren't supported. -
Fully heterogeneous main chains where every attack has
a different damage profile. The
bonus <attack>postfix lets you attach an offhand-different-die attack (PAM glaive haft, CBE bonus shot, TWF offhand) to a homogeneous main chain, andsneakcomposes withbonusacross the (main_1, …, main_N, bonus) sequence — the Rogue/PAM and Rogue/TWF cases. What doesn't work is a chain where the main attacks themselves are non-homogeneous (e.g. greatsword first attack + shortsword second attack), which is rare enough in 5e that no canonical build needs it.sneak+oncriton the same chain (Rogue multiclassing into Champion + GWM) is also rejected with an explicit error. - Per-target state machines beyond cumulative damage. The engine models per-attempt and per-round distributions exactly, and the Markov rounds-to-kill layer extends that to "how many rounds until the boss drops" with optional per-round healing or regeneration (gambler's ruin). What isn't modelled: per-target state machines that aren't cumulative-damage — concentration check chains, save-or- suck conditions propagating across turns, mid-fight HP-threshold transitions that change the strike profile.
- Reactions (Sentinel, Riposte, opportunity attacks). The bonus-action slot is modeled per-turn; reactions need a separate per-turn slot with their own trigger semantics — compose by adding the per-reaction expected damage on top of the per-round chain output for whatever reaction rate your encounter generates.
URL slug encoding
Pages under /strike/<slug> and
/vs/<a>/<b> use a tiny URL-safe substitution
so links don't need percent-encoding:
+↔p-↔m:↔.(typed-damage tags)@↔~(attack-roll postfix)*↔x(multi-attack postfix)- whitespace stripped on encode
So 2d6+5 becomes /strike/2d6'5;
1d8+5 @ AC15 +9 becomes
/strike/1d8'5~AC15'9. Modifiers that don't contain
special characters (like !, r1,
kh1, adv, c19) pass through
unchanged. The substituted characters (p m . ~) are
all RFC 3986 unreserved — no percent-encoding ever needed.
Error messages
The parser surfaces specific errors rather than a generic "syntax error". Common ones:
unexpected end of input— truncated expression.unexpected character: 'x'— couldn't parse pastx.dice count must be at least 1—0d6.dice must have at least 1 side—1d0.a 1-sided die cannot explode—1d1!.a die can carry at most one modifier (! or r<N>)—1d6!r1.kh0 / kl0 is meaningless — keep at least one die—4d6kh0.4d20kh<n> with kept > 1 enumerates 160000 outcomes …— when the brute-enumeration cost (sides^count) exceeds the 200K cap, e.g.5d20kh4.
Try it yourself
↦ Comparison tool — type any expression and see the distribution ↦ Concepts — counterintuitive damage math