source: pycodebattler/trunk/pycodebattler/skill.py @ 45

Revision 45, 4.8 KB checked in by atzm, 13 years ago (diff)

add pycodebattler

Line 
1# -*- coding: utf-8 -*-
2# $Id: 33e672ada0beb012199dc62acd15361886a22b31 $
3
4import sys
5import random
6
7try:
8    import cStringIO as _StringIO
9except ImportError:
10    import StringIO as _StringIO
11
12try:
13    set, frozenset
14except NameError:
15    from sets import Set as set, ImmutableSet as frozenset
16
17
18def pformat(skills):
19    order = ['NAME', 'TYPE', 'SP', 'LV']
20    mmap = {
21        'NAME': 'name',
22        'TYPE': 'skilltype',
23        'SP':   'point',
24        'LV':   'level',
25    }
26
27    horiz = [[getattr(s, mmap[n])() for n in order] for s in skills]
28    virt = zip(*horiz)
29
30    sepnum = (len(order) * 3) - 1
31    fmt = ['|']
32    for i, t in enumerate(virt):
33        num = max(len(str(n)) for n in list(t) + [order[i]])
34        sepnum += num
35        if i < 2:
36            fmt.append(' %%-%ds |' % num)
37        else:
38            fmt.append(' %%%ds |' % num)
39
40    fmt = ''.join(fmt + ['\n'])
41    sep = ''.join(['+', '-' * sepnum, '+', '\n'])
42
43    io = _StringIO.StringIO()
44    io.write(sep)
45    io.write(fmt % tuple(order))
46    io.write(sep)
47    for d in horiz:
48        io.write(fmt % tuple(d))
49    io.write(sep)
50    io.flush()
51
52    return io.getvalue()
53
54
55class SkillType:
56    def __init__(self, attacker):
57        self.attacker = attacker
58
59    def range(self):
60        return 0
61
62    def selectable(self, warriors):
63        return []
64
65    def efficiency(self):
66        return 0
67
68
69class HealType(SkillType):
70    def range(self):
71        return 1
72
73    def selectable(self, warriors):
74        return [self.attacker]
75
76    def efficiency(self):
77        base = self.attacker.concentration() * 2 + 10
78        gosa = base / 2
79        return 0 - random.randint(base - gosa, base + gosa)
80
81
82class ResurrectionType(SkillType):
83    def range(self):
84        return 1
85
86    def selectable(self, warriors):
87        loosers = [w for w in warriors if w.is_dead()]
88        try:
89            return [random.choice(loosers)]
90        except IndexError:
91            return []
92
93    def efficiency(self):
94        base = self.attacker.concentration() + 10
95        gosa = base / 2
96        return 0 - random.randint(base - gosa, base + gosa)
97
98
99class SingleAttackType(SkillType):
100    def range(self):
101        return 1
102
103    def selectable(self, warriors):
104        living = [w for w in warriors if not w.is_dead()]
105        living.remove(self.attacker)
106        return living
107
108    def efficiency(self):
109        base = int(self.attacker.concentration() * 2.5)
110        gosa = base / 2
111        return random.randint(base - gosa, base + gosa)
112
113
114class RangeAttackType(SkillType):
115    def range(self):
116        return self.attacker.concentration() // 25 + 1
117
118    def selectable(self, warriors):
119        living = [w for w in warriors if not w.is_dead()]
120        living.remove(self.attacker)
121        return living
122
123    def efficiency(self):
124        base = int(self.attacker.concentration() * 2.3)
125        gosa = base / 2
126        return random.randint(base - gosa, base + gosa)
127
128
129class MultiAttackType(SkillType):
130    def range(self):
131        return sys.maxint
132
133    def selectable(self, warriors):
134        living = [w for w in warriors if not w.is_dead()]
135        living.remove(self.attacker)
136        return living
137
138    def efficiency(self):
139        base = int(self.attacker.concentration() * 1.7)
140        gosa = base / 2
141        return random.randint(base - gosa, base + gosa)
142
143
144class SuicideAttackType(SkillType):
145    def range(self):
146        return sys.maxint
147
148    def selectable(self, warriors):
149        living = [w for w in warriors if not w.is_dead()]
150        living.remove(self.attacker)
151        return living + [self.attacker]
152
153    def efficiency(self):
154        return self.attacker.hitpoint()
155
156
157class Skill:
158    def __init__(self, name, point, skilltype, level=1):
159        self._name = name
160        self._point = point
161        self._skilltype = skilltype
162        self._level = level
163
164    def name(self):
165        return self._name
166
167    def point(self):
168        return self._point
169
170    def skilltype(self):
171        return str(self._skilltype).split('.')[-1]
172
173    def level(self):
174        return self._level
175
176    def range(self, attacker):
177        return self._skilltype(attacker).range()
178
179    def selectable(self, attacker, warriors):
180        return self._skilltype(attacker).selectable(warriors)
181
182    def invoke(self, attacker, targets, warriors):
183        type_ = self._skilltype(attacker)
184
185        if not targets:
186            return []
187        if not warriors:
188            return []
189        if attacker.skillpoint() < self.point():
190            return []
191        if type_.range() * (self._level // 2 + 1) < len(targets):
192            return []
193        if not set(targets).issubset(set(warriors)):
194            return []
195
196        attacker.spend(self.point())
197
198        return [(t, self._invoke_one(type_, t, targets), False, False)
199                for t in targets]
200
201    def _invoke_one(self, type_, t, targets):
202        return t.damage(int(type_.efficiency() * self.level() / len(targets)))
Note: See TracBrowser for help on using the repository browser.