From: Christian Heller Date: Wed, 30 Jan 2019 23:37:00 +0000 (+0100) Subject: Refactor and optimize FOV algorithm. X-Git-Url: https://plomlompom.com/repos/%7B%7Bdb.prefix%7D%7D/%7B%7B%20web_path%20%7D%7D/decks/blog?a=commitdiff_plain;h=de3297c4d4c8e3bf68d946434c01edc71e36f819;p=plomrogue2-experiments Refactor and optimize FOV algorithm. --- diff --git a/server_/game.py b/server_/game.py index 0974f1b..aafc740 100644 --- a/server_/game.py +++ b/server_/game.py @@ -118,13 +118,15 @@ class Thing(game_common.Thing): dijkstra_map.terrain = [n_max for i in range(dijkstra_map.size_i)] dijkstra_map[target] = 0 shrunk = True + stencil = self.get_stencil() while shrunk: shrunk = False for pos in dijkstra_map: - if self.world.map_[pos] != '.': + if stencil[pos] != '.': continue - neighbors = dijkstra_map.get_neighbors(pos) - for yx in neighbors: + neighbors = dijkstra_map.get_neighbors(tuple(pos)) + for direction in neighbors: + yx = neighbors[direction] if yx is not None and dijkstra_map[yx] < dijkstra_map[pos] - 1: dijkstra_map[pos] = dijkstra_map[yx] + 1 shrunk = True @@ -139,9 +141,10 @@ class Thing(game_common.Thing): # else: # f.write('~') # f.write('\n') - neighbors = dijkstra_map.get_neighbors(self.position) + neighbors = dijkstra_map.get_neighbors(tuple(self.position)) n = n_max - dirs = dijkstra_map.get_directions() + #print('DEBUG', self.position, neighbors) + #dirs = dijkstra_map.get_directions() #print('DEBUG dirs', dirs) #print('DEBUG neighbors', neighbors) #debug_scores = [] @@ -151,15 +154,17 @@ class Thing(game_common.Thing): # else: # debug_scores += [dijkstra_map[pos]] #print('DEBUG debug_scores', debug_scores) - direction = None - for i_dir in range(len(neighbors)): - pos = neighbors[i_dir] - if pos is not None and dijkstra_map[pos] < n: - n = dijkstra_map[pos] - direction = dirs[i_dir] + target_direction = None + for direction in neighbors: + yx = neighbors[direction] + if yx is not None: + n_new = dijkstra_map[yx] + if n_new < n: + n = n_new + target_direction = direction #print('DEBUG result', direction) - if direction: - self.set_task('MOVE', (direction,)) + if target_direction: + self.set_task('MOVE', (target_direction,)) #self.world.game.io.send('would move ' + direction) def decide_task(self): diff --git a/server_/map_.py b/server_/map_.py index 35d29c6..dd47be5 100644 --- a/server_/map_.py +++ b/server_/map_.py @@ -50,6 +50,21 @@ class Map(game_common.Map): directions += [name[5:]] return directions + def get_neighbors(self, pos): + neighbors = {} + if not hasattr(self, 'neighbors_to'): + self.neighbors_to = {} + if pos in self.neighbors_to: + return self.neighbors_to[pos] + for direction in self.get_directions(): + neighbors[direction] = None + try: + neighbors[direction] = self.move(pos, direction) + except server_.game.GameError: + pass + self.neighbors_to[pos] = neighbors + return neighbors + def new_from_shape(self, init_char): import copy new_map = copy.deepcopy(self) @@ -110,34 +125,6 @@ class MapHex(Map): else: return [start_pos[0] + 1, start_pos[1] + 1] - def get_neighbors(self, pos): - # DOWNLEFT, DOWNRIGHT, LEFT, RIGHT, UPLEFT, UPRIGHT (alphabetically) - neighbors = [None, None, None, None, None, None] # e, d, c, x, s, w - if pos[1] > 0: - neighbors[2] = [pos[0], pos[1] - 1] - if pos[1] < self.size[1] - 1: - neighbors[3] = [pos[0], pos[1] + 1] - # x, c, s, d, w, e # 3->0, 2->1, 5->4, 0->5 - if pos[0] % 2 == 1: - if pos[0] > 0 and pos[1] > 0: - neighbors[4] = [pos[0] - 1, pos[1] - 1] - if pos[0] < self.size[0] - 1 and pos[1] > 0: - neighbors[0] = [pos[0] + 1, pos[1] - 1] - if pos[0] > 0: - neighbors[5] = [pos[0] - 1, pos[1]] - if pos[0] < self.size[0] - 1: - neighbors[1] = [pos[0] + 1, pos[1]] - else: - if pos[0] > 0 and pos[1] < self.size[1] - 1: - neighbors[5] = [pos[0] - 1, pos[1] + 1] - if pos[0] < self.size[0] - 1 and pos[1] < self.size[1] - 1: - neighbors[1] = [pos[0] + 1, pos[1] + 1] - if pos[0] > 0: - neighbors[4] = [pos[0] - 1, pos[1]] - if pos[0] < self.size[0] - 1: - neighbors[0] = [pos[0] + 1, pos[1]] - return neighbors - class MapSquare(Map): @@ -151,19 +138,6 @@ class MapSquare(Map): def move_DOWN(self, start_pos): return [start_pos[0] + 1, start_pos[1]] - def get_neighbors(self, pos): - # DOWN, LEFT, RIGHT, UP (alphabetically) - neighbors = [None, None, None, None] - if pos[0] > 0: - neighbors[3] = [pos[0] - 1, pos[1]] - if pos[1] > 0: - neighbors[1] = [pos[0], pos[1] - 1] - if pos[0] < self.size[0] - 1: - neighbors[0] = [pos[0] + 1, pos[1]] - if pos[1] < self.size[1] - 1: - neighbors[2] = [pos[0], pos[1] + 1] - return neighbors - class FovMap: