172
|
1 #!/usr/bin/env python
|
239
|
2 # Copyright (C) 2000-2010 The OpenRPG Project
|
172
|
3 #
|
239
|
4 # owner@madmathlabs.com
|
172
|
5 #
|
|
6 # This program is free software; you can redistribute it and/or modify
|
|
7 # it under the terms of the GNU General Public License as published by
|
|
8 # the Free Software Foundation; either version 2 of the License, or
|
|
9 # (at your option) any later version.
|
|
10 #
|
|
11 # This program is distributed in the hope that it will be useful,
|
|
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 # GNU General Public License for more details.
|
|
15 #
|
|
16 # You should have received a copy of the GNU General Public License
|
|
17 # along with this program; if not, write to the Free Software
|
|
18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
19 # --
|
|
20 #
|
|
21 # File: dieroller/utils.py
|
|
22 # Author: OpenRPG Team
|
239
|
23 # Maintainer (Traipse): Tyler Starke
|
172
|
24 # Version:
|
184
|
25 # $Id: utils.py,v Traipse 'Ornery-Orc' prof.ebral Exp $
|
172
|
26 #
|
|
27 # Description: Classes to help manage the die roller
|
|
28 #
|
|
29
|
|
30 import re
|
|
31
|
|
32 import orpg.dieroller.rollers
|
|
33 from orpg.dieroller.base import die_rollers
|
|
34
|
243
|
35 """
|
|
36 Die Roller Changes:
|
|
37 I've made some changes for ease of reading. Below you see the new formula and the old depricated formula. The new formula is easier to understand
|
|
38 and works a little better with math. Try this: [(2+4)+4d(6+8)+(4*4)] with both formulas. Traipse succeeds, Standard (1.7.1) fails.
|
|
39
|
|
40 The new formula deals only with numbers of the Fudge roller. The math has a required process flow, which is unliked currently by me but I am not
|
|
41 going to spend more time on at currently to correct it. It occurs when using paranthesis on the facet. If paranthesis are used no modifier can be added
|
|
42 at the end, but you can added it before the roll.
|
|
43
|
|
44 This is the standard roller formula: (Math D Numbers or Math or Fudge). If that fails the new non_stdDie looks for a regExpression formula inside
|
|
45 the current die roller, set under the name. So all of that bloat to include the english language in the Gilcrease 1.8.0 remains bloat and Traipse's
|
|
46 dice can be liberated to do what they want, where they want, when they want.
|
|
47 """
|
|
48
|
172
|
49 class roller_manager(object):
|
|
50 def __new__(cls):
|
|
51 it = cls.__dict__.get("__it__")
|
|
52 if it is not None: return it
|
|
53 cls.__it__ = it = object.__new__(cls)
|
|
54 it._init()
|
|
55 return it
|
|
56
|
|
57 def _init(self):
|
|
58 self.setRoller('std')
|
|
59
|
|
60 def setRoller(self, roller_class):
|
|
61 try: self.roller_class = die_rollers[roller_class]
|
|
62 except KeyError: raise Exception("Invalid die roller!")
|
|
63
|
|
64 def getRoller(self):
|
|
65 return self.roller_class.name
|
|
66
|
|
67 def listRollers(self):
|
|
68 return die_rollers.keys()
|
|
69
|
239
|
70 def completeMath(self, matches):
|
|
71 s = matches.group(0)
|
243
|
72 try: doMath = str(eval(s))
|
|
73 except: doMath = s
|
|
74 return doMath
|
239
|
75
|
243
|
76 def stdDie_Class(self, match):
|
239
|
77 s = match.group(0)
|
172
|
78 num_sides = s.split('d')
|
|
79 if len(num_sides) > 1:
|
|
80 num_sides; num = num_sides[0]; sides = num_sides[1]
|
183
|
81 if sides.strip().upper() == 'F': sides = "'f'"
|
|
82 try:
|
|
83 if int(num) > 100 or int(sides) > 10000: return None
|
|
84 except: pass
|
172
|
85 ret = ['(', num.strip(), "**die_rollers['", self.getRoller(), "'](",
|
184
|
86 sides.strip(), '))']
|
|
87 s = ''.join(ret)
|
|
88 return s
|
|
89
|
172
|
90 # Use this to convert ndm-style (3d6) dice to d_base format
|
243
|
91 def stdDie(self, s):
|
239
|
92 math = '[\(0-9\/\*\-\+\)]+'
|
243
|
93 reg = re.compile('[0-9]+d\s*([0-9]+|'+math+'|[fF])')
|
239
|
94 #reg = re.compile("(?:\d+|\([0-9\*/\-\+]+\))\s*[a-zA-Z]+\s*[\dFf]+") ## Original
|
243
|
95 try:
|
|
96 (result, num_matches) = reg.subn(self.stdDie_Class, s)
|
|
97 #print 'main', result, num_matches
|
|
98 if num_matches == 0 or result is None:
|
|
99 reg = re.compile(math)
|
|
100 (result, math_matches) = reg.subn(self.completeMath, s)
|
|
101 #print 'math1', result, num_matches
|
|
102 reg = re.compile('[0-9]+d\s*([0-9]+|'+math+'|[fF])')
|
|
103 (result, num_matches) = reg.subn(self.stdDie_Class, result)
|
|
104 #print 'math2', result, num_matches
|
|
105 except Exception, e:
|
|
106 print 'Die string conversion failed,', e
|
|
107 return s
|
|
108 return str(result)
|
239
|
109
|
243
|
110 def nonStdDie(self, s):
|
|
111 math = '[\(0-9\/\*\-\+\)]+'
|
|
112 reg = re.compile(math)
|
|
113 (result, math_matches) = reg.subn(self.completeMath, s)
|
239
|
114
|
243
|
115 reg = re.compile(die_rollers._rollers[self.getRoller()].regExpression)
|
|
116 (result, num_matches) = reg.subn(self.roller_class().non_stdDie, s) ## Currently skipping math
|
|
117
|
|
118 if num_matches == 0 or result is None: return s
|
|
119 else: return result
|
172
|
120
|
|
121 def proccessRoll(self, s):
|
243
|
122 ## Re arranged to allow the non standard dice to use the built in roller methods,
|
|
123 ## not re-written roller methods.
|
|
124 b = self.stdDie(s)
|
|
125 try: b = str(eval(b))
|
|
126 except:
|
|
127 b = self.nonStdDie(s)
|
|
128 try: b = str(eval(b))
|
|
129 except: pass
|
184
|
130 return b
|
183
|
131
|
243
|
132
|