# How to compute consecutive condition tests used in Warhammer with AnyDice

I try to simulate the Warhammer mechanic with AnyDice. In this specific example I would like to calculate the chances of a character model to produce X not saved wounds attacking X times. Which is simplified calculated by roll to hit -> roll to wound -> armor save -> ward save.

For attacking I would just roll X d6. Here is my calculation so far:

https://anydice.com/program/2f566

The problem is in this case I pass the count of successful rolls to the next step. But I would also like to have the results of the rolls itself to implement some special logic. E.g. successful hits with result "6" produce auto-wound or successful hits with result "6" do not allow an armor save roll.

How can I do that with AnyDice?

• What do you mean by "condition" -- do you want to to select only dice that are above a certain value of pips, or below a certain value, equal to a certain value, or what other condition do you have in mind? May 7 at 22:19
• Yes, I would like to select only dice, that above or below a certain value. May 8 at 4:50
• This sounds like the wound mechanic from Warhammer/W40k, that's ok, but you need to explain a little more. May 8 at 9:05
• I am playing with the Warhammer Fantasy mechanic. Which is simplified: roll to hit -> roll to wound -> armour save -> ward save May 8 at 10:46
• Welcome to RPG.SE! Take the tour if you haven't already, and check out the help center for more guidance. May 8 at 17:19

In general, you can do this by having each function call the next one. That is, instead of writing your [hit ATTACKS] function like this:

function: hit ATTACKS:n {
DICE: ATTACKS d6
if(WS_FOE > WS * 2) { result: [count {5-WS_MODIFIER..6} in DICE] }
if(WS_FOE >= WS & WS_FOE <= WS * 2) { result: [count {4-WS_MODIFIER..6} in DICE]}
if(WS_FOE < WS) { result: [count {3-WS_MODIFIER..6} in DICE]}
}


and then passing the result of that function to [wound HITS] to get the number of wounds, you can instead write it like this to make it call [wound HITS] directly:

function: hit ATTACKS:n {
DICE: ATTACKS d6
if(WS_FOE > WS * 2) { HITS: [count {5-WS_MODIFIER..6} in DICE] }
if(WS_FOE >= WS & WS_FOE <= WS * 2) { HITS: [count {4-WS_MODIFIER..6} in DICE]}
if(WS_FOE < WS) { HITS: [count {3-WS_MODIFIER..6} in DICE]}
result: [wound HITS]
}


Then you can similarly modify your [wound HITS] function to have it call [armor save WOUNDS] directly:

function: wound HITS:n {
DICE: HITS d6
DIFF: T_FOE - S
if(DIFF > 3) { WOUNDS: 0 }
if(DIFF = 3 | DIFF = 2) { WOUNDS: [count {6} in DICE]}
if(DIFF = 1) { WOUNDS: [count {5..6} in DICE]}
if(DIFF = 0) { WOUNDS: [count {4..6} in DICE]}
if(DIFF = -1) { WOUNDS: [count {3..6} in DICE]}
if(DIFF <= -2) { WOUNDS: [count {2..6} in DICE]}
result: [armor save WOUNDS]
}


And then you should change your output statement from:

output [armor save [wound [hit A]]]


to just:

output [hit A]


since now your [hit ATTACKS] function calls the other two functions automatically. And if you did all that right, you should get exactly the same output as before.

OK, so why does that help, if it just gives the same output anyway?

It helps because now you can pass more than just one parameter to the inner functions. So for example, in your [hit ATTACKS] function, you could also pass [count 6 in DICE] as a second parameter to your next function (now redefined e.g. as [wounds HITS with SIXES]) and use it to tweak the wounds and/or armor save calculations.

However, before you do that, you should first make one more change to your [hits ATTACK] function and split it into two functions:

function: hit ATTACKS:n {
DICE: ATTACKS d6
result: [hit roll DICE]
}

function: hit roll DICE:s {
if(WS_FOE > WS * 2) { HITS: [count {5-WS_MODIFIER..6} in DICE] }
if(WS_FOE >= WS & WS_FOE <= WS * 2) { HITS: [count {4-WS_MODIFIER..6} in DICE]}
if(WS_FOE < WS) { HITS: [count {3-WS_MODIFIER..6} in DICE]}
result: [wound HITS]
}


OK, what difference does that make? Nothing, if you just run this code and look at the results. But there's a subtle difference that you can't see directly: DICE inside the [hit roll DICE] helper function has been "frozen" into a sequence containing a fixed sequence of rolled numbers. That matters if you ever try to use it more than once in the function, e.g. to count both hits and sixes separately.

…wait, what?

OK, let me demonstrate with a quick example:

DICE: 5d6
HITS: [count {4..6} in DICE]
SIXES: [count 6 in DICE]
output HITS - SIXES named "this should never be negative, right?"


Actually, if you run the code above, you can see that the output can be negative! Why? Because DICE above has not been "frozen" by passing it into a function (as a sequence parameter), and thus has no fixed value. Every time you use DICE in an expression, AnyDice treats it as a new, independent 5d6 roll. And it's quite possible to roll fewer hits on one 5d6 roll than sixes on another 5d6 roll.

(Also, even the HITS and SIXES variables themselves above are "custom dice", and so have no fixed value either. So even e.g. output HITS - HITS can and will output non-zero results!)

We can fix this by passing the 5d6 "collection of dice" into a function that takes a sequence parameter (i.e. one tagged with :s):

function: test DICE:s {
HITS: [count {4..6} in DICE]
SIXES: [count 6 in DICE]
result: HITS - SIXES
}
output [test 5d6] named "this really is always non-negative"


OK, sorry for that digression. Let's get back to your code. With the [hit ATTACKS] function split as suggested above to freeze the attack rolls, you can now tweak your code e.g. like this:

function: hit roll DICE:s {
if(WS_FOE > WS * 2) { HITS: [count {5-WS_MODIFIER..6} in DICE] }
if(WS_FOE >= WS & WS_FOE <= WS * 2) { HITS: [count {4-WS_MODIFIER..6} in DICE]}
if(WS_FOE < WS) { HITS: [count {3-WS_MODIFIER..6} in DICE]}
SIXES: [count 6 in DICE]
result: [wound HITS with SIXES]
}

function: wound HITS:n with SIXES:n {
DICE: (HITS - SIXES)d6
DIFF: T_FOE - S
if(DIFF > 3) { WOUNDS: 0 }
if(DIFF = 3 | DIFF = 2) { WOUNDS: [count {6} in DICE]}
if(DIFF = 1) { WOUNDS: [count {5..6} in DICE]}
if(DIFF = 0) { WOUNDS: [count {4..6} in DICE]}
if(DIFF = -1) { WOUNDS: [count {3..6} in DICE]}
if(DIFF <= -2) { WOUNDS: [count {2..6} in DICE]}
result: [armor save WOUNDS + SIXES]
}


Now, any natural "6" rolls on the hit roll count as automatic wounds (so we exclude them from the normal wound roll calculation and then add them back at the end before calculating the armor saves).

Ps. A word of warning: while nested functions and "freezing" dice like this are powerful tools, they can also make your program very slow if you overuse them. If that happens, you'll need to find some alternative approach to avoid timeouts.

For example, in your mechanic, the hit/wound/save rolls for each attack are independent. So, instead of calculating the distribution of successful attacks out of A attempts directly (using [hit A]), you can get the same result faster (possibly much faster) by first calculating the success rate of a single attack (using [hit 1]) as a custom die, and then rolling A of these custom dice (with A d [hit 1]) to simulate A independent attacks, like this.

• Thank you so much for your effort! May 8 at 19:16