-
Notifications
You must be signed in to change notification settings - Fork 4
/
util.py
158 lines (130 loc) · 5.78 KB
/
util.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
147
148
149
150
151
152
153
154
155
156
157
158
from actor import DoNothingActor, StunnedActor
from entityeffect import AddSpoofChild
import gametime
import libtcodpy as libtcod
from mover import ImmobileStepper
import turn
import direction
import geometry as geo
class WalkableDestinatinationsPath(object):
def __init__(self):
self._cache = {}
self._time_stamps = {}
def _has_destinations_newer_than(self, entity, position, time_stamp):
if(self._has_destinations(entity, position) and
time_stamp <= self._time_stamps[entity.description.name]):
return True
return False
def _get_destinations(self, entity, position):
class_cache = self._cache[entity.description.name]
return class_cache[position]
def _has_destinations(self, entity, position):
if not entity.description.name in self._cache.keys():
return False
class_cache = self._cache[entity.description.name]
if not position in class_cache.keys():
return False
return True
def _set_destinations(self, entity, click_of_points):
if not entity.description.name in self._cache.keys():
self._cache[entity.description.name] = {}
class_cache = self._cache[entity.description.name]
for point in click_of_points:
class_cache[point] = click_of_points
# Maybe a per point time_stamp is necessary?
self._time_stamps[entity.description.name] = turn.current_turn
def get_walkable_positions(self, entity, position, dungeon_level):
time_stamp = dungeon_level.terrain_changed_timestamp
if not self._has_destinations_newer_than(entity, position, time_stamp):
self._calculate_walkable_positions_from_entity_position(entity, position, dungeon_level)
return self._get_destinations(entity, position)
def _calculate_walkable_positions_from_entity_position(self, entity, position, dungeon_level):
visited = set()
visited.add(position)
queue = [position]
queue.extend(_get_walkable_neighbors(entity, position, dungeon_level))
while len(queue) > 0:
position = queue.pop(0)
while len(queue) > 0 and position in visited:
position = queue.pop(0)
visited.add(position)
neighbors = set(_get_walkable_neighbors(entity, position, dungeon_level)) - visited
queue.extend(neighbors)
visited = list(visited)
self._set_destinations(entity, visited)
def _position_has_item_with_auto_pick_up(position, dungeon_level):
tile = dungeon_level.get_tile(position)
item = tile.get_first_item()
if item and item.has("player_auto_pick_up"):
return True
return False
def get_closest_unseen_walkable_position(entity, position, dungeon_level):
visited = set()
visited.add(position)
queue = [position]
queue.extend(_get_walkable_neighbors(entity, position, dungeon_level))
while len(queue) > 0:
position = queue.pop(0)
while len(queue) > 0 and position in visited:
position = queue.pop(0)
if not entity.memory_map.has_seen_position(position):
return position_or_walkable_neighbor(position, entity, dungeon_level)
elif _position_has_item_with_auto_pick_up(position, dungeon_level):
return position
visited.add(position)
neighbors = set(_get_walkable_neighbors_or_unseen(position, entity, dungeon_level)) - visited
queue.extend(neighbors)
return None
def position_or_walkable_neighbor(position, entity, dungeon_level):
tile = dungeon_level.get_tile(position)
if entity.mover.can_pass_terrain(tile.get_terrain()):
return position
else:
return _get_walkable_neighbors(entity, position, dungeon_level)[0]
def _get_walkable_neighbors(entity, position, dungeon_level):
result_positions = []
for direction_ in direction.DIRECTIONS:
neighbor_position = geo.add_2d(position, direction_)
try:
neighbor = dungeon_level.get_tile(neighbor_position)
if entity.mover.can_pass_terrain(neighbor.get_terrain()):
result_positions.append(neighbor_position)
except IndexError:
pass
return result_positions
def _get_walkable_neighbors_or_unseen(position, entity, dungeon_level):
result_positions = []
for direction_ in direction.DIRECTIONS:
neighbor_position = geo.add_2d(position, direction_)
try:
neighbor = dungeon_level.get_tile(neighbor_position)
if (entity.mover.can_pass_terrain(neighbor.get_terrain()) or
not entity.memory_map.has_seen_position(neighbor_position)):
result_positions.append(neighbor_position)
except IndexError:
pass
return result_positions
def entity_skip_turn(source_entity, target_entity):
add_spoof_effect = AddSpoofChild(source_entity, DoNothingActor(), gametime.single_turn)
target_entity.effect_queue.add(add_spoof_effect)
def entity_stunned_turn(source_entity, target_entity):
add_spoof_effect = AddSpoofChild(source_entity, StunnedActor(), gametime.single_turn)
target_entity.effect_queue.add(add_spoof_effect)
def entity_skip_step(source_entity, target_entity):
add_spoof_effect = AddSpoofChild(source_entity, ImmobileStepper(), gametime.single_turn)
target_entity.effect_queue.add(add_spoof_effect)
def get_path(start, destination):
result = [start]
sx, sy = start
dx, dy = destination
libtcod.line_init(sx, sy, dx, dy)
x, y = libtcod.line_step()
while not x is None:
result.append((x, y))
x, y = libtcod.line_step()
return result
def add_energy_spent_to_entity(entity, time):
"""
Help method for spending energy for the act performing entity.
"""
entity.actor.newly_spent_energy += time