changeset 520:d011d222b4fc

modified open and extra to handle rolls that have elready been extended in some way either by extra, open or each
author digitalxero
date Fri, 19 Mar 2010 18:41:55 -0600
parents e80ca31361e7
children 71219011e19c
files orpg/dieroller/_base.py orpg/dieroller/rollers/std.py
diffstat 2 files changed, 88 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/orpg/dieroller/_base.py	Mon Mar 15 19:24:35 2010 -0600
+++ b/orpg/dieroller/_base.py	Fri Mar 19 18:41:55 2010 -0600
@@ -2,6 +2,7 @@
 import random
 import traceback
 import re
+import time
 from collections import deque, namedtuple
 
 from orpg.external.pyparsing import (Word, alphas, Literal, CaselessLiteral,
@@ -82,38 +83,15 @@
 
             return b
 
-    def extraroll(self, roll):
-        """
-        Utility function to return another roll
-        """
-        return random.randint(1, roll.sides)
-
-    #private methods DO NOT OVERRIDE these
-    _history = deque([])
-    _rolls = None
-    _result = None
-    _official = "<!-- Official Roll {roll_string} => {rolls!s} = ({result}) -->"
-    _opn = {"+": (lambda a,b: a + b),
-           "-": (lambda a,b: a - b),
-           "*": (lambda a,b: a * b),
-           "/": (lambda a,b: float(a) / float(b)),
-           "^": (lambda a,b: a ** b)}
-
-    def __new__(cls):
-        it = cls.__dict__.get("__it__")
-        if it is not None:
-            return it
-        cls.__it__ = it = object.__new__(cls)
-        it._bnf = BNF(it)
-        return it
-
     def __call__(self, roll_string):
         """
-        ** Dont override this **
         This method takes a `roll_string` like [1d4] and does all the parsing
         it will then call `evaluate_roll` to get the results and finally it
         calls `format_result` to allow custom rollers to format their output
         how they see fit.
+
+        This should be the last method you look at overriding, but if you need
+        very non standard rollers
         """
         self._rolls = []
         self._quiet = False
@@ -153,6 +131,41 @@
             logger.exception(traceback.format_exc())
             return roll_string
 
+    def extraroll(self, roll):
+        """
+        Utility function to return another roll
+        """
+        return random.randint(1, roll.sides)
+
+    def extend_roll(self, roll, idx, value=None):
+        roll.modified = roll.modified or roll.result
+        c = roll.modified[idx]
+        new = value or self.extraroll(roll)
+        if isinstance(c, int):
+            roll.modified[idx] = Roll(roll.string, roll.die, roll.sides,
+                                      [c, new])
+        else:
+            roll.modified[idx].result.append(new)
+
+    #private methods DO NOT OVERRIDE these
+    _history = deque([])
+    _rolls = None
+    _result = None
+    _official = "<!-- Official Roll {roll_string} => {rolls!s} = ({result}) -->"
+    _opn = {"+": (lambda a,b: a + b),
+           "-": (lambda a,b: a - b),
+           "*": (lambda a,b: a * b),
+           "/": (lambda a,b: float(a) / float(b)),
+           "^": (lambda a,b: a ** b)}
+
+    def __new__(cls):
+        it = cls.__dict__.get("__it__")
+        if it is not None:
+            return it
+        cls.__it__ = it = object.__new__(cls)
+        it._bnf = BNF(it)
+        return it
+
     def _do_function(self, *args):
         """
         This takes a method from the roller string and calls the
@@ -160,8 +173,9 @@
         if the method does not exist.
         """
         roll_str, loc, tokens = args
-        func = getattr(self, tokens.name)
-        func(*tokens.args)
+        func = getattr(self, tokens.name) or getattr(self, tokens.name + "_")
+        if callable(func):
+            func(*tokens.args)
 
     def _push(self, *args):
         """
@@ -208,11 +222,15 @@
         return self._rollers.keys()
 
     def process_roll(self, roll_string):
-        if isinstance(self._roller, BaseRoller):
-            return self._roller(roll_string)
-        else:
-            #Ok we are using an OLD roller, so have fun with eval and shit
-            return self.proccessRoll(roll_string)
+        st = time.time()
+        try:
+            if isinstance(self._roller, BaseRoller):
+                return self._roller(roll_string)
+            else:
+                #Ok we are using an OLD roller, so have fun with eval and shit
+                return self.proccessRoll(roll_string)
+        finally:
+            print "Roll Time:", time.time()-st
 
     def _get_roller(self):
         return self._roller.name
@@ -349,22 +367,31 @@
         return float(int(self))
 
     def __str__(self):
-        if self._modified:
-            return str(self._modified)
+        out = ['[']
+        use = self._modified or self._result
+        out.extend([str(r) + ', ' for r in use])
+        out[-1] = out[-1].strip(', ')
+        out.append(']')
 
-        return str(self._result)
+        return ''.join(out)
 
     def __add__(self, other):
         return int(self) + other
+    __radd__ = __add__
 
     def __mul__(self, by):
         return int(self) * by
+    __rmul__ = __mul__
 
     def __div__(self, by):
         return int(self) / float(by)
+    def __rdiv__(self, by):
+        return float(by) / float(self)
 
     def __sub__(self, other):
         return int(self) - other
+    def __rsub__(self, other):
+        return other - int(self)
 
     def __iter__(self):
         loop = self._modified or self._result
@@ -380,9 +407,8 @@
         return len(check)
 
     def sort(self, cmp=None, key=None, reverse=False):
-        if self._modified:
-            self._modified.sort(cmp, key, reverse)
-        self._result.sort(cmp, key, reverse)
+        self._modified = self._modified or self._result
+        self._modified.sort(cmp, key, reverse)
 
     def _get_string(self):
         return self._string
--- a/orpg/dieroller/rollers/std.py	Mon Mar 15 19:24:35 2010 -0600
+++ b/orpg/dieroller/rollers/std.py	Fri Mar 19 18:41:55 2010 -0600
@@ -3,7 +3,7 @@
 class StandardRoller(BaseRoller):
     name = "std"
 
-    def ascending(self):
+    def ascending(self, *args):
         """
         Sort the roll in ascending order
         """
@@ -11,7 +11,7 @@
         roll.sort()
         self.history.append(roll)
 
-    def decending(self):
+    def decending(self, *args):
         """
         Sort the roll in decending order
         """
@@ -37,20 +37,22 @@
         roll.modified = roll.result[:num] if not roll.modified else roll.modified[:num]
         self.history.append(roll)
 
-    def extra(self, num):
+    def extra_(self, num):
         """
         Add en extra roll for each current roll larger then `num`
         """
         roll = self.history.pop()
         roll.modified = roll.modified or roll.result
-        extras = []
-        for result in roll:
-            if result >= num:
-                extras.append(self.extraroll(roll))
 
-        roll.modified.extend(extras)
-
-        self.history.append(new_roll)
+        def do_extra(roll_):
+            for i in xrange(len(roll_)):
+                r = roll_.modified[i] if roll_.modified else roll_.result[i]
+                if not isinstance(r, (int, type(None))):
+                    do_extra(r)
+                elif r >= num:
+                    self.extend_roll(roll_, i)
+        do_extra(roll)
+        self.history.append(roll)
 
     def open(self, num):
         """
@@ -60,13 +62,19 @@
         roll = self.history.pop()
         roll.modified = roll.modified or roll.result
 
-        for result in roll:
-            if result >= num:
-                roll.modified.append(self.extraroll(roll))
+        def do_open(roll_):
+            for i in xrange(len(roll_)):
+                r = roll_.modified[i] if roll_.modified else roll_.result[i]
+                if not isinstance(r, (int, type(None))):
+                    do_open(r)
+                else:
+                    while r > num:
+                        self.extend_roll(roll_, i)
+                        r = roll_.modified[i].result[-1]
 
+        do_open(roll)
         self.history.append(roll)
 
-
     def minroll(self, num):
         """
         Ensure that no die roll is less then `num`
@@ -88,7 +96,7 @@
         roll = self.history.pop()
         roll.modified = roll.modified or roll.result
         for i in xrange(len(roll)):
-            roll.modified.append(num)
+            self.extend_roll(roll, i, num)
         self.history.append(roll)
 
     def vs(self, target):