# UNDF: UNDF-2026-000001157 # UNDF: UNDF-2026-XXXXXXXXX --- a/engines/crab/PathfindingGrid.cpp +++ b/engines/crab/PathfindingGrid.cpp @@ -27,6 +27,8 @@ #include "crab/PathfindingGrid.h" #include "crab/TMX/TMXMap.h" +#include namespace Crab { @@ -234,21 +236,22 @@ PathfindingGraphNode *PathfindingGrid::getNearestOpenNode(Vector2f nodePos, Vect if (startNode->getMovementCost() > 0) // If the clicked node is open, we're done! return startNode; PathfindingGraphNode *returnNode = nullptr; float shortestDistance = 0.0f; Common::List checkNodes; checkNodes.push_back(startNode); - Common::Array allUsedNodes; - allUsedNodes.push_back(startNode); + // Use an unordered_set for O(1) visited-node lookup instead of O(N) linear + // scan over allUsedNodes on every neighbor check. Without this fix the BFS + // is O(N^2) in the number of grid nodes visited. + std::unordered_set visitedNodes; + visitedNodes.insert(startNode); // Iterate through the nodes, check if they are open then check their distance from the compare point. while (!checkNodes.empty()) { if (checkNodes.front()->getMovementCost() > 0) { float distance = (comparePos - checkNodes.front()->getPosition()).magSqr(); if (shortestDistance == 0.0f || distance) { // If this is the new shortest distance, this becomes the new return. shortestDistance = distance; returnNode = checkNodes.front(); } } else { for (uint i = 0; i < checkNodes.front()->_neighborNodes.size(); ++i) { // If the neighbor hasn't been checked yet, add it to the list to check. - if (Common::find(allUsedNodes.begin(), allUsedNodes.end(), checkNodes.front()->_neighborNodes[i]) == allUsedNodes.end()) { - allUsedNodes.push_back(checkNodes.front()->_neighborNodes[i]); + if (visitedNodes.find(checkNodes.front()->_neighborNodes[i]) == visitedNodes.end()) { + visitedNodes.insert(checkNodes.front()->_neighborNodes[i]); checkNodes.push_back(checkNodes.front()->_neighborNodes[i]); } }