I setup a thread here called
Prob & Stat 101 to discuss probability theory, as relates to RPGs. There, in the list of free resources, I list three other online dice rollers, and a half dozen other free software packages that can do probability theory.
I developed
Palamedes to compute probabilities for difficult dice mechanics. Here are some examples to illustrate what I mean...
Step DieEarthdawn uses "Step Die" mechanics. You add your relevant stats and skills together to get a "step" number. Then you lookup this step number on a chart to find what dice to roll. You roll the dice and compare the result to a "difficulty" number to decide success or failure. There are two additional complications:
- Dice explode: If you roll the maximum on a die, you add and roll over.
- If you roll a 1 on all your dice, you fail, regardless of the difficulty number.
Example: You attack an opponent using your Melee Weapons talent. Your dexterity step is 8, your Melee Weapons rank is 6, and you are using the Aggressive Attack option, which gives a +3 step bonus. 8+6+3=17, so your Attack Step is 17. You will roll a d20 and a d10, and add the results.
Palamedes supports exploding dice. Instead of entering "d20", you input "x20" to mean an exploding 20-sided die. To simulate the roll in the example, you would do
In[0] := x20+x10
Out[0] := 17
If you roll 1s on both dice, you fail even if the target number is 2. In Palamedes, you can compute this probability as follows:
In[1] := probability(x20=1 and x10=1)
Out[1] := 0.00500000000000000
In[2] := probability(x20=1 and x10=1)//rational NB. Same thing but format output as rational number
Out[2] := 1/200
In[3] := p(x20=1&&x10=1)//QQ NB. Same thing written more compactly
Out[3] := 1/200
If you want to know your chances of meeting or beating a target number, say 20, you can do this:
In[4] := p(x20+x10>=20)
Out[4] := 0.3519927500062502
To find the mean, do
In[5] := mean(x20+x10)
Out[5] := 17.163058253906254
Similarly, you can compute the standard deviation (sd), variance (var), mode, median, skew, kurtosis, min, max (which you should ignore in this case, there is no max; see the
*Caution below for an explanation), the set of all these statistics (stats) or the Five Number Summary (fivenum).
You can also view a table of probabilities. In this case, you likely want to see a table for the the probabilities of meeting or beating a certain target number.
EDIT: The
cumulative distribution function (or cdf) is the probability of rolling less than or equal to a number. So its complement, 1 - cdf, is the probability of rolling greater than a number. Finally, 1 - cdf + p, is the probability of rolling greater than or equal to a number.
Theoretically, in this case you can roll any number (2 or more) since the dice explode. Palamedes will truncate the list after the probabilities fall below a specified threshold. In this case, using the default tolerance, it displays up to 140, but I'm only going to show the first 50 here in order to save space:
In[6] := 1 - cdf(x10 + x20) + p(x10 + x20)//table
Out[6] :=
key value
2 1
3 0.995
4 0.985
5 0.97
6 0.9500000000000001
7 0.925
8 0.895
9 0.86
10 0.82
11 0.775
12 0.73
13 0.6845
14 0.6385
15 0.592
16 0.5449999999999999
17 0.49749999999999994
18 0.4494999999999999
19 0.4009999999999999
20 0.35199999999999987
21 0.3024999999999999
22 0.25799999999999984
23 0.21819999999999984
24 0.18309999999999985
25 0.15269999999999978
26 0.12699999999999978
27 0.10599999999999979
28 0.08969999999999972
29 0.07809999999999971
30 0.07119999999999972
31 0.06399999999999968
32 0.057299999999999726
33 0.05106999999999974
34 0.04530999999999972
35 0.040019999999999674
36 0.035199999999999704
37 0.030849999999999718
38 0.026969999999999692
39 0.023559999999999637
40 0.02061999999999961
41 0.01764999999999966
42 0.014979999999999619
43 0.012594499999999599
44 0.010493499999999602
45 0.008676999999999624
46 0.007144999999999667
47 0.00589749999999962
48 0.004934499999999594
49 0.004255999999999588
50 0.003861999999999637
Naturally, you can format the results as rational numbers if you prefer. I do anyway, even though it slows down the calculation. Here's the input (output not shown):
1 - cdf(x10 + x20) + p(x10 + x20)//QQ//table
Or if you prefer probabilities in percent format, you could do this:
1 - cdf(x10 + x20) + p(x10 + x20)//percent//table
In case you're wondering, the // is just Mathematica's postfix function application. It allows you to write the function last, rather than first, to help concentrate on what's important. Some languages like F# use |> to mean "pipe forward," which works the same way. That notation is supported too. As a result, you can write the previous expression in many ways. (I support the
Tim Toady philosophy.)
Target Number Dice PoolsThis approach, used in Shadowrun and Storyteller, adds up the number of dice which are equal to or greater than some target number. Thus, you might roll 6d10, and look for how many dice are 8 to 10 for a hard task. This is a
binomial probability distribution. Palamedes let's you compute with these also:
In[0] := let p0 = p(d10>=8)
Out[0] := p0
In[1] := binom(6, p0) |> p |> table
Out[1] :=
key value
0 0.11764899999999995
1 0.30252599999999996
2 0.32413499999999995
3 0.18522000000000005
4 0.059535000000000025
5 0.010206000000000007
6 0.0007290000000000006
In[2] := binom(6, p0) |> stats |> table
Out[2] :=
key value
count 7
kurt -0.20634920634920428
max 6
mean 1.8000000000000003
median 2
min 0
mode 2
sd 1.1224972160321822
skew 0.35634832254989945
var 1.2599999999999998
Highest-Die Dice PoolsThis approach rolls a number of dice and takes the highest number rolled. This is called an
Order Statistic and Palamedes provides builtin support for this too. You can find probabilities for the highest, lowest, or anything in between.
Probability of the middle of three d20s:
orderstat(d20, 3, 2)//table
Probability of the minimum of 2 d20s, e.g., 5E's disadvantage mechanic:
p(min(2#d20))//table
or
orderstat(d20, 2, 1)//table
Another variation on this concept is the "roll 4 dice and keep the highest 3" option for AD&D character creation. Palamedes knows about these rolls too, and can compute exact results:
In[0] := 4d6k3 |> p |> QQ |> table
Out[0] :=
key value
3 1/1296
4 1/324
5 5/648
6 7/432
7 19/648
8 31/648
9 91/1296
10 61/648
11 37/324
12 167/1296
13 43/324
14 10/81
15 131/1296
16 47/648
17 1/24
18 7/432
In[1] := 4d6k3 |> stats |> table
Out[1] :=
key value
count 16
kurt -0.34326388722501333
max 18
mean 12.2445987654321
median 12
min 3
mode 13
sd 2.846844445311498
skew -0.28350765297728664
var 8.10452329580093
In the ICON system used in Star Trek fom Last Unicorn Games, you roll a number of d6's equal to your attribute and take the highest die. The exception to this is that one die is always the Drama Die -- an exploding die.
Let's say you roll 5 dice. That's 4 normal dice and 1 exploding die. Here's how you do this in Palamedes. Notice, I can drop the 6 from d6 and x6, since 6-siders are the default:
[d,d,d,d,x]
Here's how you find the maximum of that roll:
max[d,d,d,d,x]
If you want to see the probability mass function for this roll, do this:
p(max[d,d,d,d,x])|>table
Find the probability of rolling 6 or more:
p(max[d,d,d,d,x]>=6)
Now print a table of statistics for this roll:
In[2] := max[d,d,d,d,x]|>stats|>table
Out[2] :=
key value
count 37
kurt 15.722150008785043
max 42
mean 6.130926354595342
median 6
min 1
mode 6
sd 2.382889767736342
skew 3.1342443451970183
var 5.678163645182558
*Caution: When Palamedes calculates the probability mass function (pmf) for exploding dice, it does not resort to Monte Carlo simulation in this case. It knows the formula for the probability mass functions for d and x and the rules for combining pmfs under the max function. However, it truncates this calculation when the probabilities fall below a certain threshold. And that's why the max shown in the calculation above is 42 rather than infinity (∞), and why the count is 37 rather than infinity. You can see the truncated probability mass of 1x6 with the instruction:
In[3] := 1-sum(p(x))
Out[3] := 0.0000035722450848485465
or about 1 in 279,936.
Additive Dice Pools ... and Monte Carlo simulationIn WEG's D6 system, you roll a handful of d6s and add. One of the dice is designated the Wild Die, an exploding die. Here's how you'd compute statistics for WEG's 6D, i.e., 5d+x:
In[4] := 5d+x |> stats |> table
Out[4] :=
key value
count 67
kurt 1.0824814691755087
max 72
mean 21.699772447988103
median 21
min 6
mode 21
sd 5.021814798634427
skew 0.5710287501396285
var 25.218623871783734
For probabilities in percent format, do any one of these (prefix and postfix forms of the same thing):
table(percent(p(5d+x)))
p(5d+x) |> percent |> table
5d+x//p//percent//table
Another variation on the additive dice pool is Tunnels & Trolls' DARO dice throws, where you roll two dice and if you get doubles, then you add and roll over. There are also TARO dice rolls in character creation, where you roll three dice and if you get triples, then you add and roll over.
Palamedes knows how to do these rolls. And I know closed-form formulae for the pmf and cdf of both these rolls. In Palamedes, I strive to compute probabilities without recourse to Monte Carlo simulation, but I haven't implemented it in these cases yet -- the formulae are a bit dizzying. So if you want to see the statistics for rolling DARO and TARO, then use Palamedes sampling operator # to throw a large sample and then apply the stats function. If you want to see a table of probabilities, then use the sampling operator but apply the freq function instead of the p function. I usually do 100,000 trials, since going any further blows up JavaScript's stack. Here's how to do it for now using sampling, until I update Palamedes with the necessary formulae:
100000 # DARO |> stats |> table
100000 # DARO |> freq |> table
UPDATE: DARO and TARO now work with the probability/p and statistics/stats commands, just like other dice throws.
You can always get a result using sampling, but not always using a purely probabilistic computation. If you try and get a theoretical result, but get an error, then use sampling instead.
More AND LessPalamedes isn't perfect -- There are bugs and JavaScript rounding errors and cryptic error messages and poor documentation. And the language itself is highly idiosyncratic, a reflection of how I think. It's still in the alpha/experimental stage.
On the positive side, it has many powerful features. It can do a lot more than dice rolls. It does Bayesian belief networks and linear algebra too. E.g., using the linear algebra of Markov processes, I used Palamedes to figure out the expected number of turns for 6 LF to elimate 6 LF in
Chainmail, purely theoretically, without recourse to simulation. I then used simulation to verify the theoretical results.
There's already a
thread here on the OD&D Discussion to talk about Palamedes.