Commandline Die Square
Because Pythonista does not contain scipy, calculating chisquare values using it can have trouble on edge cases. This commandline script can run on data files created by the DieSquare mobile app, and uses scipy to make more reliable calculations.
Specify the DieSquare data file on the command line.
 $ ~/bin/diesquare "Bronze d20.diesquare"
 Degrees of freedom: 19.0 Xsquare: 20.6
 pvalue: 0.359317617197
 d20 bias is unlikely.
You can also specify the die size and a file of tabdelimited or colondelimited data. The file should contain two columns: the result, and how many of those results occurred.
The DieSquare file format is:
 d6
 1: 3
 2: 16
 3: 9
 4: 8
 5: 6
 6: 18
That is, any line beginning with a lowercase “d” is assumed to be specifying the die size; any line with a number followed by a colon and space followed by a number is assumed to be a result. You can also put comments in by preceding the line with a pound symbol (#).
And as you might guess, this die is almost certainly biased.
 $ ~/bin/diesquare "Skull d6.diesquare"
 Degrees of freedom: 5.0 Xsquare: 17.0
 pvalue: 0.00449979697797
 d6 bias is probable.
The code itself (Zip file, 1.6 KB) is very simple.
[toggle code]
 #!/usr/bin/python
 #http://godsmonsters.com/Features/mydicerandom/diesquareios/commandlinediesquare/
 import argparse
 import scipy.stats
 parser = argparse.ArgumentParser(description='Calculate Chi Square pvalue using DieSquare data files.')
 parser.add_argument('die', type=int, help='die size')
 parser.add_argument('data', type=argparse.FileType('r'), nargs=1)
 parser.add_argument('verbose', action='store_true')
 args = parser.parse_args()

class ChiSquare():

def __init__(self, die, rolls):
 self.die = die
 self.parseRolls(rolls)

def parseRolls(self, rolls):
 self.rollCount = 0
 self.rolls = {}

for roll in rolls:

if not roll:
 continue

if roll.startswith('d'):
 self.die = int(roll[1:])
 continue

if roll.startswith('#'):
 continue

if "\t" in roll:
 separator = "\t"

elif ": " in roll:
 separator = ": "

else:
 print("Unknown separator in line ", roll)
 continue
 roll, count = (int(x) for x in roll.split(separator))
 self.rolls[roll] = count
 self.rollCount += count

if not roll:

if args.verbose:
 print(self.rollCount)
 print(self.rolls)

def calculate(self):

if args.verbose:
 print '\n# ', self.die
 expected = float(self.rollCount)/float(self.die)
 freedom = float(self.die  1)
 observed = self.rolls.values()
 expected = [expected]*self.die
 chisquare, pvalue = scipy.stats.chisquare(observed, expected)
 print "Degrees of freedom:", freedom, "Xsquare:", chisquare
 print "pvalue:", pvalue

if pvalue < 0 or pvalue > 1:
 color = '\033[5m\033[91m'
 result = 'unknown; data generates an invalid pvalue'

elif pvalue < .05:

if pvalue < .01:
 color = '\033[91m'
 result = 'probable'

else:
 color = '\033[33m'
 result = 'possible'

if pvalue < .01:

else:
 result = 'unlikely'
 color = '\033[32m'
 #curses.start_color()
 print color + 'd' + unicode(self.die) + ' bias is ' + result + '.\033[0m'

if args.verbose:

def __init__(self, die, rolls):
 calculator = ChiSquare(args.die, args.data[0])
 calculator.calculate()
Half of the code is just parsing the datafile; the actual calculation is a couple of lines using scipy:
 observed = self.rolls.values()
 expected = [expected]*self.die
 chisquare, pvalue = scipy.stats.chisquare(observed, expected)
The variable “observed” is the list of observed result counts. The variable “expected” is the list of expected result counts. For example, rolling a d6 60 times, the expected result count is 10 for each result, so expected will equal “[10, 10, 10, 10, 10, 10]”. And observed will be the actual results; for example, in the above data the die face 1 was rolled three times, 2 sixteen times, 3 nine times, 4 eight times, 5 six times, and 6 eighteen times. This is the list “[3, 16, 9, 8, 6, 18]”. The script, of course, uses the lists it constructed by reading the datafile.
In response to DieSquare for iOS: Are your dice biased? Perform onthefly chisquare tests using your iPad or iPhone and Pythonista.
 DieSquare CL (Zip file, 1.6 KB)
 A commandline script to interpret DieSquare datafiles.
More chisquare
 DieSquare for iOS
 Are your dice biased? Perform onthefly chisquare tests using your iPad or iPhone and Pythonista.
 Are my dice random?
 My d20 appears to have been rolling a lot of ones, a disaster if I were playing D&D but a boon for Gods & Monsters. Is my die really random, or is it skewed towards a particular result? Use the ‘R’ open source statistics tool to find out.
More Programming for Gamers
 Are my dice random?
 My d20 appears to have been rolling a lot of ones, a disaster if I were playing D&D but a boon for Gods & Monsters. Is my die really random, or is it skewed towards a particular result? Use the ‘R’ open source statistics tool to find out.
 Programming for Gamers: Choosing a random item
 If you can understand a roleplaying game’s rules, you can understand programming. Programming is a lot easier.
 Easier random tables
 Rather than having to type table and count, why not just type the table name and an optional count number?
 Programming a Roman thumb
 Before we move on to more complex stuff with the “random” script, how about something even simpler? Choose or die, Bezonian!
 Multiple tables on the same command
 The way the “random” script currently stands, it does one table at a time. Often, however, you have more than one table you know you’re going to need. Why not use one command to rule them all?
 Eight more pages with the topic Programming for Gamers, and other related pages