I am having some difficulty doing opposed rolls over multiple rounds.

I am looking for a character vs. character statistics. I call them "Rookie" and "Enemy" respectively. I want to know what the chances the Rookie wins over the Enemy over X amount of rounds. I'm trying to see how modifiers affect two characters fighting each other over many rounds/turns of play.


  • Rookie Rolls 1d20+0
  • Enemy Rolls 1d20+2
  • If Rookie > Enemy, Rookie Success
  • If Rookie < Enemy, Rookie Loss
  • If Rookie = Enemy, Tie - Must have Success or Loss, so roll again
  • Best 3 out of 5 rounds makes a set
  • If the Rookie gets 3 successes, they win the set
  • If the Enemy gets 3 successes, the Rookie loses the set
  • These do not have to happen in a row

I want to know the success chances of the Rookie winning a 3 out of 5 set. I ended up brute forcing this in C# with 1 million rolls - barring no errors, I am seeing the Rookie win sets about 28.8% 31.8% of the time.

Any ideas? Thanks!

Link to AnyDice Code

X: 5

output 1d20+MODFORROOKIE > 1d20+MODFORENEMY named "d20: Rookies Success in 1 Round"
output 1d20+MODFORROOKIE = 1d20+MODFORENEMY named "d20: Rookies Tie in 1 Round"
output [count 1d20+MODFORROOKIE > 1d20+MODFORENEMY in Xd20] named "d20: Rookies # of Successes in X Rounds"
output [count 1d20+MODFORROOKIE = 1d20+MODFORENEMY in Xd20] named "d20: Rookies # of Ties in X Rounds"
  • \$\begingroup\$ I'm not sure I understand the mechanics of the action you're trying to analyze. If one player or the other wins on an early round, do you stop and not play more rounds? Is it only ties that lead to more rounds being played (or does "reroll" mean something different)? \$\endgroup\$
    – Blckknght
    Jun 22, 2019 at 18:00
  • \$\begingroup\$ This is confusing. Do you want to know the probability that, e.g., the Rookie wins 1 out of X, 2 out of X, ..., X out of X rounds, or do you want to know the probability that the rookie wins 1 round, 2 rounds in a row, 3 rounds in a row, ..., X rounds in a row? \$\endgroup\$
    – HellSaint
    Jun 22, 2019 at 19:45
  • 3
    \$\begingroup\$ As a side note, both of them are easy to calculate through either a geometric distribution or a binomial distribution. You don't actually need to simulate anything on AnyDice for that. \$\endgroup\$
    – HellSaint
    Jun 22, 2019 at 19:46
  • \$\begingroup\$ It is also not clear what mechanic, specifically from 5e, you are trying to model here. Especially because contests in 5e do not use the "reroll if both values are the same", instead it uses a (mathematically) simpler rule which is "in a tie, the attacking/contesting side wins", e.g., an attack roll of 18 wins against an AC of 18. \$\endgroup\$
    – HellSaint
    Jun 22, 2019 at 19:53
  • 2
    \$\begingroup\$ I think your analysis will be much easier if you split it into two parts. First determine the odds of one player or the other winning in a single trial. Then once you have those probabilities, you can plug them into a calculation to find the probabilities of winning multiple times over several trials. \$\endgroup\$
    – Blckknght
    Jun 23, 2019 at 17:27

2 Answers 2


An analytical solution to this system comes in three parts.

First, for a single set of opposed rolls, what are the probabilities of a win, loss, or tie for the Rookie? You could brute-force this by counting the results from all \$20 \times 20 = 400\$ possibilities. However, you can streamline this with conditional probabilities, so for example $$ P(win\space roll)= \sum_{R_i}P(R_i)\times P(win,R_i) $$ \$ P(R_i) \$ is the probability of any individual roll by Rookie and is always \$ \frac 1 {20} \$. \$P(win,R_i)\$ is the probability of Rookie winning if they have rolled \$R_i\$. So if \$R_i = 1\$, Rookie can't win and \$P(win,1)=0\$. If \$R_i=20\$, Rookie will win if the Enemy rolls anything less than 18 (which produces a tie) and \$P(win,20)=\frac {1}{17} \$. Go through this reasoning for all values of \$R_i\$ and perform the sum above and you get \$P(win\space roll) = 0.3825\$.

Similar reasoning will yield \$P(tie\space roll) = 0.045\$ and \$P(lose\space roll) = 0.5725\$.

Second, since ties trigger a re-roll, we need to calculate the probability of a win, possibly after a sequence of ties. Lets call this sequence of rolls a test. The probability of winning a test is the probability of winning on the first roll plus the probability of tying the first roll and winning the second plus the probability of tying the first two and winning the third etc. $$ P(win\space test) = P(w\space r) + P(t\space r)\times P(w\space r) + P(t\space r)^2 \times P(w\space r) + ... $$ or $$ P(win\space test)=\sum_{n=0}^{\infty}P(win\space roll)\times P(tie\space roll)^n $$ This is an infinite geometric series, which will simplify to $$ P(win\space test)=\frac {P(win\space roll)}{1 - P(tie\space roll)} = 0.400524 $$

Finally, we need the probability of winning enough times out of a group of tests. Let's call this a match. You've specified a match to be best of five, so let's look at that. $$ P(win\space match) = P(3w,5t) + P(4w,5t) + P(5w,5t) $$ The individual probabilities are just given by the binomial distribution: the probability of \$k\$ wins out of \$n\$ trials is $$ P(k,n) = \frac {n!}{k!(n-k)!}\times P(win\space trial)^k \times (1 - P(win\space trial))^{n-k} $$ Plug in the numbers, and you get \$P(win\space match) = 0.318345\$

This should be adaptable to a range of different contests. Just change the numbers in the appropriate stage of the calculation.

I'm not sure why there's a discrepancy between your simulation and this result. I'm pretty confident of my math, because I made a number of cross-checks along the way. I'll note that a fixed number of rolls does not yield a fixed number of trials. There will be an average number of trials, but if these weren't counted correctly, it could throw your calculation off.

  • \$\begingroup\$ Hey MacA, this is a well written answer - thanks! I actually had a bug in my brute force after I had another pair of eyes review it. I wasn't handling ties properly. Running 1 million trials again, I get an answer very similar to yours. (0.318743) \$\endgroup\$
    – baylisssm
    Jun 27, 2019 at 0:46

Of course, there's a way to do this in AnyDice, too.

First, we need some helper functions that are unfortunately not yet built into AnyDice by default. This one is helpful for determining whether an opposed roll is a win, a loss or a tie:

function: sign of NUMBER:n {
  if NUMBER > 0 { result: +1 }
  if NUMBER < 0 { result: -1 }
  result: 0

We can use it e.g. like this:

ROOKIE: d20 + 0
ENEMY: d20 + 2

output WINNER named "single round: +1 = Rookie win, -1 = Enemy win, 0 = tie"

Next, we need a function to reroll ties, something like the one from this answer:

function: restrict ROLL:n to RANGE:s {
  if ROLL = RANGE { result: ROLL }
  else { result: d{} }

We can use it like this to get the probability of the Rookie winning, after ties have been rerolled:

ROUND: [restrict WINNER to {+1,-1}] = +1
output ROUND named "single round with rerolls: 1 = Rookie win, 0 = Enemy win"

And finally, we can take the biased die ROUND, which rolls 1 with the probability of the Rookie winning a single round and 0 otherwise, and just plot the outcome of rolling it five times:

output 5dROUND named "number of Rookie wins over 5 rounds"

We can then read the result directly from this output, at least after clicking the "At Least" button:


Or, if you prefer, you can directly compare the number of Rookie wins against 3 and output that figure instead:

output 5dROUND >= 3 named "probability of Rookie winning at least 3 rounds out of 5"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .