/** Generate a new node */ static inline void fpathNewNode(PathfindContext &context, PathCoord dest, PathCoord pos, unsigned prevDist, PathCoord prevPos) { ASSERT((unsigned)pos.x < (unsigned)mapWidth && (unsigned)pos.y < (unsigned)mapHeight, "X (%d) or Y (%d) coordinate for path finding node is out of range!", pos.x, pos.y); // Create the node. PathNode node; unsigned costFactor = context.isDangerous(pos.x, pos.y) ? 5 : 1; node.p = pos; node.dist = prevDist + fpathEstimate(prevPos, pos)*costFactor; node.est = node.dist + fpathEstimate(pos, dest); PathExploredTile &expl = context.map[pos.x + pos.y*mapWidth]; if (expl.iteration == context.iteration && (expl.visited || expl.dist <= node.dist)) { return; // Already visited this tile. Do nothing. } // Remember where we have been, and remember the way back. expl.iteration = context.iteration; expl.dx = pos.x - prevPos.x; expl.dy = pos.y - prevPos.y; expl.dist = node.dist; expl.visited = false; // Add the node to the node heap. context.nodes.push_back(node); // Add the new node to nodes. std::push_heap(context.nodes.begin(), context.nodes.end()); // Move the new node to the right place in the heap. }
/// Recalculates estimates to new tileF tile. static void fpathAStarReestimate(PathfindContext &context, PathCoord tileF) { for (std::vector<PathNode>::iterator node = context.nodes.begin(); node != context.nodes.end(); ++node) { node->est = node->dist + fpathEstimate(node->p, tileF); } // Changing the estimates breaks the heap ordering. Fix the heap ordering. std::make_heap(context.nodes.begin(), context.nodes.end()); }
{ // Cost of moving horizontal/vertical = 70*2, cost of moving diagonal = 99*2, 99/70 = 1.41428571... ≈ √2 = 1.41421356... return iHypot((s.x - f.x)*140, (s.y - f.y)*140); } /** Generate a new node */ static inline void fpathNewNode(PathfindContext &context, PathCoord dest, PathCoord pos, unsigned prevDist, PathCoord prevPos) { ASSERT_OR_RETURN(, (unsigned)pos.x < (unsigned)mapWidth && (unsigned)pos.y < (unsigned)mapHeight, "X (%d) or Y (%d) coordinate for path finding node is out of range!", pos.x, pos.y); // Create the node. PathNode node; unsigned costFactor = context.isDangerous(pos.x, pos.y) ? 5 : context.blockingMap->map[pos.x + pos.y * mapWidth]; node.p = pos; node.dist = prevDist + fpathEstimate(prevPos, pos)*costFactor; node.est = node.dist + fpathGoodEstimate(pos, dest); Vector2i delta = Vector2i(pos.x - prevPos.x, pos.y - prevPos.y)*64; bool isDiagonal = delta.x && delta.y; PathExploredTile &expl = context.map[pos.x + pos.y*mapWidth]; if (expl.iteration == context.iteration) { if (expl.visited) { return; // Already visited this tile. Do nothing. } Vector2i deltaA = delta; Vector2i deltaB = Vector2i(expl.dx, expl.dy); Vector2i deltaDelta = deltaA - deltaB; // Vector pointing from current considered source tile leading to pos, to the previously considered source tile leading to pos.