verbose = False
def init_length(length,counts):
hold = {}
# On a pool of x dice, you can't ever succeed holding back x-1 dice.
for holdingback in range (0,length-1):
diff = {}
for difficulty in range (5,16):
successes = {}
successes['base'] = 0
successes['ruleone'] = 0
successes['rulesix']= 0
successes['bothrules'] = 0
diff[difficulty] = successes
hold[holdingback] = diff
counts[length] = hold
def count_rule_one(base,dice):
successes = base
for die in dice:
if die == 1:
successes -= 1
if successes < 0:
successes = 0
return successes
def count_rule_six(base,dice):
successes = base
for die in dice:
if die == 6:
successes += 1
if successes < 0:
successes = 0
return successes
def count_rule_both(base,dice):
successes = base
for die in dice:
if die == 1:
successes -= 1
if die == 6:
successes += 1
if successes < 0:
successes = 0
return successes
def count_current(holding,dice,counts):
rank = holding + len(dice)
roll = 0
for die in dice:
roll += die
if verbose:
print 'Rank %d, holding %d, rolling %s=%d against difficulty:' % (rank,holding,dice,roll)
# Assuming success, count how many successes would be achieved under each
# of the rules variations
base = 1 + holding
rule1 = base
rule6 = base
ruleboth = base
for die in dice:
if die == 1:
rule1 -= 1
ruleboth -= 1
if die == 6:
rule6 += 1
ruleboth += 1
if rule1 < 0:
rule1 = 0
if ruleboth < 0:
ruleboth = 0
success = 'base=%d sux, both=%d sux, rule1only=%d sux, rule6only=%d sux' % (base, ruleboth, rule1, rule6)
# Add counts for each difficulty
for difficulty in range (5,16):
successes = counts[rank][holding][difficulty]
target = difficulty + rank
# Now see if we actually succeeded
if roll >= target:
successes['base'] += base
successes['ruleone'] += rule1
successes['rulesix'] += rule6
successes['bothrules'] += ruleboth
if verbose:
print ' %d, target (%d+%d)=%d: %s' % (difficulty, difficulty, rank, target, success)
else:
# Once we hit a failure, higher difficulties will fail too, so, for performance, just bail
if verbose:
print ' %d, target (%d+%d)=%d and up: failure' % (difficulty, difficulty, rank, target)
break
def increment_current(dice,pos):
if pos == len(dice):
return 0;
value = dice[pos];
if (value == 6):
dice[pos] = 1;
return increment_current(dice,pos+1)
else:
dice[pos] = value + 1
return 1
def run_length(length,counts):
for holdingback in range (0,length-1):
currentDice = []
for index in range (length - holdingback):
currentDice.append(1);
cont = 1
possibleOutcomes = 0
while cont:
count_current(holdingback,currentDice,counts)
cont = increment_current(currentDice,0)
possibleOutcomes += 1
counts[length][holdingback]['outcomes'] = possibleOutcomes
def print_length(rank,counts):
labels = {'base' : 'basic',
'ruleone' : '1\'s subtract successes',
'rulesix' : '6\'s add successes',
'bothrules' : '1\'s subtract successes and 6\'s add successes'
}
print ''
print ''
print 'Average successes for rank %d' % (rank)
for key in labels.keys():
print ''
print 'Rules: %s' % (labels[key])
print ' vs. Difficulty'
line = 'Hold\t'
for difficulty in range (5,16):
line += '\t%i' % (difficulty)
print line
for holdingback in range (0,length-1):
possibleOutcomes = counts[length][holdingback]['outcomes']
line = '%i\t' % (holdingback)
for difficulty in range (5,16):
successes = counts[rank][holdingback][difficulty][key] + 0.0
line += '\t%.2f' % (successes / possibleOutcomes)
print line
Counts = {}
for length in range(2, 6):
init_length(length,Counts)
run_length(length,Counts)
print_length(length,Counts)