How to get an AnyDice conditional to convert a sequence to a boolean

anydicerandom-generation

I'm trying to get AnyDice to

  1. roll a dice pool of dNs
  2. if any result = N
  3. roll one more dN
  4. output 1 if that die roll is greater than variable a target number (set by the count of successes e.g. one 'result = N' on the initial roll sets the follow up target to X, two 'result = N' has a target of Y etc.)

I tried writing a custom function (with help from this answer), but I didn't do it right:

function: if CONDITION:n then A else B {
  if CONDITION { result: A } else { result: B }
}


function: explode N:d target P:s {
 EXTREME: [maximum of N]
 COUNT: [count EXTREME in N]
 if COUNT = 1 {
  result: [if d{N} > 1@P then 1 else 0]
 }
 if COUNT = 2 {
  result: [if d{N} > 1@P then 1 else 0]
 }
 result: 0
}

output [explode 2d12 target {7,4}] named "crit check"

I can't see how to make d{N} > 1@P a boolean in my AnyDice programe, what did I do wrong?

Best Answer

As a minor addendum to Someone_Evil's answer, their program will run a lot faster if you replace the line:

output [explode 2d12 on 12 target {7, 4}]

with:

output [explode 2d{0:11, 12} on 12 target {7, 4}]

The only difference is that I've relabeled the sides 1–11 on the initial dice with the number 0. The reason this makes the code faster is that, instead of having to call the function for all the \$\frac{12 \cdot 13}2 = 78\$ possible ordered 2d12 rolls, AnyDice now has to call it for only three possible rolls: {0, 0}, {12, 0} and {12, 12}. Since the function only counts the number of 12s in the roll, the results are still the same.


BTW, here's another solution using (almost) no functions:

N: 2   \ number of dice in the initial pool \
X: 12  \ number of sides on the dice rolled \
TARGETS: {12, 7, 4}

function: P:n at S:s { result: P@S }
output dX > [1 + Nd(dX = X) at TARGETS]

Unfortunately, it seems that AnyDice will raise an error if you try to evaluate the expression P@S where P is a die instead of a number, even though it has a perfectly meaningful and useful interpretation consistent with AnyDice's usual handling of dice in numeric expressions (i.e. evaluate the expression for every possible roll of the dice and collect the results into a custom die). Wrapping the expression in a trivial helper function works around this seemingly arbitrary limitation.

So, how does it work?

  • dX = X yields, in effect, a custom dX with the highest side relabeled "1" and all other sides relabeled "0".
  • Nd(dX = X) rolls N of these dice, effectively giving the number of X rolls on NdX.
  • This number can range from 0 to N, but since 0 is not a valid sequence index in AnyDice, we add one to it, making it range from 1 to N+1 instead. Then we use the resulting number as an index to the TARGETS sequence (via the helper function, since AnyDice refuses to let us do it otherwise), thus mapping each possible value of Nd(dX = X) to a distinct element of the sequence: in this case 0 → 12 (which is an impossible target to exceed with a d12), 1 → 7 and 2 → 4.
  • Finally, we compare the resulting target number to a single dX roll, returning 1 (true) if the roll is greater than the target and 0 (false) otherwise.

Note that we had to include the impossible target value 12 at the beginning of the TARGETS sequence to account for the possibility of the player rolling no twelves on any of the initial dice. Of course, if you wanted to experiment with the possibility of letting the player have a chance to crit even in this case, you could specify some lower (and thus actually achievable) target value here instead.

Related Topic