def pathfind_through_unexplored_to(self, target, initial): """A* pathfinding from initial to target, where A* can visit any position that has *NOT* been explored. Args: target: target position to pathfind to. initial: position to start pathfinding from. If None, use current player position. """ if (initial, target) not in self.pathfind2_distances: overwritten_chars = {} #for x, y in override_targets: # overwritten_chars[(x, y)] = self.grid[x][y] #if override_target_traversability: inverse_grid = np.array([[1 for j in range(COLNO)] for i in range(ROWNO)]) for x in range(ROWNO): #self.GRIDWIDTH): for y in range(COLNO): #self.GRIDHEIGHT): if self.nh.basemap_char(x, y) == ' ': inverse_grid[x][y] = 0 overwritten_chars[target] = inverse_grid[target[0]][target[1]] inverse_grid[target[0]][target[1]] = 0 #for x, y in override_targets: # self.grid[x][y] = 0 path = astar.astar(inverse_grid, initial, target, diag=False) if type(path) is bool: #verboseprint("Error: could not pathfind from", initial, "to", target, "! (target on map:", self.nh.map[target[0]][target[1]], " and basemap:", self.nh.base_map[target[0]][target[1]], ")") self.pathfind2_distances[(initial, target)] = None return None path.reverse() # path[0] should be next to start node. self.pathfind2_distances[(initial, target)] = path return self.pathfind2_distances[(initial, target)]
def pathfind_to(self, target, initial=None, full_path=True, explored_set=None, override_target_traversability=False, override_targets=[]): """A* pathfinding from initial to target, where A* can visit any position that has been explored. Args: target: target position to pathfind to. initial: position to start pathfinding from. If None, use current player position. full_path: return entire trajectory if True, else return first position from initial. explored_set: if not None, increase A* heuristic score of non-explored tiles over explored tiles (e.g., if walking through a diagonal corridor, prefer to visit each square instead of moving diagonally, so we don't miss any branching corridor). override_target_traversability: pathfind to target even if it is not traversable by the player (e.g., solid wall). override_targets: override traversability of all targets in this list (see above parameter) """ if initial == None: initial = self.cur_pos if (initial, target) not in self.pathfind_distances: overwritten_chars = {} for x, y in override_targets: overwritten_chars[(x, y)] = self.grid[x][y] if override_target_traversability: overwritten_chars[target] = self.grid[target[0]][target[1]] self.grid[target[0]][target[1]] = 0 for x, y in override_targets: self.grid[x][y] = 0 path = astar.astar(self.grid, initial, target, explored_set=explored_set) for (x, y) in overwritten_chars: self.grid[x][y] = overwritten_chars[(x, y)] if type(path) is bool: verboseprint("Error: could not pathfind from", initial, "to", target, "! (target on map:", self.map[target[0]][target[1]], " and basemap:", self.base_map[target[0]][target[1]], ")") raise Exception path.reverse() # path[0] should be next to start node. self.pathfind_distances[(initial, target)] = path path = self.pathfind_distances[(initial, target)] return path if full_path else path[0]
def find_optimal_path(self, goal=None): """ Pathplanning! Uses navmesh nodes as astar nodes, cost adjusted to match the real cost of the movement (including turns). """ # Define current and goal location loc = self.loc start = self.loc[:2] goal = goal if goal else self.goal end = goal[:2] # For readability and perhaps even speed grid = self.grid tilesize = self.settings.tilesize max_speed = self.settings.max_speed max_turn = self.settings.max_turn # If there is a straight line, just return the end point if not line_intersects_grid(start, end, grid, tilesize): return [goal], 40 # Copy mesh so we can add temp nodes mesh = copy.deepcopy(self.shared_knowledge.mesh) # Add temp nodes for start mesh[start] = dict([(n, point_dist(start, n)) for n in mesh if not line_intersects_grid(start, n, grid, tilesize)]) # Add temp nodes for end: if end not in mesh: endconns = [(n, point_dist(end, n)) for n in mesh if not line_intersects_grid(end, n, grid, tilesize)] for n, dst in endconns: mesh[n][end] = dst # NOTE TO SELF: # We're currently faking that the rotated node is a neighbour # as well by implicitly representing the move to a rotated node # through extra cost neighbours = lambda n: [n2 + (get_angle(n, n2),) for n2 in mesh[n[:2]].keys()] # cost is meshcost + number of steps needed for turn cost = lambda n1, n2: (mesh[n1[:2]][n2[:2]] + abs(int(get_rel_angle(n1, n2) / max_turn))*40) # Goal disregards orientation goal = lambda n: n[:2] == end[:2] # Heuristic, Euclidean + orientation orientation into account? heuristic = lambda n: (((n[0]-end[0])**2 + (n[1]-end[1])**2) ** 0.5 + abs(int(get_rel_angle(n, end) / max_turn))) nodes, length = astar(loc, neighbours, goal, 0, cost, heuristic) return nodes, length
def find_optimal_path(self): ''' Pathplanning! ''' # Define current and goal location loc = self.loc start = self.loc[:2] goal = self.goal end = self.goal[:2] # For readability and perhaps even speed grid = self.grid tilesize = self.settings.tilesize max_speed = self.settings.max_speed max_turn = self.settings.max_turn # If there is a straight line, just return the end point if not line_intersects_grid(loc[:2], goal[:2], grid, tilesize): return [goal] # Copy mesh so we can add temp nodes mesh = copy.deepcopy(self.fieldmarshal.mesh) # Add temp nodes for start mesh[start] = dict([(n, point_dist(start,n)) for n in mesh if not line_intersects_grid(start,n,grid,tilesize)]) # Add temp nodes for end: if end not in mesh: endconns = [(n, point_dist(end,n)) for n in mesh if not line_intersects_grid(end,n,grid,tilesize)] for n, dst in endconns: mesh[n][end] = dst # NOTE TO SELF: # We're currently faking that the rotated node is a neighbour # as well by implicitly representing the cost of its movement # through extra cost neighbours = lambda n: [n2 + (get_angle(n,n2),) for n2 in mesh[n[:2]].keys()] # cost is meshcost + number of steps turns needed cost = lambda n1, n2 : mesh[n1[:2]][n2[:2]] + abs(math.floor(get_rel_angle(n1, n2) / max_turn)) * 40 goal = lambda n: n[:2] == end[:2] heuristic = lambda n: ((n[0]-end[0]) ** 2 + (n[1]-end[1]) ** 2) ** 0.5 nodes, length = astar(loc, neighbours, goal, 0, cost, heuristic) return nodes