comparison orpg/dieroller/die.py @ 0:4385a7d0efd1 grumpy-goblin

Deleted and repushed it with the 'grumpy-goblin' branch. I forgot a y
author sirebral
date Tue, 14 Jul 2009 16:41:58 -0500
parents
children 449a8900f9ac
comparison
equal deleted inserted replaced
-1:000000000000 0:4385a7d0efd1
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
40 def __init__(self,source = []):
41 if isinstance(source, (int, float, basestring)):
42 s = []
43 s.append(di(source))
44 else:
45 s = source
46 UserList.UserList.__init__(self,s)
47
48
49 def sum(self):
50 s = 0
51 for a in self.data:
52 s += int(a)
53 return s
54
55 def __lshift__(self,other):
56 if type(other) == type(3) or type(other) == type(3.0):
57 o = other
58 elif hasattr(other,"sum"):
59 o = other.sum()
60 else:
61 return None
62
63 result = []
64 for die in self:
65 if die < o:
66 result.append(die)
67 return self.__class__(result)
68
69 def __rshift__(self,other):
70
71 if type(other) == type(3) or type(other) == type(3.0):
72 o = other
73 elif hasattr(other,"sum"):
74 o = other.sum()
75 else:
76 return None
77
78 result = []
79 for die in self:
80 if die > o:
81 result.append(die)
82 return self.__class__(result)
83
84 def __rlshift__(self,other):
85 return self.__rshift__(other)
86
87 def __rrshift__(self,other):
88 return self.__lshift__(other)
89
90
91 def __str__(self):
92 if len(self.data) > 0:
93 myStr = "[" + str(self.data[0])
94 for a in self.data[1:]:
95 myStr += ","
96 myStr += str(a)
97 myStr += "] = (" + str(self.sum()) + ")"
98 else:
99 myStr = "[] = (0)"
100 return myStr
101
102 def __lt__(self,other):
103 if type(other) == type(3) or type(other) == type(3.0):
104 return (self.sum() < other)
105 elif hasattr(other,"sum"):
106 return (self.sum() < other.sum())
107 else:
108 return UserList.UserList.__lt__(self,other)
109
110 def __le__(self,other):
111 if type(other) == type(3) or type(other) == type(3.0):
112 return (self.sum() <= other)
113 elif hasattr(other,"sum"):
114 return (self.sum() <= other.sum())
115 else:
116 return UserList.UserList.__le__(self,other)
117
118 def __eq__(self,other):
119 if type(other) == type(3) or type(other) == type(3.0):
120 return (self.sum() == other)
121 elif hasattr(other,"sum"):
122 return (self.sum() == other.sum())
123 else:
124 return UserList.UserList.__eq__(self,other)
125
126 def __ne__(self,other):
127 if type(other) == type(3) or type(other) == type(3.0):
128 return (self.sum() != other)
129 elif hasattr(other,"sum"):
130 return (self.sum() != other.sum())
131 else:
132 return UserList.UserList.__ne__(self,other)
133
134 def __gt__(self,other):
135 if type(other) == type(3) or type(other) == type(3.0):
136 return (self.sum() > other)
137 elif hasattr(other,"sum"):
138 return (self.sum() > other.sum())
139 else:
140 return UserList.UserList.__gt__(self,other)
141
142 def __ge__(self,other):
143 if type(other) == type(3) or type(other) == type(3.0):
144 return (self.sum() >= other)
145 elif hasattr(other,"sum"):
146 return (self.sum() >= other.sum())
147 else:
148 return UserList.UserList.__ge__(self,other)
149
150 def __cmp__(self,other):
151 # this function included for backwards compatibility
152 # As of 2.1, lists implement the "rich comparison"
153 # methods overloaded above.
154 if type(other) == type(3) or type(other) == type(3.0):
155 return cmp(self.sum(), other)
156 elif hasattr(other,"sum"):
157 return cmp(self.sum(), other.sum())
158 else:
159 return UserList.UserList.__cmp__(self,other)
160
161
162 def __rcmp__(self,other):
163 return self.__cmp__(other)
164
165 def __add__(self,other):
166 mycopy = copy.deepcopy(self)
167 if type(other) == type(3) or type(other) == type(3.0):
168 #if other < 0:
169 # return self.__sub__(-other)
170 #other = [di(other,other)]
171 other = [static_di(other)]
172 #return self.sum() + other
173
174 elif type(other) == type("test"):
175 return self
176 mycopy.extend(other)
177 #result = UserList.UserList.__add__(mycopy,other)
178 return mycopy
179
180 def __iadd__(self,other):
181 return self.__add__(other)
182
183 def __radd__(self,other):
184 mycopy = copy.deepcopy(self)
185 if type(other) == type(3) or type(other) == type(3.0):
186 new_die = di(0)
187 new_die.set_value(other)
188 other = new_die
189 mycopy.insert(0,other)
190 return mycopy
191
192 def __int__(self):
193 return self.sum()
194
195 def __sub__(self,other):
196 mycopy = copy.deepcopy(self)
197 if type(other) == type(3) or type(other) == type(3.0):
198 neg_die = static_di(-other)
199 #neg_die.set_value(-other)
200 other = [neg_die]
201 #return self.sum() - other
202 else:
203 other = -other
204 mycopy.extend(other)
205 return mycopy
206
207 def __rsub__(self,other):
208 mycopy = -copy.deepcopy(self)
209 #print type(other)
210 if type(other) == type(3) or type(other) == type(3.0):
211 new_die = di(0)
212 new_die.set_value(other)
213 other = new_die
214 mycopy.insert(0,other)
215 return mycopy
216
217 def __isub__(self,other):
218 return self.__sub__(other)
219
220 def __mul__(self,other):
221 if type(other) == type(3) or type(other) == type(3.0):
222 return self.sum() * other
223 elif hasattr(other,"sum"):
224 return other.sum() * self.sum()
225 else:
226 return UserList.UserList.__mul__(self,other)
227
228 def __rmul__(self,other):
229 return self.__mul__(other)
230
231 def __div__(self,other):
232 if type(other) == type(3) or type(other) == type(3.0):
233 return float(self.sum()) / other
234 elif hasattr(other,"sum"):
235 return float(self.sum()) / other.sum()
236 else:
237 return UserList.UserList.__div__(self,other)
238
239 def __rdiv__(self,other):
240 if type(other) == type(3) or type(other) == type(3.0):
241 return other / float(self.sum())
242 elif hasattr(other,"sum"):
243 return other.sum() / float(self.sum())
244 else:
245 return UserList.UserList.__rdiv__(self,other)
246
247 def __mod__(self,other):
248 if type(other) == type(3) or type(other) == type(3.0):
249 return self.sum()%other
250 elif hasattr(other,"sum"):
251 return self.sum() % other.sum()
252 else:
253 return UserList.UserList.__mod__(self,other)
254
255 def __rmod__(self,other):
256 if type(other) == type(3) or type(other) == type(3.0):
257 return other % self.sum()
258 elif hasattr(other,"sum"):
259 return other.sum() % self.sum()
260 else:
261 return UserList.UserList.__rmod__(self,other)
262
263 def __neg__(self):
264 for i in range(len(self.data)):
265 self.data[i] = -self.data[i]
266 return self
267
268 def __pos__(self):
269 for i in range(len(self.data)):
270 self.data[i] = +self.data[i]
271 return self
272
273 def __abs__(self):
274 for i in range(len(self.data)):
275 self.data[i] = abs(self.data[i])
276 return self
277 #return abs(self.sum())
278
279 def __pow__(self,other):
280 if type(other) == type(3) or type(other) == type(3.0):
281 return self.sum() ** other
282 elif hasattr(other,"sum"):
283 return self.sum() ** other.sum()
284 else:
285 return UserList.UserList.__pow__(self,other)
286
287
288 def __rpow__(self,other):
289 # We're overloading exponentiation of ints to create "other" number of dice
290
291 if other >= 1:
292 result = self.__class__(self[0].sides)
293 for t in range(other-1):
294 result+=self.__class__(self[0].sides)
295 else:
296 result = None
297
298 return result
299
300 ### di class to handle actual dice
301
302 class di:
303 def __init__(self,sides,min=1):
304 self.sides = sides
305 self.history = None
306 self.value = None
307 self.target = None
308 self.roll(min)
309
310 def __str__(self):
311 if len(self.history) > 1:
312 return str(self.history)
313 else:
314 return str(self.value)
315
316 def __neg__(self):
317 self.value = -self.value
318 for i in range(len(self.history)):
319 self.history[i] = -self.history[i]
320 return self
321
322 def __pos__(self):
323 self.value = +self.value
324 for i in range(len(self.history)):
325 self.history[i] = +self.history[i]
326 return self
327
328 def __abs__(self):
329 self.value = abs(self.value)
330 for i in range(len(self.history)):
331 self.history[i] = abs(self.history[i])
332 return self
333
334 def __repr__(self):
335 if len(self.history) > 1:
336 return str(self.history)
337 else:
338 return str(self.value)
339
340 def __int__(self):
341 return self.value
342
343
344 def __lt__(self,other):
345 if type(other) == type(3) or type(other) == type(3.0):
346 return self.value < other
347 elif hasattr(other,"value"):
348 return self.value < other.value
349 else:
350 return self < other
351
352 def __le__(self,other):
353 if type(other) == type(3) or type(other) == type(3.0):
354 return self.value <= other
355 elif hasattr(other,"value"):
356 return self.value <= other.value
357 else:
358 return self <= other
359
360 def __eq__(self,other):
361 if type(other) == type(3) or type(other) == type(3.0):
362 return self.value == other
363 elif hasattr(other,"value"):
364 return self.value == other.value
365 else:
366 return self == other
367
368 def __ne__(self,other):
369 if type(other) == type(3) or type(other) == type(3.0):
370 return self.value != other
371 elif hasattr(other,"value"):
372 return self.value != other.value
373 else:
374 return self != other
375
376 def __gt__(self,other):
377 if type(other) == type(3) or type(other) == type(3.0):
378 return self.value > other
379 elif hasattr(other,"value"):
380 return self.value > other.value
381 else:
382 return self > other
383
384 def __ge__(self,other):
385 if type(other) == type(3) or type(other) == type(3.0):
386 return self.value >= other
387 elif hasattr(other,"value"):
388 return self.value >= other.value
389 else:
390 return self >= other
391
392 def __cmp__(self,other):
393 # this function included for backwards compatibility
394 # As of 2.1, lists implement the "rich comparison"
395 # methods overloaded above.
396 if type(other) == type(3) or type(other) == type(3.0):
397 return cmp(self.value, other)
398 elif hasattr(other,"value"):
399 return cmp(self.value, other.value)
400 else:
401 return cmp(self,other)
402
403 def roll(self,min=1):
404 if isinstance(self.sides, basestring) and self.sides.lower() == 'f':
405 self.value = random.randint(-1, 1)
406 else:
407 #self.value = random.randint(min, self.sides)
408 self.value = int(random.uniform(min, self.sides+1))
409 self.history = []
410 self.history.append(self.value)
411
412 def extraroll(self):
413 if isinstance(self.sides, basestring) and self.sides.lower() == 'f':
414 result = random.randint(-1, 1)
415 else:
416 #result = random.randint(1, self.sides)
417 result = int(random.uniform(1,self.sides+1))
418
419 self.value += result
420 self.history.append(result)
421
422 def lastroll(self):
423 return self.history[len(self.history)-1]
424
425 def set_value(self,value):
426 self.value = value
427 self.history = []
428 self.history.append(self.value)
429
430 def modify(self,mod):
431 self.value += mod
432 self.history.append(mod)
433
434 def gethistory(self):
435 return self.history[:]
436
437 class static_di(di):
438 def __init__(self,value):
439 di.__init__(self,value,value)
440 self.set_value(value)
441
442
443 class std(die_base):
444 def __init__(self,source=[]):
445 die_base.__init__(self,source)
446
447 # Examples of adding member functions through inheritance.
448
449 def ascending(self):
450 result = self[:]
451 result.sort()
452 return result
453
454 def descending(self):
455 result = self[:]
456 result.sort()
457 result.reverse()
458 return result
459
460 def takeHighest(self,num_dice):
461 return self.descending()[:num_dice]
462
463 def takeLowest(self,num_dice):
464 return self.ascending()[:num_dice]
465
466 def extra(self,num):
467 for i in range(len(self.data)):
468 if self.data[i].lastroll() >= num:
469 self.data[i].extraroll()
470 return self
471
472 def open(self,num):
473 if num <= 1:
474 self
475 done = 1
476 for i in range(len(self.data)):
477 if self.data[i].lastroll() >= num:
478 self.data[i].extraroll()
479 done = 0
480 if done:
481 return self
482 else:
483 return self.open(num)
484
485 def minroll(self,min):
486 for i in range(len(self.data)):
487 if self.data[i].lastroll() < min:
488 self.data[i].roll(min)
489 return self
490
491 def each(self,mod):
492 mod = int(mod)
493 for i in range(len(self.data)):
494 self.data[i].modify(mod)
495 return self
496
497
498 def vs(self, target):
499 for dn in self.data:
500 dn.target = target
501 return self
502
503
504 ## If we are testing against a saving throw, we check for
505 ## greater than or equal to against the target value and
506 ## we only return the number of successful saves. A negative
507 ## value will never be generated.
508 def sum(self):
509 retValue = 0
510 for dn in self.data:
511 setValue = reduce( lambda x, y : int(x)+int(y), dn.history )
512 if dn.target:
513 if setValue >= dn.target:
514 retValue += 1
515
516 else:
517 retValue += setValue
518
519 return retValue