Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- Student portion of Zombie Apocalypse mini-project
- """
- #http://www.codeskulptor.org/#user43_yCIa8eafEzbL3Am_20.py
- import random
- import poc_grid
- import poc_queue
- import poc_zombie_gui
- # global constants
- EMPTY = 0
- FULL = 1
- FOUR_WAY = 0
- EIGHT_WAY = 1
- OBSTACLE = 5
- HUMAN = 6
- ZOMBIE = 7
- 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 = []
- return
- def add_zombie(self, row, col):
- """
- Add zombie to the zombie list
- """
- self._zombie_list.append((row,col))
- return
- 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.
- """
- for zombie in self._zombie_list:
- yield zombie
- 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.
- """
- for human in self._human_list:
- yield human
- def print_all(self):
- """
- prints out a grid showing where humans, zombies, and blocks are.
- """
- grid_copy = list(self._cells)
- for human in self.humans():
- grid_copy[human[0]][human[1]] = 6
- for zombie in self.zombies():
- grid_copy[zombie[0]][zombie[1]] = 7
- ans = ""
- for row in range(self._grid_height):
- ans += str(grid_copy[row])
- ans += "\n"
- return ans
- def compute_distance_field(self, entity_type):
- """
- Function computes and returns a 2D distance field
- Distance at member of entity_list is zero
- Shortest paths avoid obstacles and use four-way distances
- """
- boundary = poc_queue.Queue()
- visited = poc_grid.Grid(self.get_grid_height(),self.get_grid_width())
- 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())]
- #Que entities to boundary
- if entity_type == HUMAN:
- for human in self.humans():
- boundary.enqueue(human)
- elif entity_type == ZOMBIE:
- for zombie in self.zombies():
- boundary.enqueue(zombie)
- else:
- print "invalid input"
- return
- #set entity positions in visited grid as "full" and in distance_field as "0"
- for item in boundary:
- visited.set_full(item[0], item[1])
- distance_field[item[0]][item[1]] = 0
- #iterate to add new cells surrounding boundary members to boundary
- #set new cells as full in visited and #steps in dist_field; dequeue original boundary cell
- while boundary:
- location = boundary.dequeue()
- location_dist = distance_field[location[0]][location[1]]
- adjacent = visited.four_neighbors(location[0], location[1])
- for adj in adjacent:
- if self.is_empty(adj[0],adj[1]) and visited.is_empty(adj[0],adj[1]):
- boundary.enqueue(adj)
- visited.set_full(adj[0], adj[1])
- distance_field[adj[0]][adj[1]] = location_dist+1
- return distance_field
- def is_cell_empty(self, cell):
- """
- returns if a cell is empty
- """
- #takes single tuple instead of row, col... allows function to be used as filter
- return self.is_empty(cell[0], cell[1])
- def move_humans(self, zombie_distance_field):
- """
- Function that moves humans away from zombies, diagonal moves
- are allowed
- """
- new_humans = []
- for human in self.humans():
- possible_moves = filter(self.is_cell_empty, self.eight_neighbors(human[0], human[1]))
- best_move = self.get_best_move(human, possible_moves, zombie_distance_field, True)
- new_humans.append(best_move)
- self._human_list = new_humans
- def move_zombies(self, human_distance_field):
- """
- Function that moves zombies towards humans, no diagonal moves
- are allowed
- """
- new_zombies = []
- for zombie in self.zombies():
- possible_moves = filter(self.is_cell_empty, self.four_neighbors(zombie[0], zombie[1]))
- best_move = self.get_best_move(zombie, possible_moves, human_distance_field, False)
- new_zombies.append(best_move)
- self._zombie_list = new_zombies
- def get_best_move(self, current_position, possible_moves, distance_field, flee):
- """
- returns one of possible best moves for a zombie or human
- """
- best_move = []
- best_move.append(current_position)
- for move in possible_moves:
- if flee:
- if distance_field[move[0]][move[1]] > distance_field[best_move[0][0]][best_move[0][1]]:
- best_move = [move]
- elif distance_field[move[0]][move[1]] == distance_field[best_move[0][0]][best_move[0][1]]:
- best_move.append(move)
- elif not flee:
- if distance_field[move[0]][move[1]] < distance_field[best_move[0][0]][best_move[0][1]]:
- best_move = [move]
- elif distance_field[move[0]][move[1]] == distance_field[best_move[0][0]][best_move[0][1]]:
- best_move.append(move)
- random.shuffle(best_move)
- return best_move.pop()
- # Start up gui for simulation - You will need to write some code above
- # before this will work without errors
- poc_zombie_gui.run_gui(Apocalypse(30, 40))
- #game = Apocalypse(3, 3, [], [(2, 2)], [(1, 1)])
- #dist = [[4, 3, 2], [3, 2, 1], [2, 1, 0]]
- #print game
- #print
- #print "Print all:"
- #print game.print_all()
- #print
- ##dist = game.compute_distance_field(HUMAN)
- #print "distance field:"
- #for row in range(len(dist)):
- # print dist[row]
- #game.move_humans(dist)
- #print "Moved humans"
- #print game.print_all()
- #i = 0
- #j = 1
- #rows = 10
- #cols = 10
- #blocks = [(3,8)]
- ##zombies = [(i,col) for col in range(cols)]
- ##humans = [(j,col) for col in range(cols)]
- #zombies = [(0,4)]
- #humans = [(1,4)]
- #
- #game = Apocalypse(rows, cols, blocks, zombies, humans)
- #dist = game.compute_distance_field(ZOMBIE)
- #print "distance field:"
- #for row in range(len(dist)):
- # print dist[row]
- #print
- #print game.print_all()
- #game.move_humans(dist)
- #print game.print_all()
- #game.clear()
- #print game
Advertisement
Add Comment
Please, Sign In to add comment