171
|
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:
|
|
25 # $Id: die.py,v 1.13 2007/03/13 17:53:42 digitalxero Exp $
|
|
26 #
|
|
27 # Description: This class is used to make working with dice easier
|
|
28 #
|
|
29
|
|
30 __version__ = "$Id: die.py,v 1.13 2007/03/13 17:53:42 digitalxero Exp $"
|
|
31
|
|
32
|
|
33 import random
|
|
34 import UserList
|
|
35 import copy
|
|
36 #import string
|
|
37
|
|
38 class die_base(UserList.UserList):
|
|
39 name = None
|
|
40
|
|
41 def __init__(self,source = []):
|
|
42 if isinstance(source, (int, float, basestring)):
|
|
43 s = []
|
|
44 s.append(di(source))
|
|
45 else:
|
|
46 s = source
|
|
47 UserList.UserList.__init__(self,s)
|
|
48
|
|
49
|
|
50 def sum(self):
|
|
51 s = 0
|
|
52 for a in self.data:
|
|
53 s += int(a)
|
|
54 return s
|
|
55
|
|
56 def __lshift__(self,other):
|
|
57 if type(other) == type(3) or type(other) == type(3.0):
|
|
58 o = other
|
|
59 elif hasattr(other,"sum"):
|
|
60 o = other.sum()
|
|
61 else:
|
|
62 return None
|
|
63
|
|
64 result = []
|
|
65 for die in self:
|
|
66 if die < o:
|
|
67 result.append(die)
|
|
68 return self.__class__(result)
|
|
69
|
|
70 def __rshift__(self,other):
|
|
71
|
|
72 if type(other) == type(3) or type(other) == type(3.0):
|
|
73 o = other
|
|
74 elif hasattr(other,"sum"):
|
|
75 o = other.sum()
|
|
76 else:
|
|
77 return None
|
|
78
|
|
79 result = []
|
|
80 for die in self:
|
|
81 if die > o:
|
|
82 result.append(die)
|
|
83 return self.__class__(result)
|
|
84
|
|
85 def __rlshift__(self,other):
|
|
86 return self.__rshift__(other)
|
|
87
|
|
88 def __rrshift__(self,other):
|
|
89 return self.__lshift__(other)
|
|
90
|
|
91
|
|
92 def __str__(self):
|
|
93 if len(self.data) > 0:
|
|
94 myStr = "[" + str(self.data[0])
|
|
95 for a in self.data[1:]:
|
|
96 myStr += ","
|
|
97 myStr += str(a)
|
|
98 myStr += "] = (" + str(self.sum()) + ")"
|
|
99 else:
|
|
100 myStr = "[] = (0)"
|
|
101 return myStr
|
|
102
|
|
103 def __lt__(self,other):
|
|
104 if type(other) == type(3) or type(other) == type(3.0):
|
|
105 return (self.sum() < other)
|
|
106 elif hasattr(other,"sum"):
|
|
107 return (self.sum() < other.sum())
|
|
108 else:
|
|
109 return UserList.UserList.__lt__(self,other)
|
|
110
|
|
111 def __le__(self,other):
|
|
112 if type(other) == type(3) or type(other) == type(3.0):
|
|
113 return (self.sum() <= other)
|
|
114 elif hasattr(other,"sum"):
|
|
115 return (self.sum() <= other.sum())
|
|
116 else:
|
|
117 return UserList.UserList.__le__(self,other)
|
|
118
|
|
119 def __eq__(self,other):
|
|
120 if type(other) == type(3) or type(other) == type(3.0):
|
|
121 return (self.sum() == other)
|
|
122 elif hasattr(other,"sum"):
|
|
123 return (self.sum() == other.sum())
|
|
124 else:
|
|
125 return UserList.UserList.__eq__(self,other)
|
|
126
|
|
127 def __ne__(self,other):
|
|
128 if type(other) == type(3) or type(other) == type(3.0):
|
|
129 return (self.sum() != other)
|
|
130 elif hasattr(other,"sum"):
|
|
131 return (self.sum() != other.sum())
|
|
132 else:
|
|
133 return UserList.UserList.__ne__(self,other)
|
|
134
|
|
135 def __gt__(self,other):
|
|
136 if type(other) == type(3) or type(other) == type(3.0):
|
|
137 return (self.sum() > other)
|
|
138 elif hasattr(other,"sum"):
|
|
139 return (self.sum() > other.sum())
|
|
140 else:
|
|
141 return UserList.UserList.__gt__(self,other)
|
|
142
|
|
143 def __ge__(self,other):
|
|
144 if type(other) == type(3) or type(other) == type(3.0):
|
|
145 return (self.sum() >= other)
|
|
146 elif hasattr(other,"sum"):
|
|
147 return (self.sum() >= other.sum())
|
|
148 else:
|
|
149 return UserList.UserList.__ge__(self,other)
|
|
150
|
|
151 def __cmp__(self,other):
|
|
152 # this function included for backwards compatibility
|
|
153 # As of 2.1, lists implement the "rich comparison"
|
|
154 # methods overloaded above.
|
|
155 if type(other) == type(3) or type(other) == type(3.0):
|
|
156 return cmp(self.sum(), other)
|
|
157 elif hasattr(other,"sum"):
|
|
158 return cmp(self.sum(), other.sum())
|
|
159 else:
|
|
160 return UserList.UserList.__cmp__(self,other)
|
|
161
|
|
162
|
|
163 def __rcmp__(self,other):
|
|
164 return self.__cmp__(other)
|
|
165
|
|
166 def __add__(self,other):
|
|
167 mycopy = copy.deepcopy(self)
|
|
168 if type(other) == type(3) or type(other) == type(3.0):
|
|
169 #if other < 0:
|
|
170 # return self.__sub__(-other)
|
|
171 #other = [di(other,other)]
|
|
172 other = [static_di(other)]
|
|
173 #return self.sum() + other
|
|
174
|
|
175 elif type(other) == type("test"):
|
|
176 return self
|
|
177 mycopy.extend(other)
|
|
178 #result = UserList.UserList.__add__(mycopy,other)
|
|
179 return mycopy
|
|
180
|
|
181 def __iadd__(self,other):
|
|
182 return self.__add__(other)
|
|
183
|
|
184 def __radd__(self,other):
|
|
185 mycopy = copy.deepcopy(self)
|
|
186 if type(other) == type(3) or type(other) == type(3.0):
|
|
187 new_die = di(0)
|
|
188 new_die.set_value(other)
|
|
189 other = new_die
|
|
190 mycopy.insert(0,other)
|
|
191 return mycopy
|
|
192
|
|
193 def __int__(self):
|
|
194 return self.sum()
|
|
195
|
|
196 def __sub__(self,other):
|
|
197 mycopy = copy.deepcopy(self)
|
|
198 if type(other) == type(3) or type(other) == type(3.0):
|
|
199 neg_die = static_di(-other)
|
|
200 #neg_die.set_value(-other)
|
|
201 other = [neg_die]
|
|
202 #return self.sum() - other
|
|
203 else:
|
|
204 other = -other
|
|
205 mycopy.extend(other)
|
|
206 return mycopy
|
|
207
|
|
208 def __rsub__(self,other):
|
|
209 mycopy = -copy.deepcopy(self)
|
|
210 #print type(other)
|
|
211 if type(other) == type(3) or type(other) == type(3.0):
|
|
212 new_die = di(0)
|
|
213 new_die.set_value(other)
|
|
214 other = new_die
|
|
215 mycopy.insert(0,other)
|
|
216 return mycopy
|
|
217
|
|
218 def __isub__(self,other):
|
|
219 return self.__sub__(other)
|
|
220
|
|
221 def __mul__(self,other):
|
|
222 if type(other) == type(3) or type(other) == type(3.0):
|
|
223 return self.sum() * other
|
|
224 elif hasattr(other,"sum"):
|
|
225 return other.sum() * self.sum()
|
|
226 else:
|
|
227 return UserList.UserList.__mul__(self,other)
|
|
228
|
|
229 def __rmul__(self,other):
|
|
230 return self.__mul__(other)
|
|
231
|
|
232 def __div__(self,other):
|
|
233 if type(other) == type(3) or type(other) == type(3.0):
|
|
234 return float(self.sum()) / other
|
|
235 elif hasattr(other,"sum"):
|
|
236 return float(self.sum()) / other.sum()
|
|
237 else:
|
|
238 return UserList.UserList.__div__(self,other)
|
|
239
|
|
240 def __rdiv__(self,other):
|
|
241 if type(other) == type(3) or type(other) == type(3.0):
|
|
242 return other / float(self.sum())
|
|
243 elif hasattr(other,"sum"):
|
|
244 return other.sum() / float(self.sum())
|
|
245 else:
|
|
246 return UserList.UserList.__rdiv__(self,other)
|
|
247
|
|
248 def __mod__(self,other):
|
|
249 if type(other) == type(3) or type(other) == type(3.0):
|
|
250 return self.sum()%other
|
|
251 elif hasattr(other,"sum"):
|
|
252 return self.sum() % other.sum()
|
|
253 else:
|
|
254 return UserList.UserList.__mod__(self,other)
|
|
255
|
|
256 def __rmod__(self,other):
|
|
257 if type(other) == type(3) or type(other) == type(3.0):
|
|
258 return other % self.sum()
|
|
259 elif hasattr(other,"sum"):
|
|
260 return other.sum() % self.sum()
|
|
261 else:
|
|
262 return UserList.UserList.__rmod__(self,other)
|
|
263
|
|
264 def __neg__(self):
|
|
265 for i in range(len(self.data)):
|
|
266 self.data[i] = -self.data[i]
|
|
267 return self
|
|
268
|
|
269 def __pos__(self):
|
|
270 for i in range(len(self.data)):
|
|
271 self.data[i] = +self.data[i]
|
|
272 return self
|
|
273
|
|
274 def __abs__(self):
|
|
275 for i in range(len(self.data)):
|
|
276 self.data[i] = abs(self.data[i])
|
|
277 return self
|
|
278 #return abs(self.sum())
|
|
279
|
|
280 def __pow__(self,other):
|
|
281 if type(other) == type(3) or type(other) == type(3.0):
|
|
282 return self.sum() ** other
|
|
283 elif hasattr(other,"sum"):
|
|
284 return self.sum() ** other.sum()
|
|
285 else:
|
|
286 return UserList.UserList.__pow__(self,other)
|
|
287
|
|
288
|
|
289 def __rpow__(self,other):
|
|
290 # We're overloading exponentiation of ints to create "other" number of dice
|
|
291
|
|
292 if other >= 1:
|
|
293 result = self.__class__(self[0].sides)
|
|
294 for t in range(other-1):
|
|
295 result+=self.__class__(self[0].sides)
|
|
296 else:
|
|
297 result = None
|
|
298
|
|
299 return result
|
|
300
|
|
301 ### di class to handle actual dice
|
|
302
|
|
303 class di:
|
|
304 def __init__(self,sides,min=1):
|
|
305 self.sides = sides
|
|
306 self.history = None
|
|
307 self.value = None
|
|
308 self.target = None
|
|
309 self.roll(min)
|
|
310
|
|
311 def __str__(self):
|
|
312 if len(self.history) > 1:
|
|
313 return str(self.history)
|
|
314 else:
|
|
315 return str(self.value)
|
|
316
|
|
317 def __neg__(self):
|
|
318 self.value = -self.value
|
|
319 for i in range(len(self.history)):
|
|
320 self.history[i] = -self.history[i]
|
|
321 return self
|
|
322
|
|
323 def __pos__(self):
|
|
324 self.value = +self.value
|
|
325 for i in range(len(self.history)):
|
|
326 self.history[i] = +self.history[i]
|
|
327 return self
|
|
328
|
|
329 def __abs__(self):
|
|
330 self.value = abs(self.value)
|
|
331 for i in range(len(self.history)):
|
|
332 self.history[i] = abs(self.history[i])
|
|
333 return self
|
|
334
|
|
335 def __repr__(self):
|
|
336 if len(self.history) > 1:
|
|
337 return str(self.history)
|
|
338 else:
|
|
339 return str(self.value)
|
|
340
|
|
341 def __int__(self):
|
|
342 return self.value
|
|
343
|
|
344
|
|
345 def __lt__(self,other):
|
|
346 if type(other) == type(3) or type(other) == type(3.0):
|
|
347 return self.value < other
|
|
348 elif hasattr(other,"value"):
|
|
349 return self.value < other.value
|
|
350 else:
|
|
351 return self < other
|
|
352
|
|
353 def __le__(self,other):
|
|
354 if type(other) == type(3) or type(other) == type(3.0):
|
|
355 return self.value <= other
|
|
356 elif hasattr(other,"value"):
|
|
357 return self.value <= other.value
|
|
358 else:
|
|
359 return self <= other
|
|
360
|
|
361 def __eq__(self,other):
|
|
362 if type(other) == type(3) or type(other) == type(3.0):
|
|
363 return self.value == other
|
|
364 elif hasattr(other,"value"):
|
|
365 return self.value == other.value
|
|
366 else:
|
|
367 return self == other
|
|
368
|
|
369 def __ne__(self,other):
|
|
370 if type(other) == type(3) or type(other) == type(3.0):
|
|
371 return self.value != other
|
|
372 elif hasattr(other,"value"):
|
|
373 return self.value != other.value
|
|
374 else:
|
|
375 return self != other
|
|
376
|
|
377 def __gt__(self,other):
|
|
378 if type(other) == type(3) or type(other) == type(3.0):
|
|
379 return self.value > other
|
|
380 elif hasattr(other,"value"):
|
|
381 return self.value > other.value
|
|
382 else:
|
|
383 return self > other
|
|
384
|
|
385 def __ge__(self,other):
|
|
386 if type(other) == type(3) or type(other) == type(3.0):
|
|
387 return self.value >= other
|
|
388 elif hasattr(other,"value"):
|
|
389 return self.value >= other.value
|
|
390 else:
|
|
391 return self >= other
|
|
392
|
|
393 def __cmp__(self,other):
|
|
394 # this function included for backwards compatibility
|
183
|
395 # As of 2.1, lists implement the "rich comparison"
|
|
396 # methods overloaded above.
|
171
|
397 if type(other) == type(3) or type(other) == type(3.0):
|
|
398 return cmp(self.value, other)
|
|
399 elif hasattr(other,"value"):
|
|
400 return cmp(self.value, other.value)
|
|
401 else:
|
|
402 return cmp(self,other)
|
|
403
|
|
404 def roll(self,min=1):
|
|
405 if isinstance(self.sides, basestring) and self.sides.lower() == 'f':
|
|
406 self.value = random.randint(-1, 1)
|
|
407 else:
|
|
408 #self.value = random.randint(min, self.sides)
|
|
409 self.value = int(random.uniform(min, self.sides+1))
|
|
410 self.history = []
|
|
411 self.history.append(self.value)
|
|
412
|
|
413 def extraroll(self):
|
|
414 if isinstance(self.sides, basestring) and self.sides.lower() == 'f':
|
|
415 result = random.randint(-1, 1)
|
|
416 else:
|
|
417 #result = random.randint(1, self.sides)
|
|
418 result = int(random.uniform(1,self.sides+1))
|
|
419
|
|
420 self.value += result
|
|
421 self.history.append(result)
|
|
422
|
|
423 def lastroll(self):
|
|
424 return self.history[len(self.history)-1]
|
|
425
|
|
426 def set_value(self,value):
|
|
427 self.value = value
|
|
428 self.history = []
|
|
429 self.history.append(self.value)
|
|
430
|
|
431 def modify(self,mod):
|
|
432 self.value += mod
|
|
433 self.history.append(mod)
|
|
434
|
|
435 def gethistory(self):
|
|
436 return self.history[:]
|
|
437
|
|
438 class static_di(di):
|
|
439 def __init__(self,value):
|
|
440 di.__init__(self,value,value)
|
|
441 self.set_value(value)
|
|
442
|
|
443 class DieRollers(object):
|
|
444 _rollers = {}
|
|
445 def __new__(cls):
|
|
446 it = cls.__dict__.get("__it__")
|
|
447 if it is not None:
|
|
448 return it
|
|
449 cls.__it__ = it = object.__new__(cls)
|
|
450 return it
|
|
451
|
|
452 def keys(self):
|
|
453 return self._rollers.keys()
|
|
454
|
|
455 def register(self, roller):
|
|
456 if not self._rollers.has_key(roller.name):
|
|
457 self._rollers[roller.name] = roller
|
|
458
|
|
459 def __getitem__(self, roller_name):
|
|
460 return self._rollers.get(roller_name, None)
|
|
461
|
|
462 def __setitem__(self, *args):
|
|
463 raise AttributeError
|
|
464
|
183
|
465 die_rollers = DieRollers()
|