The new rules for D&D 5e (formerly known as D&D Next) are finally here:

D&D 5e introduces a new game mechanic, advantage and disadvantage.

**Basic d20 Rules**

Usually, players roll a 20-sided die (d20) to resolve everyting from attempts at diplomacy to hitting someone with a sword. Each thing a player tries to do has a difficulty and rolling greater than or equal to the difficulty (with various modifiers for ability and training and magic items) means the character was successful.

**Advantage and Disadvantage**

As of 5th Edition (5e) rolls can be made with advantage or disadvantage. The rules are:

- Advantage: roll two d20 and take the max
- Normal: roll one d20 and take the result
- Disadvantage: roll two d20 and take the min

So what are the chances that you’ll roll equal to or above given number with advantage, normally, or with disadvantage? Here’s a table.

roll | disadvantage | normal | advantage |
---|---|---|---|

20 | 0.002 | 0.050 | 0.098 |

19 | 0.010 | 0.100 | 0.191 |

18 | 0.022 | 0.150 | 0.278 |

17 | 0.039 | 0.200 | 0.359 |

16 | 0.062 | 0.250 | 0.437 |

15 | 0.089 | 0.300 | 0.510 |

14 | 0.123 | 0.350 | 0.576 |

13 | 0.160 | 0.400 | 0.639 |

12 | 0.202 | 0.450 | 0.698 |

11 | 0.249 | 0.500 | 0.751 |

10 | 0.303 | 0.550 | 0.798 |

9 | 0.361 | 0.600 | 0.840 |

8 | 0.424 | 0.650 | 0.877 |

7 | 0.492 | 0.700 | 0.910 |

6 | 0.564 | 0.750 | 0.938 |

5 | 0.640 | 0.800 | 0.960 |

4 | 0.723 | 0.850 | 0.978 |

3 | 0.811 | 0.900 | 0.990 |

2 | 0.903 | 0.950 | 0.998 |

1 | 1.000 | 1.000 | 1.000 |

The effect is huge. There’s less than a 9% chance of rolling 15 or higher with disadvantage, whereas there’s a 30% chance normally and a 51% chance with advantage.

Here’s a plot (apologies for the poor ggplot2() and png() defaults — I don’t understand ggplot2 config well enough to make titles, clean up labels, axes, tick mark labels, boundaries, margins, colors, and so on to make it more readable without spending all night on the project).

The vertical distances at a given horizontal position show you how much of a bonus you get for advantage or disadvantage.

[*Update: there's an* *alternative plot on the* Roles, Rules, and Rolls* blog* *that displays the difference between advantage and a simple +3 bonus, as used in previous D&D editions.*]

**Analytic Solution**

The probabilities involved are simple rank statistics for two uniform discrete variables.

You can compute these probabilities analytically, as I show in Part III of the page where I explain the math and stats behind my simple baseball simulation game, *Little Professor Baseball*.

The basic game is a cross between *All-Star Baseball* and *Strat-o-Matic*. I wanted a rolling system where both players roll, one for the batter and one for the pitcher, and you use card for the player with the highest roll to resolve the outcome. The winning roll is going to have a distribution like the advantage probabilities above (except that Little Professor Baseball uses rolls from 1–1000 rather than 1–20. As a bonus, earlier sections of the math page explains why *Strat-o-Matic* cards looks so extreme on their own (unlike the *All-Star Baseball* spinners).

I developed the game after reading Jim Albert’s most excellent book, *Curve Ball*, and I included the cards for the 1970 Cinncinnatti Reds and Baltimore Orioles (which for trivia, were mine and Andrew’s favorite teams as kids).

**Simulation-Based Calculation**

I computed the table with a simple Monte Carlo simulation, the R code for which is as follows.

oneroll <- function(D) { return(sample(D,1)); } advantage <- function() { return(max(oneroll(20), oneroll(20))); } disadvantage <- function() { return(min(oneroll(20), oneroll(20))); } NUM_SIMS <- 100000; advs <- rep(0,NUM_SIMS); for (n in 1:NUM_SIMS) advs[n] <- advantage(); disadvs <- rep(0,NUM_SIMS); for (n in 1:NUM_SIMS) disadvs[n] <- disadvantage(); print("", quote=FALSE); print("CCDF (Pr[result >= k])",quote=FALSE); print(sprintf("%2s %6s %6s %6s", "k", "disadv", "normal", "advant"), quote=FALSE); cumulative_disadv <- 0; cumulative_norm <- 0; cumulative_adv <- 0; for (k in 20:1) { cumulative_disadv <- cumulative_disadv + sum(disadvs == k) / NUM_SIMS; cumulative_norm <- cumulative_norm + 0.05; cumulative_adv <- cumulative_adv + sum(advs == k) / NUM_SIMS; print(sprintf("%2d %6.3f %6.3f %6.3f", k, cumulative_disadv, cumulative_norm, cumulative_adv), quote=FALSE); }

I'm sure Ben could've written that in two or three lines of R code.