Browse code
refactoring combat into several files
edwlan authored on 29/07/2013 03:55:55
Showing 5 changed files
Showing 5 changed files
- libs/combat_parts/__init__.py
- libs/combat_parts/constants.py
- libs/combat_parts/equipment.py
- libs/combat_parts/races.py
- libs/combat_parts/skills.py
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 |
+ |