8
\$\begingroup\$

I'm working on a dice-heavy RPG, and trying to model a generic AnyDice function to calculate the probability of rolling a specific desired result for dice faces, such as "At least 3 dice with either 5's or 6's on them", with Y d6 and Z rerolls, rerolling any dice that do not match one of the desired numbers, where Y and Z could be adjusted to allow me to balance the system. Essentially something akin to Yahtzee.

Does anyone have any pointers on how to approach this?


Edit: To elaborate, I am trying specifically to construct a formula that would allow me to input a pattern to match the rolls against, and rerolling ones that fail it. I stumbled upon this answer elsewhere, but can't figure out how to tweak it to accept multiple rerolls and specific patterns such as at least one of 5 and 6.

\$\endgroup\$
3
  • \$\begingroup\$ Welcome to RPG.SE! Take the tour if you haven't already and see the help center or ask us here in the comments (use @ to ping someone) if you need more guidance. Good Luck and Happy Gaming! \$\endgroup\$
    – Someone_Evil
    Commented Apr 22, 2023 at 16:07
  • 1
    \$\begingroup\$ In the interest of getting you as useful answers as possible; what have you tried yourself (and where did you get stuck)? And is there a particular reason you're wanting an Anydice solution (either way is fine)? \$\endgroup\$
    – Someone_Evil
    Commented Apr 22, 2023 at 16:09
  • \$\begingroup\$ Thank you, I added clarifications on the solution I tried and couldn't figure out how to extend to my usecase. It doesn't have to be AnyDice, but it seemed like more flexible and futureproof solution for future tweaks. \$\endgroup\$
    – Nimbrod
    Commented Apr 23, 2023 at 13:00

2 Answers 2

10
\$\begingroup\$

For the particular kind of pattern you describe ("number of dice showing one of a particular set of faces"), the most efficient solution is to start by defining a custom die with its faces relabeled as either 1 (for the faces we want to count) or 0 (for the faces we don't want).

Since comparisons between dice and numbers in AnyDice evaluate to 1 if true and to 0 if false, this can be done simply by comparing the die to a target number and assigning its result to a variable, e.g. like this:

X: d6 >= 5

or (equivalently):

X: [count {5, 6} in d6]

Once you have the custom die, you can roll Y of them and count the number of matching faces simply with:

output YdX named "number of 5s and 6s on [Y]d6"

As for rerolls, it turns out the we can apply a simple trick: since we know that the optimal strategy is to never reroll dice that rolled a matching face (i.e. a face we relabeled with 1) and to always reroll as many dice that rolled a non-matching face (i.e. a face we relabeled with 0) as possible, we can instead just roll Z extra dice (where Z is that maximum allowed number of rerolls) and take the Y highest of them, like this:

output [highest Y of (Y+Z)dX] named "number of 5s and 6s on [Y]d6 with [Z] single die rerolls"

Here's a full example program demonstrating this: https://anydice.com/program/2f089


Update: I assumed above that by "Y dice with Z rerolls" you meant being able to reroll one of the Y dice (not necessarily always the same one) up to Z times.

If you instead meant being able to reroll all of the Y dice at once up to Z times, until you get a good enough roll, you can do that efficiently like this:

output [highest 1 of (1+Z)d(YdX)] named "number of 5s and 6s on [Y]d6 with [Z] full rerolls"

Now, that code really needs a disclaimer. What it's really calculating is the distribution you'd get by rolling 1+Z sets of Y dice and picking the best one of those sets. That's of course not quite the same as being able to reroll a single set of Y dice up to Z times, since you won't know what your future rolls will be when you need to decide whether to reroll.

But if you're just trying to roll at least a certain result, then the optimal rerolling strategy is simple: always reroll if you're below the target, and never reroll if you're at or above it. And it's not hard to see that the only way to fail to hit the target this way is to use up all of your Z rerolls (and your single original roll) and fail all of them. So your chance of rolling at least your target number with this strategy is the same as if you made all 1+Z rolls in advance and just picked the best one.

(Of course, the best roll might be even better than the first successful one, but a success is a success either way.)

So the correct way (for your mechanic) to read the results from this program is to look at it in "At Least" mode:

AnyDice screenshot of a bar chart titled "number of 5s and 6s on 7d6 with 3 full rerolls". The bars are numbered from 0 to 7, and their values are 100% for 0, 100% for 1, 99.52% for 2, 89.40% for 3, 53.29% for 4, 16.91% for 5, 2.72% for 6, and 0.18% for 7.

…and interpret e.g. the 53.29% value for a target number of 4 as the probability of getting at least four 5s and 6s on 7d6 if you can reroll all the dice up to three times and will stop as soon as you get at least four 5s and 6s. And similarly the 16.91% is the probability of getting at least five 5s and 6s if you stop rerolling as soon as you do. But if you stop at four 5s and 6s, you will not get five of them with 16.91% probability.


Update 2: As noted by HighDiceRoller, there's a third possible interpretation: you might mean that you can reroll any subset of the Y dice up to Z times.

Now, for your specific type of pattern (where you just want to roll as many of a particular set of faces as possible, and whether you want to keep or reroll a particular die doesn't depend on any of the other dice) this is equivalent to being able to reroll each individual die separately up to Z times. And thus, we can again model it efficiently in AnyDice just by defining a "best of 1+Z" custom die (based on our relabeled die X above) and then rolling Y of them:

Q: [highest 1 of (1+Z)dX]
output YdQ named "number of 5s and 6s on [Y]d6 with [Z] rerolls of any subset"

Here's a program implementing all three of these possible reroll mechanics: https://anydice.com/program/2f116

(BTW, this is a much stronger reroll mechanic than either of the previous two, effectively combining both of their strongest features: you get just as many potential rerolls per die as with the "reroll all Y dice" mechanic, but you also get to keep all of your "good" rolls instead of having to reroll them along with the bad ones.)

\$\endgroup\$
3
  • \$\begingroup\$ Thanks for the idea! Although I am having bit of a difficulty understanding how adding the extra dice equal to amount of rerolls simulates the rerolls. If we go with a basic example of rolling as many 6's as possible on 5d6 with one reroll, we could potentially roll 10 dice in total given all first ones are blank, rather than just 6d6 as per your suggested formula of Y+Z dice? While researching, I saw another answer of yours with a function that rerolls "bad" results, similar to what I am looking for, seems it and the current solution output different odds: anydice.com/program/2f0d6 \$\endgroup\$
    – Nimbrod
    Commented Apr 23, 2023 at 12:53
  • \$\begingroup\$ @Nimbrod the answer uses different meaning of "reroll" of what you use I believe. The answer assumes "one reroll" means "one die being rerolled" and "two rerolls" means "two dice being rerolled". You seem to intend that "one reroll" means "one chance to select any number of dice and reroll them". In that case, we can't use the simple trick mentioned in this answer. \$\endgroup\$
    – justhalf
    Commented Apr 23, 2023 at 16:06
  • \$\begingroup\$ @Nimbrod: Yes, as justhalf noted, I was assuming that a "reroll" meant rerolling a single die. I added an alternative solution in case you meant rerolling all of the Y dice at once instead. \$\endgroup\$ Commented Apr 24, 2023 at 2:11
1
\$\begingroup\$

The importance of phrasing

At this point we've had at least three interpretations of "rerolling":

  • The initial interpretation: up to Z rerolls of individual dice; multiple rerolls can be applied to the same die.
  • Ilmari Karonen's current interpretation at time of writing: up to Z rerolls of all Y dice at a time.
  • My interpretation of the question text at time of writing:

rerolling any dice that do not match one of the desired numbers

which I take to mean the same as the previous interpretation, except only failures are rerolled each time rather than the entire pool.

Adapting prior work

I stumbled upon this answer elsewhere, but can't figure out how to tweak it to accept multiple rerolls and specific patterns such as at least one of 5 and 6.

In this case, you can nest rerolls, e.g.

W: [d6 reroll {1,2,3,4} as [d6 reroll {1,2,3,4} as d6]]
output [count {5, 6} in 5dW]

You could also make the reroll depth a parameter of the function and process it recursively. However, you may need to increase the maximum function depth from the default value depending on how large the depth (i.e. the number of rerolls Z) could be.

set "maximum function depth" to 20

function: ROLL:n reroll BAD:s as REROLL:d depth DEPTH:n {
  if ROLL = BAD & DEPTH > 0 { result: [REROLL reroll BAD as REROLL depth DEPTH - 1] }
  result: ROLL
}

W: [d6 reroll {1,2,3,4} as d6 depth 2]
output [count {5,6} in 5dW]

Icepool

In my own Icepool Python package I've implemented a built-in reroll method:

from icepool import d6
output(5 @ (d6 >= 5).reroll(depth=2))

You can try it in your browser here.

  • d6 >= 5 works as in AnyDice (see Ilmari Karonen's answer).
  • @ evaluates the left side, rolls the right side that many times, and sums, similar to AnyDice's d operator.
  • reroll rerolls specified outcomes, or if not specified, the single lowest possible outcome (in this case False), with the option to set a particular depth.

Mathematical notes

Suppose your base die has denominator \$q = r + k\$, where \$r / q\$ is the chance of rolling a "bad" outcome (which you would want to reroll) and \$k / q\$ is the chance of rolling a "good" outcome (which you would want to keep). After \$n\$ rerolls, you would only end with a bad outcome if all \$n\$ rolls before it also rolled bad outcomes. So the chance of ending up with a bad outcome is

$$ \frac{r^{n+1}}{q^{n+1}} $$

If there are multiple bad outcomes, you can take one factor of \$r\$ and divide it among the individual bad outcomes accordingly.

The remaining numerator is then the chance of rolling a good outcome.

$$ \frac{q^{n+1} - r^{n+1}}{q^{n+1}} $$

Note that the numerator is divisible by \$q - r = k\$, so you can likewise attribute this to individual good outcomes. If \$k\$ is factored out, the remaining factor is

$$ q^n + rq^{n-1} + \cdots + r^{n-1}q + r^n $$

where the terms correspond to no failures and \$n\$ unused rerolls, one failure and \$n-1\$ unused rerolls, and so on. This thus provides a probabilistic interpretation of the formula for a finite geometric sum.

Extended problems

These solutions rely on the fact that each die is either a success or not, and thus the decision to reroll can be made for each die independent of the others. In cases where this is not true, such as something closer to full Yahtzee or poker dice, you may need to resort to more elaborate methods such as backward induction to find the optimal strategy and the resulting probabilities.

In other words, this depends on the meaning of

input a pattern to match the rolls against

yet another way in which specific phrasing is important.

\$\endgroup\$

You must log in to answer this question.

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