git.fiddlerwoaroof.com
Browse code

refactoring combat into several files

edwlan authored on 29/07/2013 03:55:55
Showing 5 changed files
2 2
new file mode 100644
... ...
@@ -0,0 +1,5 @@
1
+HEALTHY = 0
2
+WOUNDED = 1
3
+KNOCKOUT = 2
4
+
5
+
0 6
new file mode 100644
... ...
@@ -0,0 +1,77 @@
1
+from .. import type_dict
2
+
3
+import collections
4
+
5
+class Equipment(object): pass
6
+class Weapon(Equipment): pass
7
+class Armor(Equipment): pass
8
+
9
+
10
+class Slot(object):
11
+	def __init__(self, name, type):
12
+		self.name = name
13
+		self.attr = 'slotted_%s' % name
14
+		self.type = type
15
+
16
+	def __get__(self, instance, owner):
17
+		return self.getitem(instance)
18
+	def __set__(self, instance, value):
19
+		self.setitem(instance, value)
20
+
21
+	def setitem(self, instance, value):
22
+		if isinstance(value, self.type):
23
+			setattr(instance, 'slotted_%s' % self.name, value)
24
+		else:
25
+			raise ValueError(
26
+				'Can\'t use an object of type %s in a slot of type %s' % (type(value), self.type)
27
+			)
28
+
29
+
30
+	def getitem(self, instance):
31
+		return getattr(instance, self.attr, None)
32
+
33
+	def filled(self, instance):
34
+		return self.getitem(instance) is not None
35
+
36
+	@classmethod
37
+	def add_slot(cls, name, type):
38
+		def _inner(to_cls):
39
+			inst = cls(name, type)
40
+			setattr(to_cls, name, inst)
41
+			if not hasattr(to_cls, 'equipment_slots'):
42
+				to_cls.equipment_slots = Slots((name,inst))
43
+			else:
44
+				to_cls.equipment_slots[name] = inst
45
+			return to_cls
46
+		return _inner
47
+
48
+
49
+class Slots(collections.MutableMapping):
50
+	def __init__(self, *args, **kw):
51
+		self.slots = dict(args)
52
+		self.slots.update(kw)
53
+		self.slots_by_type = type_dict.TypeDict(__default=[])
54
+		for k in self.slots:
55
+			slot = self.slots[k]
56
+			self.slots_by_type[slot.type].append(slot)
57
+
58
+	def __getitem__(self, key):
59
+		return self.slots[key]
60
+	def __setitem__(self, k, v):
61
+		self.slots[k] = v
62
+	def __delitem__(self, key):
63
+		del self.slots[key]
64
+
65
+	def __iter__(self):
66
+		return iter(self.slots)
67
+	def __len__(self):
68
+		return len(self.slots)
69
+
70
+	def slots_of_type(self, slot_type):
71
+		return self.slots_by_type[slot_type]
72
+
73
+class Sword(Weapon):
74
+	attack = 1
75
+	damage_mod = 1
76
+
77
+
0 78
new file mode 100644
... ...
@@ -0,0 +1,47 @@
1
+import random
2
+
3
+class Race(object):
4
+	registry = {}
5
+	@classmethod
6
+	def register(cls, new):
7
+		cls.registry[new.__name__.lower()] = new
8
+
9
+	@classmethod
10
+	def random_race(cls):
11
+		return random.choice(self.registry.values())
12
+	@property
13
+	def name(self):
14
+		return self.__class__.__name__.lower()
15
+
16
+	allowed_professions = set()
17
+	def __init__(self, attr):
18
+		self.mod(attr)
19
+
20
+	def allows_profession(self, prof):
21
+		return prof in self.allowed_professions
22
+
23
+@Race.register
24
+class Human(Race):
25
+	def mod(self, attr):
26
+		attr.spt += 1
27
+
28
+@Race.register
29
+class Elf(Race):
30
+	allowed_professions = {'fighter', 'wizard', 'thief'}
31
+	def mod(self, attr):
32
+		attr.int += 1
33
+
34
+@Race.register
35
+class Dwarf(Race):
36
+	allowed_professions = {'fighter', 'Priest', 'thief'}
37
+	def mod(self, atr):
38
+		attr.str += 1
39
+
40
+@Race.register
41
+class Hobbit(Race):
42
+	allowed_professions = {'thief', 'barbarian'}
43
+	def mod(self, atr):
44
+		attr.dex += 1
45
+
46
+
47
+
0 48
new file mode 100644
... ...
@@ -0,0 +1,119 @@
1
+from ..dice import MULT, ADD
2
+from .. import dice
3
+from .constants import *
4
+
5
+import collections
6
+
7
+def health_mod(func):
8
+	def _inner(self):
9
+		mod = 0
10
+		if self.attr.state >= WOUNDED:
11
+			mod = -3
12
+		result = func(self)
13
+		result += mod
14
+		return result
15
+	return _inner
16
+
17
+class Skills(object):
18
+	def __init__(self, attr):
19
+		self.skills = {
20
+			'agility','craft','fighting','knowledge',
21
+			'perception','persuasion','shooting','speed',
22
+			'stealth','toughness'
23
+		}
24
+		self.attr = attr
25
+		self.training = Trainer(self)
26
+		self.train = self.training.select
27
+
28
+	def check(self, skill, dieroll):
29
+		dieroll.dice = dice.DieJar().d20
30
+		roll = dieroll.roll()
31
+		if roll == 1:
32
+			result = False
33
+		if roll == 20:
34
+			result = True
35
+		else:
36
+			result = roll < getattr(self, skill)
37
+		return result, roll-result # (passes, difference)
38
+
39
+	@property
40
+	@health_mod
41
+	def agility(self):
42
+		return (self.attr.dex * 2) + self.training.agility
43
+	@property
44
+	@health_mod
45
+	def craft(self):
46
+		return self.attr.dex + self.attr.int + self.training.craft
47
+	@property
48
+	@health_mod
49
+	def fighting(self):
50
+		return self.attr.str + self.attr.int + self.training.fighting
51
+	@property
52
+	@health_mod
53
+	def knowledge(self):
54
+		return self.attr.int * 2 + self.training.knowledge
55
+	@property
56
+	@health_mod
57
+	def perception(self):
58
+		return self.attr.int + attr.spt + self.training.perception
59
+	@property
60
+	@health_mod
61
+	def persuasion(self):
62
+		return self.attr.spt * 2 + self.training.persuasion
63
+	@property
64
+	@health_mod
65
+	def shooting(self):
66
+		return self.attr.dex + self.attr.int + self.training.shooting
67
+	@property
68
+	@health_mod
69
+	def speed(self):
70
+		return self.attr.str + self.attr.dex + self.training.speed
71
+	@property
72
+	@health_mod
73
+	def stealth(self):
74
+		return self.attr.dex + self.attr.spt + self.training.stealth
75
+	@property
76
+	@health_mod
77
+	def toughness(self):
78
+		return self.attr.str + self.attr.spt + self.training.toughness
79
+
80
+class Trainer(object):
81
+	mods = dict(
82
+		untrained=-1,
83
+		familiar=0,
84
+		trained=1,
85
+		experienced=2,
86
+		mastered=3
87
+	)
88
+
89
+	def __init__(self, skills):
90
+		self.skills = skills
91
+		self.training = collections.defaultdict(lambda: -1)
92
+		self.points = 500
93
+		self.training_cost = 100
94
+
95
+	def select(self, skill, degree):
96
+		if hasattr(degree, 'upper'):
97
+			degree = self.mods.get(degree, 0)
98
+		if self.points >= self.training_cost and degree in self.mods.values():
99
+			self.training[skill] = degree
100
+			self.points -= self.training_cost
101
+
102
+	def __getattr__(self, key):
103
+		skills = object.__getattribute__(self, 'skills')
104
+		if key in self.skills.skills:
105
+			return self.training[key]
106
+		else:
107
+			raise
108
+	def __setattr__(self, key, value):
109
+		if hasattr(self, 'skills') and key in self.skills.skills:
110
+			if -1 <= value <= 3:
111
+				self.training[key] = int(round(value))
112
+			else:
113
+				raise AttributeError(
114
+					'cannot set training of %s to %d, (out of range [-1,3])' % (key, value)
115
+				)
116
+		else:
117
+			object.__setattr__(self, key, value)
118
+
119
+