%matplotlib inline import numpy as np import itertools import matplotlib.pyplot as plt import re import sys # Copyright (c) 2014, Casey Webster. # All rights reserved. # Licensed under BSD 3-clause license. # get a copy at http://opensource.org/licenses/BSD-3-Clause def roll(dicestr): p = re.compile(r""" \(? (?P\d+)? [dD] (?P\d+) (?:\+ (?P\d+) )? \)? (?:[xX*] (?P\d+) )? """, re.VERBOSE) m = p.match(dicestr) if not m: raise ValueError("Invalid string contents") if m.group('ndice') == None: ndice = 1 else: ndice = int(m.group('ndice')) dtype = int(m.group('dtype')) if m.group('add') == None: add = 0 else: add = int(m.group('add')) if m.group('mult') == None: mult = 1 else: mult = int(m.group('mult')) rollinfo(ndice,dtype,add,mult) def rollinfo(ndice,nsides,add,mult): min = (ndice+add)*mult max = ((ndice*nsides)+add)*mult n = max-min+1 rolls = list(itertools.product(range(1,nsides+1),repeat=ndice)) outcomes = len(rolls) rolls = [(sum(x)+add)*mult for x in rolls] counts = list(np.zeros(n)) for i in rolls: counts[i-min] += 1 sums = list(range(min,max+1,mult)) # remove 0-valued elements counts = list(filter((0.).__ne__,counts)) #calc probability stuff p = [float(x/outcomes)*100 for x in counts] ap = np.cumsum(p) mean = np.mean(rolls) std = np.std(rolls) plt.plot(sums,p) plt.fill_between(sums,p,0,where=[(x > mean-std) and (x < mean+std) for x in sums], color='0.75') plt.plot([mean,mean],[0,np.max(p)], color='k') plt.xlim(min,max) plt.ylim(0,np.max(p)) ax2 = plt.twinx() ax2.plot(sums,ap) ax2.set_ylim(0,100) ax2.set_xlim(min,max) title="{0}d{1}".format(ndice,nsides) if add > 0: title +="+{0}".format(add) if mult > 1: title +="*{0}".format(mult) plt.text(0.05,0.90,title, size='x-large', transform=ax2.transAxes) plt.text(0.05,0.85,r"$\mu$ = {0}".format(mean), transform=ax2.transAxes) plt.text(0.05,0.80,r"$\sigma$ = {0:1.2f}".format(std), transform=ax2.transAxes) plt.text(0.05,0.75,r"range = [{0}-{1}]".format(min,max), transform=ax2.transAxes) #plt.xticks([np.arange(min,mean+1,1),np.arange(mean,max,1)]) roll("2d6") roll("(3d6+6)*2") roll("4d6") roll("4d6+6") roll("5d8") roll("d20") roll("4d10*10")