Death Saving Throw Success and Failure

r
d&d
Published

September 8, 2023

In Dungeons and Dragons, a character who loses all of their hit points is knocked unconscious. After that, they roll dice to see if they die permanently or if they stabilize. Each turn, they roll a 20-sided die (a d20). A 10 or higher is a success, and a 9 or lower is a failure. There are two special cases: rolling a 1 counts as two failed rolls, and rolling a 20 is an automatic success, stabilizing you with no further rolls needed. Three successes stabilizes you, and three failures kills you permanently. The probability of success in any individual roll is 55%, but what is the probability of success on the whole series of rolls? To answer this, I’ll do a quick simulation.

Because we’re dealing with random numbers, I will set.seed() to ensure replicability.

set.seed(20230908)

For a single trial:

failures <- 0
successes <- 0
while (failures < 3 && successes < 3) {
  roll <- sample(1:20, 1)
  print(paste("Roll:", roll))
  if (roll == 1) {
    failures <- failures + 2
  } else if (roll < 10) {
    failures <- failures + 1
  } else if (roll == 20) {
    successes <- 3
  } else {
    successes <- successes + 1
  }
  print(paste("  Successes:", successes))
  print(paste("  Failures:", failures))
}
[1] "Roll: 18"
[1] "  Successes: 1"
[1] "  Failures: 0"
[1] "Roll: 11"
[1] "  Successes: 2"
[1] "  Failures: 0"
[1] "Roll: 20"
[1] "  Successes: 3"
[1] "  Failures: 0"

Brilliant, I’m alive!

But now we want to repeat that many, many times to calculate the probability of success. I’m going to populate a vector called outcomes with whether each trial resulted in a success – TRUE means three successful saves, FALSE means three failed saves.

n <- 1e6

outcomes <- replicate(n, {
  failures <- 0
  successes <- 0
  while (failures < 3 && successes < 3) {
    roll <- sample(1:20, 1)
    if (roll == 1) {
      failures <- failures + 2
    } else if (roll < 10) {
      failures <- failures + 1
    } else if (roll == 20) {
      successes <- 3
    } else {
      successes <- successes + 1
    }
  }
  successes == 3
})

mean(outcomes)
[1] 0.595217

After one million repetitions, it looks like the probability of success is about 59.5%. Better than 50-50, but still…not great when you’re talking life and death.

It should be noted that without the wrinkles of the natural 1 and natural 20, this is a simple binomial trial where we check for three successes out of five trials with a probability of 0.55.

pbinom(2, size = 5, prob = 0.55, lower.tail = FALSE)
[1] 0.5931269

Which turns out to be almost identical to the actual game mechanic. So the rules for natural 1s and 20s may add some excitement to each roll, but it doesn’t change the math.