dice.py: Factored string-based dice creation into a @classmethod

This commit is contained in:
Anna Rose 2012-03-21 12:08:58 -04:00
parent eb1c897b96
commit fb1d1f01a6

82
dice.py
View File

@ -13,6 +13,43 @@ import argparse
# Implements a "dice" - that is, a series of dice plus modifiers # Implements a "dice" - that is, a series of dice plus modifiers
class Dice(): class Dice():
# This builds dice out of a simple input format
# All of the dark regex magic is contained to this function,
# lest it corrupt innocent code
@classmethod
def from_desc(cls, desc):
if not re.match(r'^\d+d\d+', desc):
raise Exception('Dice format invalid. See --help')
(n, s) = re.match(r'^(\d+)d(\d+)', desc).groups()
num = int(n)
sides = int(s)
mod = 0
drop_low = 0
drop_high = 0
reroll = 0
reroll_times = 0
for m in re.findall(r'[dD+-]\d+', desc):
if m[0] == '-':
mod += int(m)
elif m[0] == '+':
mod += int(m[1:])
elif m[0] == 'D':
drop_high = int(m[1:])
elif m[0] == 'd':
drop_low = int(m[1:])
m = re.search(r'r(\d+)(x\d+)?', desc)
if m:
(r, rt) = m.groups()
reroll = int(r)
if rt:
reroll_times = int(rt[1:])
return cls(num, sides, mod, drop_low, drop_high, reroll, reroll_times)
def __init__(self, num, sides, mod, drop_low=0, drop_high=0, reroll=0, reroll_times=0): def __init__(self, num, sides, mod, drop_low=0, drop_high=0, reroll=0, reroll_times=0):
self.num = num self.num = num
self.sides = sides self.sides = sides
@ -23,7 +60,13 @@ class Dice():
self.reroll_times = reroll_times self.reroll_times = reroll_times
self.times_rolled = 0 self.times_rolled = 0
# Rolls the dice, prints the result
def num_rolls(self):
return self.times_rolled
# Rolls the dice, returns a structure
# containing the result plus metadata
def roll(self, verbose=False): def roll(self, verbose=False):
results = [] results = []
rerolled = [] rerolled = []
@ -103,43 +146,12 @@ class Dice():
return "{num}d{sides}{mod}{drop}{reroll}".format(num=self.num, sides=self.sides, mod=mod_info, drop=drop_info, reroll=reroll_info) return "{num}d{sides}{mod}{drop}{reroll}".format(num=self.num, sides=self.sides, mod=mod_info, drop=drop_info, reroll=reroll_info)
# This takes command-line input as dice description strings
# This builds dice out of a simple input format # and builds a list of Dice objects
# All of the dark regex magic is contained to this function,
# lest it corrupt innocent code
def parse_input(args): def parse_input(args):
dice_list = [] dice_list = []
for arg in args: for arg in args:
if not re.match(r'^\d+d\d+', arg): dice_list.append(Dice.from_desc(arg))
continue
(n, s) = re.match(r'^(\d+)d(\d+)', arg).groups()
num = int(n)
sides = int(s)
mod = 0
dlow = 0
dhigh = 0
reroll = 0
reroll_times = 0
for m in re.findall(r'[dD+-]\d+', arg):
if m[0] == '-':
mod += int(m)
elif m[0] == '+':
mod += int(m[1:])
elif m[0] == 'D':
dhigh = int(m[1:])
elif m[0] == 'd':
dlow = int(m[1:])
m = re.search(r'r(\d+)(x\d+)?', arg)
if m:
(r, rt) = m.groups()
reroll = int(r)
if rt:
reroll_times = int(rt[1:])
dice_list.append(Dice(num, sides, mod, drop_low=dlow, drop_high=dhigh, reroll=reroll, reroll_times=reroll_times))
return dice_list return dice_list