git.fiddlerwoaroof.com
Browse code

refactoring combat.py

edwlan authored on 29/07/2013 03:58:09
Showing 1 changed files
... ...
@@ -1,6 +1,9 @@
1 1
 from . import dice
2
-from .dice import MULT,ADD
3
-from . import type_dict
2
+
3
+from .combat_parts import races
4
+from .combat_parts import equipment
5
+from .combat_parts import skills
6
+from .combat_parts import constants as const
4 7
 
5 8
 import collections
6 9
 
... ...
@@ -10,261 +13,26 @@ class Attributes(object):
10 13
 		self.int = intellect
11 14
 		self.dex = dexterity
12 15
 		self.spt = spirit
13
-		self.state = HEALTHY
14
-
15
-def health_mod(func):
16
-	def _inner(self):
17
-		mod = 0
18
-		if self.attr.state >= WOUNDED:
19
-			mod = -3
20
-		result = func(self)
21
-		result += mod
22
-		return result
23
-	return _inner
24
-
25
-
26
-
27
-class Skills(object):
28
-	def __init__(self, attr):
29
-		self.skills = {
30
-			'agility','craft','fighting','knowledge',
31
-			'perception','persuasion','shooting','speed',
32
-			'stealth','toughness'
33
-		}
34
-		self.attr = attr
35
-		self.training = Trainer(self)
36
-		self.train = self.training.select
37
-
38
-	def check(self, skill, dieroll):
39
-		dieroll.dice = dice.DieJar().d20
40
-		roll = dieroll.roll()
41
-		if roll == 1:
42
-			result = False
43
-		if roll == 20:
44
-			result = True
45
-		else:
46
-			result = roll < getattr(self, skill)
47
-		return result, roll-result # (passes, difference)
48
-
49
-	@property
50
-	@health_mod
51
-	def agility(self):
52
-		return (self.attr.dex * 2) + self.training.agility
53
-	@property
54
-	@health_mod
55
-	def craft(self):
56
-		return self.attr.dex + self.attr.int + self.training.craft
57
-	@property
58
-	@health_mod
59
-	def fighting(self):
60
-		return self.attr.str + self.attr.int + self.training.fighting
61
-	@property
62
-	@health_mod
63
-	def knowledge(self):
64
-		return self.attr.int * 2 + self.training.knowledge
65
-	@property
66
-	@health_mod
67
-	def perception(self):
68
-		return self.attr.int + attr.spt + self.training.perception
69
-	@property
70
-	@health_mod
71
-	def persuasion(self):
72
-		return self.attr.spt * 2 + self.training.persuasion
73
-	@property
74
-	@health_mod
75
-	def shooting(self):
76
-		return self.attr.dex + self.attr.int + self.training.shooting
77
-	@property
78
-	@health_mod
79
-	def speed(self):
80
-		return self.attr.str + self.attr.dex + self.training.speed
81
-	@property
82
-	@health_mod
83
-	def stealth(self):
84
-		return self.attr.dex + self.attr.spt + self.training.stealth
85
-	@property
86
-	@health_mod
87
-	def toughness(self):
88
-		return self.attr.str + self.attr.spt + self.training.toughness
89
-
90
-class Trainer(object):
91
-	mods = dict(
92
-		untrained=-1,
93
-		familiar=0,
94
-		trained=1,
95
-		experienced=2,
96
-		mastered=3
97
-	)
98
-
99
-	def __init__(self, skills):
100
-		self.skills = skills
101
-		self.training = collections.defaultdict(lambda: -1)
102
-		self.points = 500
103
-		self.training_cost = 100
104
-
105
-	def select(self, skill, degree):
106
-		if hasattr(degree, 'upper'):
107
-			degree = self.mods.get(degree, 0)
108
-		if self.points >= self.training_cost and degree in self.mods.values():
109
-			self.training[skill] = degree
110
-			self.points -= self.training_cost
111
-
112
-	def __getattr__(self, key):
113
-		skills = object.__getattribute__(self, 'skills')
114
-		if key in self.skills.skills:
115
-			return self.training[key]
116
-		else:
117
-			raise
118
-	def __setattr__(self, key, value):
119
-		if hasattr(self, 'skills') and key in self.skills.skills:
120
-			if -1 <= value <= 3:
121
-				self.training[key] = int(round(value))
122
-			else:
123
-				raise AttributeError(
124
-					'cannot set training of %s to %d, (out of range [-1,3])' % (key, value)
125
-				)
126
-		else:
127
-			object.__setattr__(self, key, value)
128
-
129
-
130
-class Equipment(object): pass
131
-class Weapon(Equipment): pass
132
-class Armor(Equipment): pass
133
-
134
-
135
-class Slot(object):
136
-	def __init__(self, name, type):
137
-		self.name = name
138
-		self.attr = 'slotted_%s' % name
139
-		self.type = type
140
-
141
-	def __get__(self, instance, owner):
142
-		return self.getitem(instance)
143
-	def __set__(self, instance, value):
144
-		self.setitem(instance, value)
145
-
146
-	def setitem(self, instance, value):
147
-		if isinstance(value, self.type):
148
-			setattr(instance, 'slotted_%s' % self.name, value)
149
-		else:
150
-			raise ValueError(
151
-				'Can\'t use an object of type %s in a slot of type %s' % (type(value), self.type)
152
-			)
153
-
154
-
155
-	def getitem(self, instance):
156
-		return getattr(instance, self.attr, None)
157
-
158
-	def filled(self, instance):
159
-		return self.getitem(instance) is not None
160
-
161
-	@classmethod
162
-	def add_slot(cls, name, type):
163
-		def _inner(to_cls):
164
-			inst = cls(name, type)
165
-			setattr(to_cls, name, inst)
166
-			if not hasattr(to_cls, 'equipment_slots'):
167
-				to_cls.equipment_slots = Slots((name,inst))
168
-			else:
169
-				to_cls.equipment_slots[name] = inst
170
-			return to_cls
171
-		return _inner
16
+		self.state = const.HEALTHY
172 17
 
173 18
 
174
-class Slots(collections.MutableMapping):
175
-	def __init__(self, *args, **kw):
176
-		self.slots = dict(args)
177
-		self.slots.update(kw)
178
-		self.slots_by_type = type_dict.TypeDict(__default=[])
179
-		for k in self.slots:
180
-			slot = self.slots[k]
181
-			self.slots_by_type[slot.type].append(slot)
182
-
183
-	def __getitem__(self, key):
184
-		return self.slots[key]
185
-	def __setitem__(self, k, v):
186
-		self.slots[k] = v
187
-	def __delitem__(self, key):
188
-		del self.slots[key]
189
-
190
-	def __iter__(self):
191
-		return iter(self.slots)
192
-	def __len__(self):
193
-		return len(self.slots)
194
-
195
-	def slots_of_type(self, slot_type):
196
-		return self.slots_by_type[slot_type]
197
-
198
-class Race(object):
199
-	registry = {}
200
-	@classmethod
201
-	def register(cls, new):
202
-		cls.registry[new.__name__.lower()] = new
203
-
204
-	@classmethod
205
-	def random_race(cls):
206
-		return random.choice(self.registry.values())
207
-	@property
208
-	def name(self):
209
-		return self.__class__.__name__.lower()
210
-
211
-	allowed_professions = set()
212
-	def __init__(self, attr):
213
-		self.mod(attr)
214
-
215
-	def allows_profession(self, prof):
216
-		return prof in self.allowed_professions
217
-
218
-@Race.register
219
-class Human(Race):
220
-	def mod(self, attr):
221
-		attr.spt += 1
222
-
223
-@Race.register
224
-class Elf(Race):
225
-	allowed_professions = {'fighter', 'wizard', 'thief'}
226
-	def mod(self, attr):
227
-		attr.int += 1
228
-
229
-@Race.register
230
-class Dwarf(Race):
231
-	allowed_professions = {'fighter', 'Priest', 'thief'}
232
-	def mod(self, atr):
233
-		attr.str += 1
234
-
235
-@Race.register
236
-class Hobbit(Race):
237
-	allowed_professions = {'thief', 'barbarian'}
238
-	def mod(self, atr):
239
-		attr.dex += 1
240
-
241
-
242
-class Sword(Weapon):
243
-	attack = 1
244
-	damage_mod = 1
245
-
246
-
247
-HEALTHY = 0
248
-WOUNDED = 1
249
-KNOCKOUT = 2
250
-
251
-@Slot.add_slot('weapon', Weapon)
252
-@Slot.add_slot('armor', Armor)
19
+@equipment.Slot.add_slot('weapon', equipment.Weapon)
20
+@equipment.Slot.add_slot('armor', equipment.Armor)
253 21
 class Adventurer(object):
254 22
 	@property
255 23
 	def state(self):
256 24
 		return self.attributes.state
257 25
 	@state.setter
258 26
 	def state(self, val):
259
-		if val not in {HEALTHY, WOUNDED, KNOCKOUT}:
27
+		if val not in {const.HEALTHY, const.WOUNDED, const.KNOCKOUT}:
260 28
 			raise ValueError('Value for state invalid')
261 29
 		self.attributes.state = val
262 30
 
263 31
 	def __init__(self, name, race, str, int, dex, spt):
264 32
 		self.name = name
265 33
 		self.attributes = Attributes(str, int, dex, spt)
266
-		self.skills = Skills(self.attributes)
267
-		self.race = Race.registry[race](self.attributes)
34
+		self.skills = skills.Skills(self.attributes)
35
+		self.race = races.Race.registry[race](self.attributes)
268 36
 
269 37
 	def wield(self, slot, equipment):
270 38
 		turns = 1
... ...
@@ -300,7 +68,7 @@ class Adventurer(object):
300 68
 			if damage > 0:
301 69
 				self.state += 1
302 70
 				print '%s takes %d damage and is now %s' % (self.name, damage, ['healthy', 'wounded', 'ko'][self.state if self.state < 3 else 2])
303
-				if self.state >= KNOCKOUT:
71
+				if self.state >= const.KNOCKOUT:
304 72
 					self.die()
305 73
 
306 74
 	def die(self): pass
... ...
@@ -316,13 +84,13 @@ def get_stats():
316 84
 	print sum(stats), stats
317 85
 	return stats
318 86
 
87
+if __name__ == '__main__':
88
+	a = Adventurer('bob', 'elf', *get_stats())
89
+	b = Adventurer('bill', 'elf', *get_stats())
319 90
 
320
-a = Adventurer('bob', 'elf', *get_stats())
321
-b = Adventurer('bill', 'elf', *get_stats())
322
-
323
-while KNOCKOUT not in {a.state, b.state}:
324
-	a.attack(b)
325
-	b.attack(a)
91
+	while const.KNOCKOUT not in {a.state, b.state}:
92
+		a.attack(b)
93
+		b.attack(a)
326 94
 
327
-print a.name, 'is', ['healthy', 'wounded', 'ko'][a.state if a.state < 3 else 2]
328
-print b.name, 'is', ['healthy', 'wounded', 'ko'][b.state if b.state < 3 else 2]
95
+	print a.name, 'is', ['healthy', 'wounded', 'ko'][a.state if a.state < 3 else 2]
96
+	print b.name, 'is', ['healthy', 'wounded', 'ko'][b.state if b.state < 3 else 2]