Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ''' NOTES ON WHAT TO DO NEXT
- I PERSONALLY NEED TO UNDERSTAND ALL THE CODE!
- Run standalone and return something like a tuple
- run standalone with a specified output method
- have an object to hold a bunch of information for you, etc.
- d4-20 results in a minimum value of 1, maybe that's not the best by default unless specified
- d4x20 doesn't multiply
- there's no division, which is probably just fine
- I think I could crash this by doing a mult with like 1.2 or something like that
- there's a reroll feature that I don't really understand currently. I should figure out how this works... and currently it just rr the low values, which is ok.
- '''
- '''CURRENT FEATURES
- Syntax
- rolldesc,min1
- Roll Descriptions
- d4x200 gives 200 results of 1d4
- 12d4 shows the sum of rolling 1d4 twelve times.
- d4^3 gives 3 separate results of rolling 1d4
- 4d6kh3 rolls 4d6 but keeps the results of only the highest 3 dice.
- 4d6kl3 lowest.
- d4+20 gives sum of 1d4 and 20
- d4-20 since the minimum result is currently 1 by default, this will return a 1.
- d4*100 result of d4 multiplied by 100
- '''
- '''FINAL FEATURES
- I'd like to spruce this up with documentation so that it makes a nice HTML page on how to run it.
- I'd like a stand-alone mode that is used to just run a one-shot roll.
- Ideally I'd like my choice of how to output results (html, terminal, etc.)
- I'd like to get rid of all the bugs but I don't know how I would find them, based on having random (and some hidden) output!
- EV calculations, calculating percentage chances of success, etc.
- '''
- # feature: sort the ^ results
- # feature: allow , to give multiple rolls per output
- # feature: tell the rolls that are being made
- # feature: verbose rolls for keeping highest dice
- # feature: allow non-sorting as well as sorting
- # feature request: PUT A SORT RIGHT INTO THE ROLL DEScription
- # therefore functions that sort needs to get it from a self.sort thing.
- # actually maybe not because then I run into this issue of whether or not I
- # always need to have people specify sort vs no sort, etc. Not sure.
- # the self.mult is a partial model of how to solve this, though... consider that.
- # also I will need to update the documentation in order to make this work, maybe I should do something like N and S (sort, nosort)
- # consider doing something with the roll() in order to include a rolldescription there.
- import re, random
- random.seed()
- DEBUG = False
- TESTS = False
- #DEBUG = True
- TESTS = True
- # --------------------------------------------------------------
- def test_rolls():
- # print sum(Roller('3d6*10000').roll()) / float(10000)
- roller = Roller('d20*100')
- roller.rollout()
- def test_patterns():
- p = re.compile(r'\d*d\d+[+-]?\d*', re.IGNORECASE)
- assert p.match('d20')
- assert p.match('1d20')
- assert p.match('d20+2')
- assert p.match('d20-1')
- assert p.match('1D20+1')
- assert p.match('d6')
- assert p.match('3d6')
- assert p.match('15d10-1')
- assert p.match('D20aa') # This passes, but len == len p.match('D20aa').group() fails, which is good.
- assert p.match('2D20')
- #assert p.match('20D') #fails correctly
- #assert p.match('da20').group() #fails correctly
- #assert p.match('ad20') #fails correctly
- #assert p.match('^6') #fails correctly
- p = re.compile(r'\^\d+')
- def tests():
- test_patterns()
- test_rolls()
- # --------------------------------------------------------------
- class Roller:
- def __init__(self, rolldesc='1d20', MIN1=True):
- self.MIN1 = MIN1 #sets whether a dice roll can go below zero or not (2d4 is one roll, not two rolls)
- self.rolldesc = rolldesc
- self.results = []
- self.r = self.roll
- self.mult = False # I think currently this says how many groups to run of the same roll...
- def parse(self):
- pat_num_sides = re.compile(r'\d*D\d+')
- m = pat_num_sides.match(self.rdupper)
- assert m
- m = m.group().split('D')
- numdice = int(m[0]) if m[0] else 1
- dicesides = int(m[1])
- assert numdice > 0
- assert dicesides > 0
- pat_mod = re.compile(r'[+-]\d+')
- m = pat_mod.search(self.rdupper)
- additive = int(m.group()) if m else 0
- pat_multiplicative = re.compile(r'[*]\d+') #CURRENTLY I'M HAVING TROUBLE GETTING THE ASTERISK TO BE PROPERLY SEARCHED AS '*' INSTEAD OF WILDCARD
- m = pat_reps.search(self.rdupper)
- print m
- print m.group()
- multiplicative = int(m.group()[1:]) if m else 1
- assert multiplicative >= 1
- # print multiplicative
- pat_reps = re.compile(r'[X]\d+')
- m = pat_reps.search(self.rdupper)
- reps = int(m.group()[1:]) if m else 1
- assert reps >= 1
- pat_mult = re.compile(r'\^\d+')
- m = pat_mult.search(self.rdupper)
- mult = int(m.group()[1:]) if m else 1
- if mult < 2:
- self.mult = False
- else:
- self.mult = mult
- pat_reroll = re.compile(r'RR\d+')
- m = pat_reroll.search(self.rdupper)
- reroll = int(m.group()[2:]) if m else 0
- # not sure how to do this yet:
- '''
- pat_sort = re.compile(r's')
- if pat_sort.search(self.rdupper): self.sort = true
- '''
- pat_keep = re.compile(r'K[HL]\d+')
- m = pat_keep.search(self.rdupper)
- if m:
- if m.group()[1] == 'H':
- keephigh = int(m.group()[2:])
- keeplow = 0
- else:
- keeplow = int(m.group()[2:])
- keephigh = 0
- else:
- keephigh = 0
- keeplow = 0
- return numdice, dicesides, additive, reps, reroll, keephigh, keeplow, mult
- def newroll(self, rollstr):
- self.rolldesc = rollstr
- def clear_results(self):
- self.results = []
- def roll(self):
- '''Returns list of lists of results.'''
- self.rdupper = self.rolldesc.upper()
- self.clear_results()
- num, sides, mod, reps, reroll, keephigh, keeplow, mult = self.parse()
- def rollgroup(MIN1=True):
- results = []
- for r in range(reps):
- result = 0
- rolls = []
- for n in range(num):
- roll = random.randint(reroll+1,sides) + mod
- rolls.append(roll)
- if DEBUG: print roll
- #FIX: SORTED??
- #rolls = sorted(rolls)
- if keephigh:
- result = sum(rolls[-keephigh:])
- elif keeplow:
- result = sum(rolls[:keeplow])
- else:
- result = sum(rolls)
- if self.MIN1: result = max(result, 1)
- if DEBUG: print result
- results.append(result)
- if DEBUG: print num, sides, mod, reps, reroll, keephigh, keeplow
- if DEBUG: print results
- return results
- if not self.mult:
- self.results = rollgroup(self.MIN1)
- return self.results
- else:
- mults = []
- for m in range(self.mult):
- mults.append(rollgroup(self.MIN1))
- self.results = mults
- return self.results
- def printout(self, sort=False):
- if not self.mult:
- if sort:
- print list(reversed(sorted(self.results)))
- else:
- print self.results
- else:
- for r in self.results:
- if sort:
- print list(reversed(sorted(r)))
- else:
- print r
- def rollout(self, sort=False):
- self.roll()
- self.printout(sort)
- # -------------------------------------------------
- if __name__ == '__main__':
- if TESTS: tests()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement