My post on probabilities of Marvel Heroic Roleplaying dice pools has gotten a lot of attention, so I’ve decided to share some code that can be used to compute the expected results of dice pools for Cortex+ games. The code is in C# and was written as a very basic console application that prints out the results for a hard-coded set of dice (I was too lazy to add command line support since I had originally intended the code to be a throwaway project that I was just using to crunch numbers while writing the mixed dice pools post).
Here’s the code:
using System;
using System.Collections.Generic;
namespace CortexPlusMath
{
class Program
{
static void Main(string[] args)
{
// Captain America:
// Solo, Enhanced Strength, Weapon, Combat Master
int[] dice = { 6, 8, 8, 10 };
//int[] dice = { 6, 8, 8, 10, 4 };
//int[] dice = { 6, 8, 8, 10, 8 };
//int[] dice = { 6, 8, 10, 10 };
double average =
ComputeAverageResult(dice);
double meanComplications =
ComputeAverageComplications(dice);
double chanceOfComplication =
ComputeChanceOfComplications(dice);
double averageEffectDie =
ComputeAverageEffectDie(dice);
string diceString = "";
foreach (int d in dice)
{
diceString += "d" + d.ToString() + " ";
}
Console.WriteLine("Cortex+ Average");
Console.WriteLine(" Dice Pool: "
+ diceString);
Console.WriteLine(" Average Result: "
+ average.ToString());
Console.WriteLine(" Average Effect Die: "
+ averageEffectDie.ToString());
Console.WriteLine(" Average Number of Complications: "
+ meanComplications.ToString());
Console.WriteLine(" Probability of 1+ Complications: "
+ chanceOfComplication.ToString());
}
static private List GetResultsTable(int[] dice)
{
List possibleResults = new List();
foreach (int sides in dice)
{
List clonedResults = new List();
if (possibleResults.Count == 0)
{
for (int i = 1; i <= sides; i++)
{
DicePool newPool = new DicePool();
newPool.AddDieRoll(new DieRoll(sides, i));
clonedResults.Add(newPool);
}
}
else
{
for (int i = 1; i <= sides; i++)
{
foreach (DicePool oldPool in possibleResults)
{
DicePool newPool = oldPool.Clone();
newPool.AddDieRoll(new DieRoll(sides, i));
clonedResults.Add(newPool);
}
}
}
possibleResults = clonedResults;
}
return possibleResults;
}
static double ComputeAverageResult(int[] dice)
{
List possibleResults = GetResultsTable(dice);
int possibilities = possibleResults.Count;
int total = 0;
foreach (DicePool result in possibleResults)
{
total += result.GetResult();
}
double average = (double)total / (double)possibilities;
return average;
}
static double ComputeAverageComplications(int[] dice)
{
List possibleResults = GetResultsTable(dice);
int possibilities = possibleResults.Count;
int total = 0;
foreach (DicePool result in possibleResults)
{
total += result.GetComplications();
}
double average = (double)total / (double)possibilities;
return average;
}
static double ComputeChanceOfComplications(int[] dice)
{
List possibleResults = GetResultsTable(dice);
int possibilities = possibleResults.Count;
int total = 0;
foreach (DicePool result in possibleResults)
{
if (result.GetComplications() > 0)
{
total++;
}
}
double probability = (double)total / (double)possibilities;
return probability;
}
static double ComputeAverageEffectDie(int[] dice)
{
List possibleResults = GetResultsTable(dice);
int possibilities = possibleResults.Count;
int total = 0;
foreach (DicePool result in possibleResults)
{
total += result.GetEffectDie();
}
double average = (double)total / (double)possibilities;
return average;
}
}
class DieRoll
{
public DieRoll(int sides)
{
Sides = sides;
Randomize();
}
public DieRoll(int sides, int result)
{
Sides = sides;
Result = result;
}
public int Sides { get; set; }
public int Result { get; set; }
public void Randomize()
{
Result = s_rand.Next(1, Sides + 1);
}
private static Random s_rand = new Random();
}
class DieRollComparer : IComparer
{
public int Compare(DieRoll x, DieRoll y)
{
if (x.Result > y.Result)
{
return -1;
}
else if (x.Result < y.Result)
{
return 1;
}
else
{
if (x.Sides < y.Sides)
{
return -1;
}
else if (x.Sides > y.Sides)
{
return 1;
}
else
{
return 0;
}
}
}
}
class DicePool
{
public DicePool()
{
_dice = new List();
}
public void AddDie(int sides)
{
DieRoll roll = new DieRoll(sides);
_dice.Add(roll);
}
public void AddDieRoll(DieRoll roll)
{
_dice.Add(roll);
}
public int GetResult()
{
SortDice();
if (_dice.Count >= 2)
{
int result = 0;
if (_dice[0].Result != 1)
{
result += _dice[0].Result;
}
if (_dice[1].Result != 1)
{
result += _dice[1].Result;
}
return result;
}
else if (_dice.Count == 1)
{
if (_dice[0].Result == 1)
{
return 0;
}
else
{
return _dice[0].Result;
}
}
else
{
return 0;
}
}
public int GetComplications()
{
int complications = 0;
foreach (DieRoll d in _dice)
{
if (d.Result == 1)
{
complications++;
}
}
return complications;
}
public int GetEffectDie()
{
SortDice();
if (_dice.Count < 3 ||
_dice[0].Result == 1 ||
_dice[1].Result == 1 ||
_dice[2].Result == 1)
{
// Default to d4 effect die
return 4;
}
else
{
List remainingDice = new List();
for (int i = 2; i < _dice.Count; i++)
{
if (_dice[i].Result != 1)
{
remainingDice.Add(_dice[i].Sides);
}
}
if (remainingDice.Count >= 2)
{
remainingDice.Sort();
remainingDice.Reverse();
}
return remainingDice[0];
}
}
public DicePool Clone()
{
DicePool clone = new DicePool();
foreach (DieRoll d in _dice)
{
clone._dice.Add(new DieRoll(d.Sides, d.Result));
}
return clone;
}
private void SortDice()
{
_dice.Sort(new DieRollComparer());
}
private List _dice;
}
}


27 July 2012 
![RPG Bloggers Network [RPGBN]](http://glimmthegnome.files.wordpress.com/2011/05/rpgbloggers_member_square-150x150.jpg)


I’m more of a Mathematica/Matlab guy…