From fb1d1f01a64e9faa7a33fab2abc85735094e0ab3 Mon Sep 17 00:00:00 2001 From: Anna Wiggins Date: Wed, 21 Mar 2012 12:08:58 -0400 Subject: [PATCH] dice.py: Factored string-based dice creation into a @classmethod --- dice.py | 82 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/dice.py b/dice.py index 2020f3c..caa8abc 100755 --- a/dice.py +++ b/dice.py @@ -13,6 +13,43 @@ import argparse # Implements a "dice" - that is, a series of dice plus modifiers 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): self.num = num self.sides = sides @@ -22,8 +59,14 @@ class Dice(): self.reroll = reroll self.reroll_times = reroll_times self.times_rolled = 0 + + + def num_rolls(self): + return self.times_rolled + - # Rolls the dice, prints the result + # Rolls the dice, returns a structure + # containing the result plus metadata def roll(self, verbose=False): results = [] 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) - -# 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 +# This takes command-line input as dice description strings +# and builds a list of Dice objects def parse_input(args): dice_list = [] for arg in args: - if not re.match(r'^\d+d\d+', 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)) + dice_list.append(Dice.from_desc(arg)) return dice_list