-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathactor.py
146 lines (127 loc) · 4.37 KB
/
actor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import libtcodpy as tcod
import ai
from display_char import DisplayChar
from command import ActionType, MOVES
from render import show_popup
next_actor_id = 0
def starting_stats(actor_type):
if actor_type == 'player':
return 10, 0, 1
else:
return 1, 0, 1
class Actor:
"""
A class to represent both the player and monsters
"""
def __init__(self, type, pos):
global next_actor_id
self.kind = type
self.pos = pos
if type == 'player':
self.ai = ai.PlayerAI(self)
else:
self.ai = ai.SimpleMonsterAI(self)
self.is_active_player = False
self.max_hp, self.defense, self.power = starting_stats(type)
self.hp = self.max_hp
self.alive = True
self.id = next_actor_id
next_actor_id += 1
self.inventory = []
self.energy = 0
def name(self):
if self.kind == 'player':
if self.is_active_player:
return 'you'
else:
return 'your past self'
else:
return 'the ' + self.kind
def possessive(self):
if self.kind == 'player':
if self.is_active_player:
return "your"
else:
return "your past self's"
else:
return "the " + self.kind + "'s"
def conjugate(self, verb):
if self.is_active_player:
return verb
else:
return verb + 's'
def execute(self, command, game_map):
action = command.action
if action in MOVES:
x, y = self.pos
dx, dy = MOVES[action]
newpos = x + dx, y + dy
other = game_map.actor_at(newpos)
if other:
return self.attack(other)
else:
return self.move_to(game_map, newpos)
if action is ActionType.Rest:
return [{'time': 100}]
if action is ActionType.Exit:
return [{'exit': True}]
if action is ActionType.Pickup:
return self.pickup(game_map)
if action is ActionType.Describe:
if self.is_active_player:
show_popup(command.item.description(), 'DESCRIBE')
return []
if action is ActionType.Apply:
used, results = command.item.apply(self)
if used:
self.inventory.remove(command.item)
return results
return []
def pickup(self, game_map):
if len(self.inventory) >= 26:
return [{'message': 'Inventory full.'}]
item = game_map.item_at(self.pos)
if not item:
return []
self.inventory.append(item)
game_map.items.remove(item)
return [{'message': '{} {} up {}.'.format(self.name().capitalize(),
self.conjugate('pick'),
item.name())},
{'time': 100}]
def attack(self, target):
results = []
damage = self.power - target.defense
results.append({'message': '{} {} {}.'.format(self.name().capitalize(),
self.conjugate('hit'),
target.name())})
if damage > 0:
results.extend(target.hurt(damage))
results.append({'time': 100})
return results
def hurt(self, amount):
results = []
self.hp -= amount
if self.hp <= 0:
results.append({'dead': self})
return results
def die(self):
self.alive = False
return '{} {}!'.format(self.name().capitalize(), self.conjugate('die'))
def move_to(self, map, pos):
if not map.is_passable(pos):
return []
if map.actor_at(pos):
return []
x, y = self.pos
self.pos = pos
if self.is_active_player:
map.los_changed = True
return [{'time': 100}]
def display_char(self):
if self.kind == 'player':
return DisplayChar('@', tcod.white)
elif self.kind == 'human weakling':
return DisplayChar('w', tcod.light_cyan)
else:
return DisplayChar('?', tcod.magenta)