diff --git a/source/glest_game/ai/path_finder.cpp b/source/glest_game/ai/path_finder.cpp index 3a22be01..11b469f1 100644 --- a/source/glest_game/ai/path_finder.cpp +++ b/source/glest_game/ai/path_finder.cpp @@ -39,8 +39,8 @@ namespace Glest{ namespace Game{ const int PathFinder::maxFreeSearchRadius = 10; //const int PathFinder::pathFindNodesMax= 400; -const int PathFinder::pathFindNodesMax = 1500; -const int PathFinder::pathFindRefresh = 10; +const int PathFinder::pathFindNodesMax = 1000; +const int PathFinder::pathFindRefresh = 20; const int PathFinder::pathFindBailoutRadius = 20; @@ -226,8 +226,8 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu // Try to bail out up to PathFinder::pathFindBailoutRadius cells away if(tryRadius > 0) { - for(int bailoutX = -PathFinder::pathFindBailoutRadius; bailoutX >= PathFinder::pathFindBailoutRadius && ts == tsBlocked; ++bailoutX) { - for(int bailoutY = -PathFinder::pathFindBailoutRadius; bailoutY >= PathFinder::pathFindBailoutRadius && ts == tsBlocked; ++bailoutY) { + for(int bailoutX = -PathFinder::pathFindBailoutRadius; bailoutX <= PathFinder::pathFindBailoutRadius && ts == tsBlocked; ++bailoutX) { + for(int bailoutY = -PathFinder::pathFindBailoutRadius; bailoutY <= PathFinder::pathFindBailoutRadius && ts == tsBlocked; ++bailoutY) { const Vec2i newFinalPos = finalPos + Vec2i(bailoutX,bailoutY); bool canUnitMove = map->canMove(unit, unit->getPos(), newFinalPos); @@ -245,7 +245,7 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu } } else { - for(int bailoutX = PathFinder::pathFindBailoutRadius; bailoutX >= -tryRadius && ts == tsBlocked; --bailoutX) { + for(int bailoutX = PathFinder::pathFindBailoutRadius; bailoutX >= -PathFinder::pathFindBailoutRadius && ts == tsBlocked; --bailoutX) { for(int bailoutY = PathFinder::pathFindBailoutRadius; bailoutY >= -PathFinder::pathFindBailoutRadius && ts == tsBlocked; --bailoutY) { const Vec2i newFinalPos = finalPos + Vec2i(bailoutX,bailoutY); bool canUnitMove = map->canMove(unit, unit->getPos(), newFinalPos); @@ -347,10 +347,128 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout openPosList.clear(); closedNodesList.clear(); + TravelState ts = tsImpossible; + const Vec2i unitPos = unit->getPos(); const Vec2i finalPos= computeNearestFreePos(unit, targetPos); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + UnitPathInterface *path= unit->getPath(); + // Check the previous path find cache for the unit to see if its good to + // use + const bool tryLastPathCache = true; + if(tryLastPathCache == true && path != NULL) { + UnitPathBasic *basicPathFinder = dynamic_cast(path); + if(basicPathFinder != NULL && basicPathFinder->getLastPathCacheQueueCount() > 0) { + vector cachedPath= basicPathFinder->getLastPathCacheQueue(); + for(int i = 0; i < cachedPath.size(); ++i) { + Vec2i &pos1 = cachedPath[i]; + // Looking to find if the unit is in one of the cells in the cached path + if(unitPos == pos1) { + // Now see if we can re-use this path to get to the final destination + for(int j = i+1; j < cachedPath.size(); ++j) { + Vec2i &pos2 = cachedPath[j]; + bool canUnitMoveToCell = map->aproxCanMove(unit, pos1, pos2); + if(canUnitMoveToCell == true) { + if(pos2 == finalPos) { + //on the way + ts= tsMoving; + + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + + //store path + basicPathFinder->clear(); + + int pathCount=0; + for(int k=i+1; k <= j; k++) { + if(pathCount < pathFindRefresh) { + basicPathFinder->add(cachedPath[k]); + } + basicPathFinder->addToLastPathCache(cachedPath[k]); + pathCount++; + } + + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) { + char szBuf[4096]=""; + sprintf(szBuf,"[Setting new path for unit] openNodesList.size() [%ld] openPosList.size() [%ld] finalPos [%s] targetPos [%s] inBailout [%d] ts [%d]", + openNodesList.size(),openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts); + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + + if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) { + string commandDesc = "none"; + Command *command= unit->getCurrCommand(); + if(command != NULL && command->getCommandType() != NULL) { + commandDesc = command->getCommandType()->toString(); + } + + char szBuf[1024]=""; + sprintf(szBuf,"State: moving, cmd [%s] pos: %s dest pos: %s, Queue= %d",commandDesc.c_str(),unit->getPos().getString().c_str(), targetPos.getString().c_str(),path->getQueueCount()); + unit->setCurrentUnitTitle(szBuf); + } + + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + + return ts; + //break; + } + else if(j - i > pathFindRefresh) { + //on the way + ts= tsMoving; + + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + + //store path + basicPathFinder->clear(); + + int pathCount=0; + for(int k=i+1; k <= cachedPath.size(); k++) { + if(pathCount < pathFindRefresh) { + basicPathFinder->add(cachedPath[k]); + } + basicPathFinder->addToLastPathCache(cachedPath[k]); + pathCount++; + } + + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) { + char szBuf[4096]=""; + sprintf(szBuf,"[Setting new path for unit] openNodesList.size() [%ld] openPosList.size() [%ld] finalPos [%s] targetPos [%s] inBailout [%d] ts [%d]", + openNodesList.size(),openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts); + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + + if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) { + string commandDesc = "none"; + Command *command= unit->getCurrCommand(); + if(command != NULL && command->getCommandType() != NULL) { + commandDesc = command->getCommandType()->toString(); + } + + char szBuf[1024]=""; + sprintf(szBuf,"State: moving, cmd [%s] pos: %s dest pos: %s, Queue= %d",commandDesc.c_str(),unit->getPos().getString().c_str(), targetPos.getString().c_str(),path->getQueueCount()); + unit->setCurrentUnitTitle(szBuf); + } + + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + + return ts; + } + } + + pos1 = pos2; + } + + break; + } + } + } + } + + //path find algorithm //a) push starting pos into openNodes @@ -362,7 +480,6 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout firstNode->next= NULL; firstNode->prev= NULL; - const Vec2i unitPos = unit->getPos(); firstNode->pos= unitPos; firstNode->heuristic= heuristic(unitPos, finalPos); firstNode->exploredCell= true; @@ -449,8 +566,8 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); //check results of path finding - TravelState ts = tsImpossible; - UnitPathInterface *path= unit->getPath(); + ts = tsImpossible; + //UnitPathInterface *path= unit->getPath(); if(pathFound == false || lastNode == firstNode) { //blocked if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) { @@ -494,10 +611,16 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout //store path path->clear(); + UnitPathBasic *basicPathFinder = dynamic_cast(path); currNode= firstNode; - for(int i=0; currNode->next != NULL && i < pathFindRefresh; currNode= currNode->next, i++) { - path->add(currNode->next->pos); + for(int i=0; currNode->next != NULL; currNode= currNode->next, i++) { + if(i < pathFindRefresh) { + path->add(currNode->next->pos); + } + if(basicPathFinder) { + basicPathFinder->addToLastPathCache(currNode->next->pos); + } } if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index 4192c317..c65d0e91 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -40,6 +40,7 @@ const int UnitPathBasic::maxBlockCount= GameConstants::updateFps / 2; UnitPathBasic::UnitPathBasic() { this->blockCount = 0; this->pathQueue.clear(); + this->lastPathCacheQueue.clear(); } bool UnitPathBasic::isEmpty() const { @@ -56,11 +57,13 @@ bool UnitPathBasic::isStuck() const { void UnitPathBasic::clear() { pathQueue.clear(); + lastPathCacheQueue.clear(); blockCount= 0; } void UnitPathBasic::incBlockCount() { pathQueue.clear(); + lastPathCacheQueue.clear(); blockCount++; } @@ -68,6 +71,10 @@ void UnitPathBasic::add(const Vec2i &path){ pathQueue.push_back(path); } +void UnitPathBasic::addToLastPathCache(const Vec2i &path) { + lastPathCacheQueue.push_back(path); +} + Vec2i UnitPathBasic::pop() { Vec2i p= pathQueue.front(); pathQueue.erase(pathQueue.begin()); @@ -1993,11 +2000,13 @@ void Unit::setLastHarvestResourceTarget(const Vec2i *pos) { } void Unit::addCurrentTargetPathTakenCell(const Vec2i &target,const Vec2i &cell) { +/* if(currentTargetPathTaken.first != target) { currentTargetPathTaken.second.clear(); } currentTargetPathTaken.first = target; currentTargetPathTaken.second.push_back(cell); +*/ } std::string Unit::toString() const { diff --git a/source/glest_game/type_instances/unit.h b/source/glest_game/type_instances/unit.h index d4575b8d..eb0b508e 100644 --- a/source/glest_game/type_instances/unit.h +++ b/source/glest_game/type_instances/unit.h @@ -129,6 +129,7 @@ private: private: int blockCount; vector pathQueue; + vector lastPathCacheQueue; public: UnitPathBasic(); @@ -140,10 +141,14 @@ public: virtual void clearBlockCount() { blockCount = 0; } virtual void incBlockCount(); virtual void add(const Vec2i &path); + void addToLastPathCache(const Vec2i &path); Vec2i pop(); virtual int getBlockCount() const { return blockCount; } virtual int getQueueCount() const { return pathQueue.size(); } + int getLastPathCacheQueueCount() const { return lastPathCacheQueue.size(); } + vector getLastPathCacheQueue() const { return lastPathCacheQueue; } + virtual vector getQueue() const { return pathQueue; } virtual std::string toString() const;