167
|
1 #!/usr/bin/env python
|
|
2 # Copyright (C) 2000-2001 The OpenRPG Project
|
|
3 #
|
|
4 # openrpg-dev@lists.sourceforge.net
|
|
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: die.py
|
|
22 # Author: Andrew Bennett
|
|
23 # Maintainer:
|
|
24 # Version:
|
195
|
25 # $Id: die.py,v Traipse 'Ornery-Orc' prof.ebral Exp $
|
167
|
26 #
|
|
27 # Description: This class is used to make working with dice easier
|
|
28 #
|
|
29
|
195
|
30 __version__ = "$Id: die.py,v Traipse 'Ornery-Orc' prof.ebral Exp Exp $"
|
167
|
31
|
|
32 import random
|
|
33 import UserList
|
|
34 import copy
|
|
35
|
|
36 class die_base(UserList.UserList):
|
|
37 name = None
|
|
38
|
|
39 def __init__(self,source = []):
|
|
40 if isinstance(source, (int, float, basestring)):
|
|
41 s = []
|
|
42 s.append(di(source))
|
195
|
43 else: s = source
|
167
|
44 UserList.UserList.__init__(self,s)
|
|
45
|
|
46 def sum(self):
|
|
47 s = 0
|
|
48 for a in self.data:
|
|
49 s += int(a)
|
|
50 return s
|
|
51
|
|
52 def __lshift__(self,other):
|
|
53 if type(other) == type(3) or type(other) == type(3.0):
|
|
54 o = other
|
|
55 elif hasattr(other,"sum"):
|
|
56 o = other.sum()
|
195
|
57 else: return None
|
167
|
58 result = []
|
|
59 for die in self:
|
195
|
60 if die < o: result.append(die)
|
167
|
61 return self.__class__(result)
|
|
62
|
|
63 def __rshift__(self,other):
|
195
|
64 if type(other) == type(3) or type(other) == type(3.0): o = other
|
|
65 elif hasattr(other,"sum"): o = other.sum()
|
|
66 else: return None
|
167
|
67 result = []
|
|
68 for die in self:
|
195
|
69 if die > o: result.append(die)
|
167
|
70 return self.__class__(result)
|
|
71
|
|
72 def __rlshift__(self,other):
|
|
73 return self.__rshift__(other)
|
|
74
|
|
75 def __rrshift__(self,other):
|
|
76 return self.__lshift__(other)
|
|
77
|
|
78 def __str__(self):
|
228
|
79 try: print "MY STRING", myStr
|
|
80 except: pass
|
167
|
81 if len(self.data) > 0:
|
|
82 myStr = "[" + str(self.data[0])
|
|
83 for a in self.data[1:]:
|
|
84 myStr += ","
|
|
85 myStr += str(a)
|
|
86 myStr += "] = (" + str(self.sum()) + ")"
|
195
|
87 else: myStr = "[] = (0)"
|
167
|
88 return myStr
|
|
89
|
|
90 def __lt__(self,other):
|
|
91 if type(other) == type(3) or type(other) == type(3.0):
|
|
92 return (self.sum() < other)
|
195
|
93 elif hasattr(other,"sum"): return (self.sum() < other.sum())
|
|
94 else: return UserList.UserList.__lt__(self,other)
|
167
|
95
|
|
96 def __le__(self,other):
|
|
97 if type(other) == type(3) or type(other) == type(3.0):
|
|
98 return (self.sum() <= other)
|
195
|
99 elif hasattr(other,"sum"): return (self.sum() <= other.sum())
|
|
100 else: return UserList.UserList.__le__(self,other)
|
167
|
101
|
|
102 def __eq__(self,other):
|
|
103 if type(other) == type(3) or type(other) == type(3.0):
|
|
104 return (self.sum() == other)
|
195
|
105 elif hasattr(other,"sum"): return (self.sum() == other.sum())
|
|
106 else: return UserList.UserList.__eq__(self,other)
|
167
|
107
|
|
108 def __ne__(self,other):
|
195
|
109 if type(other) == type(3) or type(other) == type(3.0): return (self.sum() != other)
|
|
110 elif hasattr(other,"sum"): return (self.sum() != other.sum())
|
|
111 else: return UserList.UserList.__ne__(self,other)
|
167
|
112
|
|
113 def __gt__(self,other):
|
195
|
114 if type(other) == type(3) or type(other) == type(3.0): return (self.sum() > other)
|
|
115 elif hasattr(other,"sum"): return (self.sum() > other.sum())
|
|
116 else: return UserList.UserList.__gt__(self,other)
|
167
|
117
|
|
118 def __ge__(self,other):
|
195
|
119 if type(other) == type(3) or type(other) == type(3.0): return (self.sum() >= other)
|
|
120 elif hasattr(other,"sum"): return (self.sum() >= other.sum())
|
|
121 else: return UserList.UserList.__ge__(self,other)
|
167
|
122
|
|
123 def __cmp__(self,other):
|
|
124 # this function included for backwards compatibility
|
|
125 # As of 2.1, lists implement the "rich comparison"
|
|
126 # methods overloaded above.
|
195
|
127 if type(other) == type(3) or type(other) == type(3.0): return cmp(self.sum(), other)
|
|
128 elif hasattr(other,"sum"): return cmp(self.sum(), other.sum())
|
|
129 else: return UserList.UserList.__cmp__(self,other)
|
167
|
130
|
|
131 def __rcmp__(self,other):
|
|
132 return self.__cmp__(other)
|
|
133
|
|
134 def __add__(self,other):
|
|
135 mycopy = copy.deepcopy(self)
|
|
136 if type(other) == type(3) or type(other) == type(3.0):
|
|
137 other = [static_di(other)]
|
195
|
138 elif type(other) == type("test"): return self
|
167
|
139 mycopy.extend(other)
|
|
140 return mycopy
|
|
141
|
|
142 def __iadd__(self,other):
|
|
143 return self.__add__(other)
|
|
144
|
|
145 def __radd__(self,other):
|
|
146 mycopy = copy.deepcopy(self)
|
|
147 if type(other) == type(3) or type(other) == type(3.0):
|
|
148 new_die = di(0)
|
|
149 new_die.set_value(other)
|
|
150 other = new_die
|
|
151 mycopy.insert(0,other)
|
|
152 return mycopy
|
|
153
|
|
154 def __int__(self):
|
|
155 return self.sum()
|
|
156
|
|
157 def __sub__(self,other):
|
|
158 mycopy = copy.deepcopy(self)
|
|
159 if type(other) == type(3) or type(other) == type(3.0):
|
|
160 neg_die = static_di(-other)
|
|
161 other = [neg_die]
|
195
|
162 else: other = -other
|
167
|
163 mycopy.extend(other)
|
|
164 return mycopy
|
|
165
|
|
166 def __rsub__(self,other):
|
|
167 mycopy = -copy.deepcopy(self)
|
|
168 if type(other) == type(3) or type(other) == type(3.0):
|
|
169 new_die = di(0)
|
|
170 new_die.set_value(other)
|
|
171 other = new_die
|
|
172 mycopy.insert(0,other)
|
|
173 return mycopy
|
|
174
|
|
175 def __isub__(self,other):
|
|
176 return self.__sub__(other)
|
|
177
|
|
178 def __mul__(self,other):
|
195
|
179 if type(other) == type(3) or type(other) == type(3.0): return self.sum() * other
|
|
180 elif hasattr(other,"sum"): return other.sum() * self.sum()
|
|
181 else: return UserList.UserList.__mul__(self,other)
|
167
|
182
|
|
183 def __rmul__(self,other):
|
|
184 return self.__mul__(other)
|
|
185
|
|
186 def __div__(self,other):
|
195
|
187 if type(other) == type(3) or type(other) == type(3.0): return float(self.sum()) / other
|
|
188 elif hasattr(other,"sum"): return float(self.sum()) / other.sum()
|
|
189 else: return UserList.UserList.__div__(self,other)
|
167
|
190
|
|
191 def __rdiv__(self,other):
|
195
|
192 if type(other) == type(3) or type(other) == type(3.0): return other / float(self.sum())
|
|
193 elif hasattr(other,"sum"): return other.sum() / float(self.sum())
|
|
194 else: return UserList.UserList.__rdiv__(self,other)
|
167
|
195
|
|
196 def __mod__(self,other):
|
195
|
197 if type(other) == type(3) or type(other) == type(3.0): return self.sum()%other
|
|
198 elif hasattr(other,"sum"): return self.sum() % other.sum()
|
|
199 else: return UserList.UserList.__mod__(self,other)
|
167
|
200
|
|
201 def __rmod__(self,other):
|
195
|
202 if type(other) == type(3) or type(other) == type(3.0): return other % self.sum()
|
|
203 elif hasattr(other,"sum"): return other.sum() % self.sum()
|
|
204 else: return UserList.UserList.__rmod__(self,other)
|
167
|
205
|
|
206 def __neg__(self):
|
195
|
207 for i in range(len(self.data)): self.data[i] = -self.data[i]
|
167
|
208 return self
|
|
209
|
|
210 def __pos__(self):
|
195
|
211 for i in range(len(self.data)): self.data[i] = +self.data[i]
|
167
|
212 return self
|
|
213
|
|
214 def __abs__(self):
|
195
|
215 for i in range(len(self.data)): self.data[i] = abs(self.data[i])
|
167
|
216 return self
|
|
217
|
|
218 def __pow__(self,other):
|
195
|
219 if type(other) == type(3) or type(other) == type(3.0): return self.sum() ** other
|
|
220 elif hasattr(other,"sum"): return self.sum() ** other.sum()
|
|
221 else: return UserList.UserList.__pow__(self,other)
|
167
|
222
|
|
223 def __rpow__(self,other):
|
|
224 # We're overloading exponentiation of ints to create "other" number of dice
|
|
225 if other >= 1:
|
|
226 result = self.__class__(self[0].sides)
|
195
|
227 for t in range(other-1): result+=self.__class__(self[0].sides)
|
|
228 else: result = None
|
167
|
229 return result
|
|
230
|
|
231 ### di class to handle actual dice
|
|
232
|
|
233 class di:
|
195
|
234 def __init__(self, sides, min=1):
|
167
|
235 self.sides = sides
|
|
236 self.history = None
|
|
237 self.value = None
|
|
238 self.target = None
|
|
239 self.roll(min)
|
|
240
|
|
241 def __str__(self):
|
195
|
242 if len(self.history) > 1: return str(self.history)
|
|
243 else: return str(self.value)
|
167
|
244
|
|
245 def __neg__(self):
|
|
246 self.value = -self.value
|
195
|
247 for i in range(len(self.history)): self.history[i] = -self.history[i]
|
167
|
248 return self
|
|
249
|
|
250 def __pos__(self):
|
|
251 self.value = +self.value
|
195
|
252 for i in range(len(self.history)): self.history[i] = +self.history[i]
|
167
|
253 return self
|
|
254
|
|
255 def __abs__(self):
|
|
256 self.value = abs(self.value)
|
|
257 for i in range(len(self.history)):
|
|
258 self.history[i] = abs(self.history[i])
|
|
259 return self
|
|
260
|
|
261 def __repr__(self):
|
195
|
262 if len(self.history) > 1: return str(self.history)
|
|
263 else: return str(self.value)
|
167
|
264
|
|
265 def __int__(self):
|
|
266 return self.value
|
|
267
|
|
268 def __lt__(self,other):
|
195
|
269 if type(other) == type(3) or type(other) == type(3.0): return self.value < other
|
|
270 elif hasattr(other,"value"): return self.value < other.value
|
|
271 else: return self < other
|
167
|
272
|
|
273 def __le__(self,other):
|
195
|
274 if type(other) == type(3) or type(other) == type(3.0): return self.value <= other
|
|
275 elif hasattr(other,"value"): return self.value <= other.value
|
|
276 else: return self <= other
|
167
|
277
|
|
278 def __eq__(self,other):
|
195
|
279 if type(other) == type(3) or type(other) == type(3.0): return self.value == other
|
|
280 elif hasattr(other,"value"): return self.value == other.value
|
|
281 else: return self == other
|
167
|
282
|
|
283 def __ne__(self,other):
|
195
|
284 if type(other) == type(3) or type(other) == type(3.0): return self.value != other
|
|
285 elif hasattr(other,"value"): return self.value != other.value
|
|
286 else: return self != other
|
167
|
287
|
|
288 def __gt__(self,other):
|
195
|
289 if type(other) == type(3) or type(other) == type(3.0): return self.value > other
|
|
290 elif hasattr(other,"value"): return self.value > other.value
|
|
291 else: return self > other
|
167
|
292
|
|
293 def __ge__(self,other):
|
195
|
294 if type(other) == type(3) or type(other) == type(3.0): return self.value >= other
|
|
295 elif hasattr(other,"value"): return self.value >= other.value
|
|
296 else: return self >= other
|
167
|
297
|
|
298 def __cmp__(self,other):
|
|
299 # this function included for backwards compatibility
|
180
|
300 # As of 2.1, lists implement the "rich comparison"
|
|
301 # methods overloaded above.
|
195
|
302 if type(other) == type(3) or type(other) == type(3.0): return cmp(self.value, other)
|
|
303 elif hasattr(other,"value"): return cmp(self.value, other.value)
|
|
304 else: return cmp(self,other)
|
167
|
305
|
|
306 def roll(self,min=1):
|
195
|
307 if isinstance(self.sides, basestring) and self.sides.lower() == 'f': self.value = random.randint(-1, 1)
|
|
308 else: self.value = int(random.uniform(min, self.sides+1))
|
167
|
309 self.history = []
|
|
310 self.history.append(self.value)
|
|
311
|
|
312 def extraroll(self):
|
195
|
313 if isinstance(self.sides, basestring) and self.sides.lower() == 'f': result = random.randint(-1, 1)
|
|
314 else: result = int(random.uniform(1,self.sides+1))
|
167
|
315 self.value += result
|
|
316 self.history.append(result)
|
|
317
|
|
318 def lastroll(self):
|
|
319 return self.history[len(self.history)-1]
|
|
320
|
|
321 def set_value(self,value):
|
|
322 self.value = value
|
|
323 self.history = []
|
|
324 self.history.append(self.value)
|
|
325
|
|
326 def modify(self,mod):
|
|
327 self.value += mod
|
|
328 self.history.append(mod)
|
|
329
|
|
330 def gethistory(self):
|
|
331 return self.history[:]
|
|
332
|
|
333 class static_di(di):
|
|
334 def __init__(self,value):
|
|
335 di.__init__(self,value,value)
|
|
336 self.set_value(value)
|
|
337
|
|
338 class DieRollers(object):
|
|
339 _rollers = {}
|
|
340 def __new__(cls):
|
|
341 it = cls.__dict__.get("__it__")
|
195
|
342 if it is not None: return it
|
167
|
343 cls.__it__ = it = object.__new__(cls)
|
|
344 return it
|
|
345
|
|
346 def keys(self):
|
|
347 return self._rollers.keys()
|
|
348
|
|
349 def register(self, roller):
|
|
350 if not self._rollers.has_key(roller.name):
|
|
351 self._rollers[roller.name] = roller
|
|
352
|
|
353 def __getitem__(self, roller_name):
|
|
354 return self._rollers.get(roller_name, None)
|
|
355
|
|
356 def __setitem__(self, *args):
|
|
357 raise AttributeError
|
|
358
|
177
|
359 die_rollers = DieRollers()
|