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):
|
|
79 if len(self.data) > 0:
|
|
80 myStr = "[" + str(self.data[0])
|
|
81 for a in self.data[1:]:
|
|
82 myStr += ","
|
|
83 myStr += str(a)
|
|
84 myStr += "] = (" + str(self.sum()) + ")"
|
195
|
85 else: myStr = "[] = (0)"
|
167
|
86 return myStr
|
|
87
|
|
88 def __lt__(self,other):
|
|
89 if type(other) == type(3) or type(other) == type(3.0):
|
|
90 return (self.sum() < other)
|
195
|
91 elif hasattr(other,"sum"): return (self.sum() < other.sum())
|
|
92 else: return UserList.UserList.__lt__(self,other)
|
167
|
93
|
|
94 def __le__(self,other):
|
|
95 if type(other) == type(3) or type(other) == type(3.0):
|
|
96 return (self.sum() <= other)
|
195
|
97 elif hasattr(other,"sum"): return (self.sum() <= other.sum())
|
|
98 else: return UserList.UserList.__le__(self,other)
|
167
|
99
|
|
100 def __eq__(self,other):
|
|
101 if type(other) == type(3) or type(other) == type(3.0):
|
|
102 return (self.sum() == other)
|
195
|
103 elif hasattr(other,"sum"): return (self.sum() == other.sum())
|
|
104 else: return UserList.UserList.__eq__(self,other)
|
167
|
105
|
|
106 def __ne__(self,other):
|
195
|
107 if type(other) == type(3) or type(other) == type(3.0): return (self.sum() != other)
|
|
108 elif hasattr(other,"sum"): return (self.sum() != other.sum())
|
|
109 else: return UserList.UserList.__ne__(self,other)
|
167
|
110
|
|
111 def __gt__(self,other):
|
195
|
112 if type(other) == type(3) or type(other) == type(3.0): return (self.sum() > other)
|
|
113 elif hasattr(other,"sum"): return (self.sum() > other.sum())
|
|
114 else: return UserList.UserList.__gt__(self,other)
|
167
|
115
|
|
116 def __ge__(self,other):
|
195
|
117 if type(other) == type(3) or type(other) == type(3.0): return (self.sum() >= other)
|
|
118 elif hasattr(other,"sum"): return (self.sum() >= other.sum())
|
|
119 else: return UserList.UserList.__ge__(self,other)
|
167
|
120
|
|
121 def __cmp__(self,other):
|
|
122 # this function included for backwards compatibility
|
|
123 # As of 2.1, lists implement the "rich comparison"
|
|
124 # methods overloaded above.
|
195
|
125 if type(other) == type(3) or type(other) == type(3.0): return cmp(self.sum(), other)
|
|
126 elif hasattr(other,"sum"): return cmp(self.sum(), other.sum())
|
|
127 else: return UserList.UserList.__cmp__(self,other)
|
167
|
128
|
|
129 def __rcmp__(self,other):
|
|
130 return self.__cmp__(other)
|
|
131
|
|
132 def __add__(self,other):
|
|
133 mycopy = copy.deepcopy(self)
|
|
134 if type(other) == type(3) or type(other) == type(3.0):
|
|
135 other = [static_di(other)]
|
195
|
136 elif type(other) == type("test"): return self
|
167
|
137 mycopy.extend(other)
|
|
138 return mycopy
|
|
139
|
|
140 def __iadd__(self,other):
|
|
141 return self.__add__(other)
|
|
142
|
|
143 def __radd__(self,other):
|
|
144 mycopy = copy.deepcopy(self)
|
|
145 if type(other) == type(3) or type(other) == type(3.0):
|
|
146 new_die = di(0)
|
|
147 new_die.set_value(other)
|
|
148 other = new_die
|
|
149 mycopy.insert(0,other)
|
|
150 return mycopy
|
|
151
|
|
152 def __int__(self):
|
|
153 return self.sum()
|
|
154
|
|
155 def __sub__(self,other):
|
|
156 mycopy = copy.deepcopy(self)
|
|
157 if type(other) == type(3) or type(other) == type(3.0):
|
|
158 neg_die = static_di(-other)
|
|
159 other = [neg_die]
|
195
|
160 else: other = -other
|
167
|
161 mycopy.extend(other)
|
|
162 return mycopy
|
|
163
|
|
164 def __rsub__(self,other):
|
|
165 mycopy = -copy.deepcopy(self)
|
|
166 if type(other) == type(3) or type(other) == type(3.0):
|
|
167 new_die = di(0)
|
|
168 new_die.set_value(other)
|
|
169 other = new_die
|
|
170 mycopy.insert(0,other)
|
|
171 return mycopy
|
|
172
|
|
173 def __isub__(self,other):
|
|
174 return self.__sub__(other)
|
|
175
|
|
176 def __mul__(self,other):
|
195
|
177 if type(other) == type(3) or type(other) == type(3.0): return self.sum() * other
|
|
178 elif hasattr(other,"sum"): return other.sum() * self.sum()
|
|
179 else: return UserList.UserList.__mul__(self,other)
|
167
|
180
|
|
181 def __rmul__(self,other):
|
|
182 return self.__mul__(other)
|
|
183
|
|
184 def __div__(self,other):
|
195
|
185 if type(other) == type(3) or type(other) == type(3.0): return float(self.sum()) / other
|
|
186 elif hasattr(other,"sum"): return float(self.sum()) / other.sum()
|
|
187 else: return UserList.UserList.__div__(self,other)
|
167
|
188
|
|
189 def __rdiv__(self,other):
|
195
|
190 if type(other) == type(3) or type(other) == type(3.0): return other / float(self.sum())
|
|
191 elif hasattr(other,"sum"): return other.sum() / float(self.sum())
|
|
192 else: return UserList.UserList.__rdiv__(self,other)
|
167
|
193
|
|
194 def __mod__(self,other):
|
195
|
195 if type(other) == type(3) or type(other) == type(3.0): return self.sum()%other
|
|
196 elif hasattr(other,"sum"): return self.sum() % other.sum()
|
|
197 else: return UserList.UserList.__mod__(self,other)
|
167
|
198
|
|
199 def __rmod__(self,other):
|
195
|
200 if type(other) == type(3) or type(other) == type(3.0): return other % self.sum()
|
|
201 elif hasattr(other,"sum"): return other.sum() % self.sum()
|
|
202 else: return UserList.UserList.__rmod__(self,other)
|
167
|
203
|
|
204 def __neg__(self):
|
195
|
205 for i in range(len(self.data)): self.data[i] = -self.data[i]
|
167
|
206 return self
|
|
207
|
|
208 def __pos__(self):
|
195
|
209 for i in range(len(self.data)): self.data[i] = +self.data[i]
|
167
|
210 return self
|
|
211
|
|
212 def __abs__(self):
|
195
|
213 for i in range(len(self.data)): self.data[i] = abs(self.data[i])
|
167
|
214 return self
|
|
215
|
|
216 def __pow__(self,other):
|
195
|
217 if type(other) == type(3) or type(other) == type(3.0): return self.sum() ** other
|
|
218 elif hasattr(other,"sum"): return self.sum() ** other.sum()
|
|
219 else: return UserList.UserList.__pow__(self,other)
|
167
|
220
|
|
221 def __rpow__(self,other):
|
|
222 # We're overloading exponentiation of ints to create "other" number of dice
|
|
223 if other >= 1:
|
|
224 result = self.__class__(self[0].sides)
|
195
|
225 for t in range(other-1): result+=self.__class__(self[0].sides)
|
|
226 else: result = None
|
167
|
227 return result
|
|
228
|
|
229 ### di class to handle actual dice
|
|
230
|
|
231 class di:
|
195
|
232 def __init__(self, sides, min=1):
|
167
|
233 self.sides = sides
|
|
234 self.history = None
|
|
235 self.value = None
|
|
236 self.target = None
|
|
237 self.roll(min)
|
|
238
|
|
239 def __str__(self):
|
195
|
240 if len(self.history) > 1: return str(self.history)
|
|
241 else: return str(self.value)
|
167
|
242
|
|
243 def __neg__(self):
|
|
244 self.value = -self.value
|
195
|
245 for i in range(len(self.history)): self.history[i] = -self.history[i]
|
167
|
246 return self
|
|
247
|
|
248 def __pos__(self):
|
|
249 self.value = +self.value
|
195
|
250 for i in range(len(self.history)): self.history[i] = +self.history[i]
|
167
|
251 return self
|
|
252
|
|
253 def __abs__(self):
|
|
254 self.value = abs(self.value)
|
|
255 for i in range(len(self.history)):
|
|
256 self.history[i] = abs(self.history[i])
|
|
257 return self
|
|
258
|
|
259 def __repr__(self):
|
195
|
260 if len(self.history) > 1: return str(self.history)
|
|
261 else: return str(self.value)
|
167
|
262
|
|
263 def __int__(self):
|
|
264 return self.value
|
|
265
|
|
266 def __lt__(self,other):
|
195
|
267 if type(other) == type(3) or type(other) == type(3.0): return self.value < other
|
|
268 elif hasattr(other,"value"): return self.value < other.value
|
|
269 else: return self < other
|
167
|
270
|
|
271 def __le__(self,other):
|
195
|
272 if type(other) == type(3) or type(other) == type(3.0): return self.value <= other
|
|
273 elif hasattr(other,"value"): return self.value <= other.value
|
|
274 else: return self <= other
|
167
|
275
|
|
276 def __eq__(self,other):
|
195
|
277 if type(other) == type(3) or type(other) == type(3.0): return self.value == other
|
|
278 elif hasattr(other,"value"): return self.value == other.value
|
|
279 else: return self == other
|
167
|
280
|
|
281 def __ne__(self,other):
|
195
|
282 if type(other) == type(3) or type(other) == type(3.0): return self.value != other
|
|
283 elif hasattr(other,"value"): return self.value != other.value
|
|
284 else: return self != other
|
167
|
285
|
|
286 def __gt__(self,other):
|
195
|
287 if type(other) == type(3) or type(other) == type(3.0): return self.value > other
|
|
288 elif hasattr(other,"value"): return self.value > other.value
|
|
289 else: return self > other
|
167
|
290
|
|
291 def __ge__(self,other):
|
195
|
292 if type(other) == type(3) or type(other) == type(3.0): return self.value >= other
|
|
293 elif hasattr(other,"value"): return self.value >= other.value
|
|
294 else: return self >= other
|
167
|
295
|
|
296 def __cmp__(self,other):
|
|
297 # this function included for backwards compatibility
|
180
|
298 # As of 2.1, lists implement the "rich comparison"
|
|
299 # methods overloaded above.
|
195
|
300 if type(other) == type(3) or type(other) == type(3.0): return cmp(self.value, other)
|
|
301 elif hasattr(other,"value"): return cmp(self.value, other.value)
|
|
302 else: return cmp(self,other)
|
167
|
303
|
|
304 def roll(self,min=1):
|
195
|
305 if isinstance(self.sides, basestring) and self.sides.lower() == 'f': self.value = random.randint(-1, 1)
|
|
306 else: self.value = int(random.uniform(min, self.sides+1))
|
167
|
307 self.history = []
|
|
308 self.history.append(self.value)
|
|
309
|
|
310 def extraroll(self):
|
195
|
311 if isinstance(self.sides, basestring) and self.sides.lower() == 'f': result = random.randint(-1, 1)
|
|
312 else: result = int(random.uniform(1,self.sides+1))
|
167
|
313 self.value += result
|
|
314 self.history.append(result)
|
|
315
|
|
316 def lastroll(self):
|
|
317 return self.history[len(self.history)-1]
|
|
318
|
|
319 def set_value(self,value):
|
|
320 self.value = value
|
|
321 self.history = []
|
|
322 self.history.append(self.value)
|
|
323
|
|
324 def modify(self,mod):
|
|
325 self.value += mod
|
|
326 self.history.append(mod)
|
|
327
|
|
328 def gethistory(self):
|
|
329 return self.history[:]
|
|
330
|
|
331 class static_di(di):
|
|
332 def __init__(self,value):
|
|
333 di.__init__(self,value,value)
|
|
334 self.set_value(value)
|
|
335
|
|
336 class DieRollers(object):
|
|
337 _rollers = {}
|
|
338 def __new__(cls):
|
|
339 it = cls.__dict__.get("__it__")
|
195
|
340 if it is not None: return it
|
167
|
341 cls.__it__ = it = object.__new__(cls)
|
|
342 return it
|
|
343
|
|
344 def keys(self):
|
|
345 return self._rollers.keys()
|
|
346
|
|
347 def register(self, roller):
|
|
348 if not self._rollers.has_key(roller.name):
|
|
349 self._rollers[roller.name] = roller
|
|
350
|
|
351 def __getitem__(self, roller_name):
|
|
352 return self._rollers.get(roller_name, None)
|
|
353
|
|
354 def __setitem__(self, *args):
|
|
355 raise AttributeError
|
|
356
|
177
|
357 die_rollers = DieRollers()
|