From 624237ed473f68308b99b178ab933f88d1bd9963 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Sun, 29 Apr 2012 04:45:51 +0000 Subject: [PATCH] - attempt to tweak the pathfinder a bit for performance when units are consistently having a hard time pathfinding we scale back their max cell count used in pathfinding until they have better success in pathfinding --- source/glest_game/ai/path_finder.cpp | 17 +++- source/glest_game/ai/path_finder.h | 94 +++++++++++++---------- source/glest_game/type_instances/unit.cpp | 6 ++ source/glest_game/type_instances/unit.h | 6 ++ 4 files changed, 80 insertions(+), 43 deletions(-) diff --git a/source/glest_game/ai/path_finder.cpp b/source/glest_game/ai/path_finder.cpp index a1edab48..1845f266 100644 --- a/source/glest_game/ai/path_finder.cpp +++ b/source/glest_game/ai/path_finder.cpp @@ -763,7 +763,15 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout if(maxNodeCount < 0) { maxNodeCount = factions[unit->getFactionIndex()].useMaxNodeCount; + + //printf("AStar set maxNodeCount = %d\n",maxNodeCount); } + + if(maxNodeCount >= 1 && unit->getPathfindFailedConsecutiveFrameCount() >= 10) { + maxNodeCount = 200; + //printf("AStar maxpath cut for unit [%d - %s] to %d\n",unit->getId(),unit->getFullName().c_str(), maxNodeCount); + } + UnitPathInterface *path= unit->getPath(); int unitFactionIndex = unit->getFactionIndex(); @@ -1095,9 +1103,16 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout doAStarPathSearch(nodeLimitReached, whileLoopCount, unitFactionIndex, pathFound, node, finalPos, tryJPSPathfinder, - closedNodes, cameFrom, canAddNode, unit, maxNodeCount); + closedNodes, cameFrom, canAddNode, unit, maxNodeCount,frameIndex); // Now see if the unit is eligble for pathfind max nodes boost? + if(nodeLimitReached == true) { + unit->incrementPathfindFailedConsecutiveFrameCount(); + } + else { + unit->resetPathfindFailedConsecutiveFrameCount(); + } + if(nodeLimitReached == true && maxNodeCount != pathFindNodesAbsoluteMax) { if(unit->isLastPathfindFailedFrameWithinCurrentFrameTolerance() == true) { if(frameIndex < 0) { diff --git a/source/glest_game/ai/path_finder.h b/source/glest_game/ai/path_finder.h index 29b530ef..bd9d8fd9 100644 --- a/source/glest_game/ai/path_finder.h +++ b/source/glest_game/ai/path_finder.h @@ -212,8 +212,9 @@ private: bool result = false; Vec2i sucPos= node->pos + Vec2i(i, j); - // std::map > >::iterator iterFind1 = factions[unit->getFactionIndex()].mapFromToNodeList.find(unit->getType()->getId()); - // if(iterFind1 != factions[unit->getFactionIndex()].mapFromToNodeList.end()) { + int unitFactionIndex = unit->getFactionIndex(); + // std::map > >::iterator iterFind1 = factions[unitFactionIndex].mapFromToNodeList.find(unit->getType()->getId()); + // if(iterFind1 != factions[unitFactionIndex].mapFromToNodeList.end()) { // std::map >::iterator iterFind2 = iterFind1->second.find(node->pos); // if(iterFind2 != iterFind1->second.end()) { // std::map::iterator iterFind3 = iterFind2->second.find(sucPos); @@ -226,21 +227,22 @@ private: //bool canUnitMoveToCell = map->aproxCanMove(unit, node->pos, sucPos); //bool canUnitMoveToCell = map->aproxCanMoveSoon(unit, node->pos, sucPos); - if(openPos(sucPos, factions[unit->getFactionIndex()]) == false && + if(openPos(sucPos, factions[unitFactionIndex]) == false && canUnitMoveSoon(unit, node->pos, sucPos) == true) { //if node is not open and canMove then generate another node - Node *sucNode= newNode(factions[unit->getFactionIndex()],maxNodeCount); + Node *sucNode= newNode(factions[unitFactionIndex],maxNodeCount); if(sucNode != NULL) { sucNode->pos= sucPos; sucNode->heuristic= heuristic(sucNode->pos, finalPos); sucNode->prev= node; sucNode->next= NULL; sucNode->exploredCell= map->getSurfaceCell(Map::toSurfCoords(sucPos))->isExplored(unit->getTeam()); - if(factions[unit->getFactionIndex()].openNodesList.find(sucNode->heuristic) == factions[unit->getFactionIndex()].openNodesList.end()) { - factions[unit->getFactionIndex()].openNodesList[sucNode->heuristic].clear(); + if(factions[unitFactionIndex].openNodesList.find(sucNode->heuristic) == factions[unitFactionIndex].openNodesList.end()) { + factions[unitFactionIndex].openNodesList[sucNode->heuristic].clear(); + //factions[unitFactionIndex].openNodesList[sucNode->heuristic].reserve(PathFinder::pathFindNodesMax); } - factions[unit->getFactionIndex()].openNodesList[sucNode->heuristic].push_back(sucNode); - factions[unit->getFactionIndex()].openPosList[sucNode->pos] = true; + factions[unitFactionIndex].openNodesList[sucNode->heuristic].push_back(sucNode); + factions[unitFactionIndex].openPosList[sucNode->pos] = true; result = true; } @@ -249,7 +251,7 @@ private: } } - // factions[unit->getFactionIndex()].mapFromToNodeList[unit->getType()->getId()][node->pos][sucPos] = result; + // factions[unitFactionIndex].mapFromToNodeList[unit->getType()->getId()][node->pos][sucPos] = result; return result; } @@ -307,14 +309,20 @@ private: int & unitFactionIndex, bool & pathFound, Node *& node, const Vec2i & finalPos, const bool tryJPSPathfinder, std::map closedNodes, std::map cameFrom, std::map , - bool> canAddNode, Unit *& unit, int & maxNodeCount) { + bool> canAddNode, Unit *& unit, int & maxNodeCount, int curFrameIndex) { + + Chrono chrono; + //if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); + chrono.start(); + + FactionState &factionState = factions[unitFactionIndex]; while(nodeLimitReached == false) { whileLoopCount++; - if(factions[unitFactionIndex].openNodesList.empty() == true) { + if(factionState.openNodesList.empty() == true) { pathFound = false; break; } - node = minHeuristicFastLookup(factions[unitFactionIndex]); + node = minHeuristicFastLookup(factionState); if(node->pos == finalPos || node->exploredCell == false) { pathFound = true; break; @@ -322,58 +330,54 @@ private: if(tryJPSPathfinder == true) { closedNodes[node->pos] = true; } - if(factions[unitFactionIndex].closedNodesList.find(node->heuristic) == factions[unitFactionIndex].closedNodesList.end()) { - factions[unitFactionIndex].closedNodesList[node->heuristic].clear(); + if(factionState.closedNodesList.find(node->heuristic) == factionState.closedNodesList.end()) { + factionState.closedNodesList[node->heuristic].clear(); + //factionState.closedNodesList[node->heuristic].reserve(PathFinder::pathFindNodesMax); } - factions[unitFactionIndex].closedNodesList[node->heuristic].push_back(node); - factions[unitFactionIndex].openPosList[node->pos] = true; + factionState.closedNodesList[node->heuristic].push_back(node); + factionState.openPosList[node->pos] = true; if(tryJPSPathfinder == true) { astarJPS(cameFrom, node, finalPos, closedNodes, canAddNode, unit, nodeLimitReached, maxNodeCount); } else { - int failureCount = 0; - int cellCount = 0; - int tryDirection = factions[unitFactionIndex].random.randRange(0, 3); - if(tryDirection == 3){ - for(int i = 1;i >= -1 && nodeLimitReached == false;--i){ - for(int j = -1;j <= 1 && nodeLimitReached == false;++j){ - if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false){ + int failureCount = 0; + int cellCount = 0; + int tryDirection = factionState.random.randRange(0, 3); + + if(tryDirection == 3) { + for(int i = 1;i >= -1 && nodeLimitReached == false;--i) { + for(int j = -1;j <= 1 && nodeLimitReached == false;++j) { + if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false) { failureCount++; } cellCount++; } - } - } else if(tryDirection == 2) { - for(int i = -1;i <= 1 && nodeLimitReached == false;++i){ - for(int j = 1;j >= -1 && nodeLimitReached == false;--j){ - if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false){ + for(int i = -1;i <= 1 && nodeLimitReached == false;++i) { + for(int j = 1;j >= -1 && nodeLimitReached == false;--j) { + if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false) { failureCount++; } cellCount++; } - } - } else if(tryDirection == 1) { - for(int i = -1;i <= 1 && nodeLimitReached == false;++i){ - for(int j = -1;j <= 1 && nodeLimitReached == false;++j){ - if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false){ - failureCount++; - } - cellCount++; + for(int i = -1;i <= 1 && nodeLimitReached == false;++i) { + for(int j = -1;j <= 1 && nodeLimitReached == false;++j) { + if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false) { + failureCount++; } - + cellCount++; } - } - else{ - for(int i = 1;i >= -1 && nodeLimitReached == false;--i){ - for(int j = 1;j >= -1 && nodeLimitReached == false;--j){ - if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false){ + } + else { + for(int i = 1;i >= -1 && nodeLimitReached == false;--i) { + for(int j = 1;j >= -1 && nodeLimitReached == false;--j) { + if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false) { failureCount++; } cellCount++; @@ -382,6 +386,12 @@ private: } } } + + //!!! + //if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld nodeLimitReached = %d whileLoopCount = %d nodePoolCount = %d\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),nodeLimitReached,whileLoopCount,factionState.nodePoolCount); + if(chrono.getMillis() > 1) { + printf("AStar for unit [%d - %s] took msecs: %lld nodeLimitReached = %d whileLoopCount = %d nodePoolCount = %d curFrameIndex = %d travel distance = %f\n",unit->getId(),unit->getFullName().c_str(), (long long int)chrono.getMillis(),nodeLimitReached,whileLoopCount,factionState.nodePoolCount,curFrameIndex,unit->getPos().dist(finalPos)); + } } }; diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index c22317df..d5e00702 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -391,6 +391,7 @@ Unit::Unit(int id, UnitPathInterface *unitpath, const Vec2i &pos, lastAttackerUnitId = -1; lastAttackedUnitId = -1; causeOfDeath = ucodNone; + pathfindFailedConsecutiveFrameCount = 0; targetRotationZ=.0f; targetRotationX=.0f; @@ -3772,6 +3773,9 @@ void Unit::saveGame(XmlNode *rootNode) { unitNode->addAttribute("lastAttackedUnitId",intToStr(lastAttackedUnitId), mapTagReplacements); // CauseOfDeathType causeOfDeath; unitNode->addAttribute("causeOfDeath",intToStr(causeOfDeath), mapTagReplacements); + + //pathfindFailedConsecutiveFrameCount + unitNode->addAttribute("pathfindFailedConsecutiveFrameCount",intToStr(pathfindFailedConsecutiveFrameCount), mapTagReplacements); } Unit * Unit::loadGame(const XmlNode *rootNode, GameSettings *settings, Faction *faction, World *world) { @@ -4177,6 +4181,8 @@ Unit * Unit::loadGame(const XmlNode *rootNode, GameSettings *settings, Faction * // CauseOfDeathType causeOfDeath; result->causeOfDeath = static_cast(unitNode->getAttribute("causeOfDeath")->getIntValue()); + result->pathfindFailedConsecutiveFrameCount = unitNode->getAttribute("pathfindFailedConsecutiveFrameCount")->getIntValue(); + if(result->alive) { world->getMapPtr()->putUnitCells(result, newUnitPos); //result->born(); diff --git a/source/glest_game/type_instances/unit.h b/source/glest_game/type_instances/unit.h index 5587331b..3f56cae5 100644 --- a/source/glest_game/type_instances/unit.h +++ b/source/glest_game/type_instances/unit.h @@ -436,6 +436,8 @@ private: int lastAttackedUnitId; CauseOfDeathType causeOfDeath; + uint32 pathfindFailedConsecutiveFrameCount; + public: Unit(int id, UnitPathInterface *path, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing); ~Unit(); @@ -448,6 +450,10 @@ public: const UnitAttackBoostEffectOriginator & getAttackBoostOriginatorEffect() const { return currentAttackBoostOriginatorEffect; } bool unitHasAttackBoost(const AttackBoost *boost, const Unit *source) const; + inline uint32 getPathfindFailedConsecutiveFrameCount() const { return pathfindFailedConsecutiveFrameCount; } + inline void incrementPathfindFailedConsecutiveFrameCount() { pathfindFailedConsecutiveFrameCount++; } + inline void resetPathfindFailedConsecutiveFrameCount() { pathfindFailedConsecutiveFrameCount=0; } + //queries Command *getCurrrentCommandThreadSafe(); void setIgnoreCheckCommand(bool value) { ignoreCheckCommand=value;}