In First Edition of WFRPG Damage during combat works as follows:

You roll 2d10 as a perctile die. If you get lower than your skills you hit. You then roll a 1d6 + damage modifier. If you roll a 6, you explode the dice, and roll again.

What is the best way to solve this problem, so that I can help my DM tweak the monster stats to make combat more of a challenge?

(We have advanced about 5-6 more times than the module thinks we have)

  • \$\begingroup\$ Question was answered here: chat.stackexchange.com/transcript/message/11127766#11127766 \$\endgroup\$
    – GMNoob
    Commented Sep 8, 2013 at 14:24
  • \$\begingroup\$ A better question is "Why do you need to use AnyDice for that calculation?". \$\endgroup\$
    – user9281
    Commented Sep 9, 2013 at 0:41
  • \$\begingroup\$ @RickyDemer Do you know of a better way to get an accurate picture of the impact of these changes? \$\endgroup\$
    – GMNoob
    Commented Sep 9, 2013 at 7:29
  • 1
    \$\begingroup\$ Solve (1+2+3+4+5+(x+x))/6 = x to get the average total from a single exploding die, add the damage modifier, and then multiply that by the hit probability. \$\endgroup\$
    – user9281
    Commented Sep 9, 2013 at 8:03
  • 1
    \$\begingroup\$ rpg.stackexchange.com/questions/3274/… is the possible duplicate. \$\endgroup\$
    – Vatine
    Commented Sep 11, 2013 at 0:52

2 Answers 2


Following AnyDice code will generate probability of a defender dying on each of the rounds 1-10, as well as probabilities of taking various amounts of damage from each attack:

WS: 30
loop N over {1..10} 
  HITCHANCE: (1d100 < WS)
  DAMAGETAKEN: [highest of (DAMAGE - TOUGHNESS) and 0]
  output WOUNDS<=0 named "dead in [N] round(s)"
output DAMAGETAKEN named "Damage taken"

Values for WS and STRENGTH should be set to the attacker's parameters, while TOUGHNESS and WOUNDS to those of the defender. The average damage value from the last graph can be used for quick estimation of the average number of rounds the defender will live.

  • 1
    \$\begingroup\$ won't be correct, since you have to confirm the open end on the first damage die, by remaking the to hit check. Note also that you don't confirm further 6's; they just continue to open end. You need a custom explode routine. \$\endgroup\$
    – aramis
    Commented Sep 9, 2013 at 13:36
  • \$\begingroup\$ @aramis Arg, I forgot about that rule, thanks! \$\endgroup\$
    – GMNoob
    Commented Sep 11, 2013 at 12:06

A more technical answer.... I used Python to write a simple enough code that can calculate this. For the non-coders, I am sorry... (I have put the code at the end of the answer so not to get in the way)

I used the variables I got from the chat to get these results:

>>> calculate() 
most common: [(6, '8.5%'), (7, '8.26%'), (5, '8.02%'), (4, '7.89%'), (8, '7.22%'), (3, '7.05%'), (9, '6.64%'), (10, '6.41%'), (2, '5.74%'), (11, '4.87%')] 
minimum: 1, chance: 4.44% 
maximum: 40, chance: 0.01% 
average: 8.5942, nearest: [9.0, 8.0], chance: ['6.64%', '7.22%']

Basically, this is a specific answer, but using the calculate function in this Python code will provide the answers if you give it the right variables. Good luck.


from random import randint
from collections import Counter
import math

def roll_dice(expression, explode=False):
    Rolls X dice of Y sides (XdY) - explode means max result is another dice
    amount, sides = map(int, expression.split('d'))
    result = 0
    roll = 0
    while roll < amount:
        r = randint(1, sides)
        result += r
        if explode and r == sides:
            roll += 1
    return result

def calculate_rounds(ws, toughness, strength, wounds):
    Simulates combat to calculate number of rounds
    n = 0
    while True:
        n += 1
        if roll_dice('1d100') > ws:
        damage = roll_dice('1d6', explode=True) + strength
        wounds -= max(damage - toughness, 0)
        if wounds <= 0:
            return n

def calculate(ws=30, toughness=3, strength=3, wounds=8, times=10000):
    Performs multiple combat simulations to get statistics
    r = [calculate_rounds(ws, toughness, strength, wounds) for _ in range(times)]
    c = Counter(r)
    d = {k:'%s%%'%((float(v)/len(r))*100) for k,v in c.iteritems()}
    minimum = min(d)
    maximum = max(d)
    most_common = [(k, d[k]) for k,_ in c.most_common(10)]
    average = float(sum(r))/len(r)
    nearest = [math.ceil(average), math.floor(average)]
    chance = [d[x] for x in nearest]
    print 'most common: %s' % most_common
    print 'minimum: %s, chance: %s' % (minimum, d[minimum])
    print 'maximum: %s, chance: %s' % (maximum, d[maximum])
    print 'average: %s, nearest: %s, chance: %s' % (average, nearest, chance)
    return c # counter, dictionary of rounds:times for each number of rounds

You must log in to answer this question.

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