0
\$\begingroup\$

I want to find a formula to get the probabilities of dice roles in the game Infinity. In this game people are rolling a set number of 20 sided die against another number of 20 sided die, hoping to roll the higher number. In addition each person has a set target number that limits how high a die value he can use. So if my target number is 13 any number I roll above a 13 does not count.

For example if I am rolling 3 dice (20 sided) and need to roll a 11 or below, and my opponent is rolling 1 die (20 sided) and needs a 14 or below. What are my chances of getting a higher number than him without going over 11?

\$\endgroup\$
  • \$\begingroup\$ Do the dice under your limit add together into a sum? Or are you looking to get your single best die higher than your opponent's single best die? If all their dice roll over their limit, is that an automatic win for you? How are ties handled? \$\endgroup\$ – DMGregory Apr 26 '17 at 22:21
  • \$\begingroup\$ Each die result counts alone and ties candle each other. \$\endgroup\$ – Narrowed Mind Apr 27 '17 at 0:13
  • \$\begingroup\$ "Each die result counts alone and ties candle each other" does that mean that if I roll 10, 15, 15, it is equivalent to me only rolling 10? [I assume meant "cancel"] - Edit: what about 10, 12, 15, 15? Does that equal 22? \$\endgroup\$ – Theraot Apr 27 '17 at 1:12
2
\$\begingroup\$

Let's say out of n D-sided dice, the highest roll I get is an x. What are the chances of that?

Well first, I had to roll nothing higher than x. So that's x eligible rolls per die (1, 2, 3, ... x-1, x), out of D I could have rolled, compounded n times:

 P(no higher than x) = (x/D)^n

Now out of these x possible values, I must have rolled the biggest one, x itself, at least once. That means I didn't roll x-1 or lower all n times:

 P(at least one x | no higher than x) = 1 - P(no x | no higher than x)
                                      = 1 - ((x-1)/x)^n

So, putting these together, the chance that my best roll was x is:

 P(at least one x | no higher than x) * P(no higher than x)
 = (1 - ((x-1)/x)^n) * (x/D)^n

So far so good. But some of my dice might get ruled out by rolling too high. To account for that, I'm going to leave the pure math world and go into some imperative code so we can work iteratively, hopefully a bit clearer than sigma notation. ;)

float[] ProbableBestRollsUnderLimit(int numDice, int numSides, int limit) {

    // Initialize an array to hold our probability of rolling each value.
    // Here I'll assume C# conventions where the array comes pre-initialized with 0s.
    float[] pBest = new float[numSides + 1];

    // Set the zero entry to the probability that we roll every die over the limit.
    pBest[0] = power(numSides - limit, numDice);

    for(int d = 1; d < numDice; d++) {
        // Get probability that we roll exactly d dice within our limiting value.
        float piWithinLimit = power(limit, d) * power(numSides - limit, numDice - d);
        // Factor in combinations of *which* dice were over/within limit.
        piWithinLimit *= choose(numDice, d);

        // Using the formula worked out above, accumulate probabilities of rolling
        // a best-of-d-dice result of i. Here we treat the dice as only limit-sided
        // since our P(i dice within limit) term already rules out the higher rolls.
        for(int i = 1; i <= limit; i++)
            pBest[i] += piWithinLimit * (1f - power((i-1)/i, d))*power(i/limit, d);
    }

    return pBest;
}

This method returns a table of probabilities, where the ith entry is the probability that my best roll is i.


With two of these tables, one for me and one for my opponent, I can work out the probable results of the match:

// My probability table.
float[] myBest = ProbableBestRollsUnderLimit(myDiceCount, 20, myLimit);

// My opponent's probability table.
float[] vsBest = ProbableBestRollsUnderLimit(vsDiceCount, 20, vsLimit);

// Compute a cumulative probability table for "P(opponent rolled lower than X)"
float[] vsLowerThan = new float[21];
for(int i = 0; i < 20; i++)
   vsLowerThan[i+1] = vsLowerThan[i] + vsBest[i];

float pWin = 0f;
float pLose = 0f;
float pTie = 0f;

for(int i = 0; i <= myLimit; i++) {
   // I win if I roll i and my opponent rolled less than i.
   pWin += myBest[i]*vsLowerThan[i];

   // We tie if we both rolled exactly i.
   pTie += myBest[i] * vsBest[i];
}

pLose = 1f - pWin - pTie;

Running these numbers with your example above (3 dice limit 11 vs 1 die limit 14),the 3-dice roller has a 55.97% chance to win, 7.28% chance to tie, and 36.75% chance to lose. (The dominant factor here being that the opponent has a 30% chance to roll over their limit and have their lone die discarded, while with 3 dice we've got only a 9% chance of complete disqualification this way)

This at least looks right to me. I'll offer this for now with the disclaimer that it's after midnight and I haven't tested this thoroughly, so it's entirely possible there's some blatant bugs lurking in there. ;) If you find one, let me know in the comments and we'll get it sorted out!

\$\endgroup\$
  • \$\begingroup\$ Ya that looks like exactly what I wanted. Thank you! \$\endgroup\$ – Narrowed Mind Apr 27 '17 at 15:21

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.