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 '19 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 '19 at 19:45
  • 2
    \$\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 '19 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 '19 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 '19 at 17:27

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.

| improve this answer | |
  • \$\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 '19 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"
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.