Open this document in the playground · Download source
Build and defend a complete scoped model
Part H · L32 · Prerequisite: L31 · One modelling idea
Situation, question, and prediction
Graduation brief: model one target’s risk of taking at least 28 damage from a base D&D 2014 Fireball, with Dexterity save bonus +3 against DC 15. A success halves damage, rounded down. No resistance or Evasion. Before reading the solution, write assumptions, choose representations, predict bounds, and construct the report from a blank file.
Build
Sample solution: build the independent damage total and natural save, then classify their pair. Preserve the actual damage total while deciding whether to halve it. >= includes damage exactly equal to the target’s HP. The policy does not multiply unrelated hit and damage marginals; both determine one event inside the callback.
hp = 28
save_bonus = 3
save_dc = 15
full = dice_pool(8, 6).sum()
bands = scale().step("Below HP threshold").step("Damage reaches HP")
def harm(raw_damage, natural_save):
damage = raw_damage
if natural_save + save_bonus >= save_dc:
damage = raw_damage // 2
if damage >= hp:
return "Damage reaches HP"
return "Below HP threshold"
result = joint_classify(full, d(20), bands, harm)
output("One-target Fireball risk", result)
output("At least current HP in damage", result.pmf("Damage reaches HP"))
One-target Fireball risk · Outcomes
| outcome | % | frac | X/730 |
|---|---|---|---|
| Below HP threshold | 70.3 | 513/730 | 513 |
| Damage reaches HP | 29.7 | 217/730 | 217 |
At least current HP in damage · Prob
| outcome | % | frac | X/730 |
|---|---|---|---|
| At least current HP in damage | 29.7 | 217/730 | 217 |
Run, read, and check
The save succeeds on natural 12–20: 9/20. A successful save deals at most 24, so cannot reach 28 HP. An independent oracle is therefore (11/20) × P(8d6 ≥28). Count eight-d6 totals by repeated convolution or a separate small dynamic count. Overall mean damage is (11/20)×28 + (9/20)×13.75 = 21.5875, but the risk is a separate question.
Change one thing
Set HP to 49: risk is zero. Set HP to 4: every possible damage result reaches it, so risk is one. At HP 28 with save bonus 20 the risk is zero because all ordinary saves succeed; at bonus −20 it becomes P(8d6 ≥28). These are model boundary checks, not special death-save rules.
Try it yourself
Graduation: invent a two-d6 rule where armour subtracts after taking the higher die, then ask about a specified HP threshold. Deliver a standalone literate file, one independent face count, at least two boundary checks, and exclusions. Acceptance criteria: use 36 equally likely pairs, keep the higher before armour, floor at zero, and query inclusively. Example d6+d6, armour 2, HP 4: only a maximum 6 reaches HP, probability 11/36. Do not reuse this Fireball script unchanged.
Rules and model notes
D&D Basic Rules 2014: Fireball, ordinary saves, and rounding down. One target; no shared multi-target event, concentration, resistance, vulnerability, Evasion, or instant-death interpretation. “Damage reaches HP” is not a claim of death.
What you now know / where next
Build and defend a complete scoped model is the reusable idea. Follow the generated previous/next links below, or return to the course index. For a complete self-contained application, see fireball-one-target.
Content ID: L32 · Review status: pilot
Prerequisites: L31