-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path2_6.py
166 lines (143 loc) · 5.42 KB
/
2_6.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
159
160
161
162
163
164
165
166
"""
Student portion of Zombie Apocalypse mini-project
"""
import poc_grid
import poc_queue
import poc_zombie_gui
EMPTY = 0
FULL = 1
FOUR_WAY = 0
EIGHT_WAY = 1
OBSTACLE = "obstacle"
HUMAN = "human"
ZOMBIE = "zombie"
class Apocalypse(poc_grid.Grid):
"""
Class for simulating zombie pursuit of human on grid with
obstacles
"""
def __init__(self, grid_height, grid_width, obstacle_list=None, \
zombie_list=None, human_list=None):
"""
Create a simulation of given size with given obstacles,
humans, and zombies
"""
poc_grid.Grid.__init__(self, grid_height, grid_width)
if obstacle_list != None:
for cell in obstacle_list:
self.set_full(cell[0], cell[1])
if zombie_list != None:
self._zombie_list = list(zombie_list)
else:
self._zombie_list = []
if human_list != None:
self._human_list = list(human_list)
else:
self._human_list = []
def clear(self):
"""
Set cells in obstacle grid to be empty
Reset zombie and human lists to be empty
"""
poc_grid.Grid.clear(self)
self._zombie_list = []
self._human_list = []
def add_zombie(self, row, col):
"""
Add zombie to the zombie list
"""
self._zombie_list.append((row, col))
def num_zombies(self):
"""
Return number of zombies
"""
return len(self._zombie_list)
def zombies(self):
"""
Generator that yields the zombies in the order they were
added.
"""
return (zombie for zombie in self._zombie_list)
def add_human(self, row, col):
"""
Add human to the human list
"""
self._human_list.append((row, col))
def num_humans(self):
"""
Return number of humans
"""
return len(self._human_list)
def humans(self):
"""
Generator that yields the humans in the order they were added.
"""
return (human for human in self._human_list)
def compute_distance_field(self, entity_type):
"""
Function computes a 2D distance field
Distance at member of entity_queue is zero
Shortest paths avoid obstacles and use distance_type distances
"""
visited = poc_grid.Grid(self.get_grid_height(), self.get_grid_width())
for row in range(self.get_grid_height()):
for col in range(self.get_grid_width()):
if not self.is_empty(row, col):
visited.set_full(row, col)
distance_field = [[self.get_grid_height() * self.get_grid_width() \
for dummy_col in range(self.get_grid_width())] \
for dummy_row in range(self.get_grid_height())]
entity_cells = self._zombie_list \
if entity_type is ZOMBIE \
else self._human_list
boundary = poc_queue.Queue()
for entity_cell in entity_cells:
visited.set_full(entity_cell[0], entity_cell[1])
distance_field[entity_cell[0]][entity_cell[1]] = 0
boundary.enqueue(entity_cell)
while len(boundary) > 0:
current = boundary.dequeue()
neighbors = self.four_neighbors(current[0], current[1])
distance = distance_field[current[0]][current[1]] + 1
for neighbor in neighbors:
if visited.is_empty(neighbor[0], neighbor[1]):
if distance < distance_field[neighbor[0]][neighbor[1]]:
distance_field[neighbor[0]][neighbor[1]] = distance
visited.set_full(neighbor[0], neighbor[1])
boundary.enqueue(neighbor)
return distance_field
def move_humans(self, zombie_distance):
"""
Function that moves humans away from zombies, diagonal moves
are allowed
"""
for index, human_cell in enumerate(self._human_list):
safest_cell = human_cell
safest_distance = zombie_distance[human_cell[0]][human_cell[1]]
neighbors = self.eight_neighbors(human_cell[0], human_cell[1])
for neighbor_cell in neighbors:
if not self.is_empty(neighbor_cell[0], neighbor_cell[1]):
continue
distance = zombie_distance[neighbor_cell[0]][neighbor_cell[1]]
if distance > safest_distance:
safest_cell = neighbor_cell
safest_distance = distance
self._human_list[index] = safest_cell
def move_zombies(self, human_distance):
"""
Function that moves zombies towards humans, no diagonal moves
are allowed
"""
for index, zombie_cell in enumerate(self._zombie_list):
nearest_cell = zombie_cell
nearest_distance = human_distance[zombie_cell[0]][zombie_cell[1]]
neighbors = self.four_neighbors(zombie_cell[0], zombie_cell[1])
for neighbor_cell in neighbors:
if not self.is_empty(neighbor_cell[0], neighbor_cell[1]):
continue
distance = human_distance[neighbor_cell[0]][neighbor_cell[1]]
if distance < nearest_distance:
nearest_cell = neighbor_cell
nearest_distance = distance
self._zombie_list[index] = nearest_cell
poc_zombie_gui.run_gui(Apocalypse(30, 40))