1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-17 01:32:21 +02:00

Try to reduce amount of time AI spends on pathfinding

This commit is contained in:
Ivan Savenko
2024-12-23 13:26:54 +00:00
parent e035cf9e63
commit 1caab5100a
7 changed files with 59 additions and 33 deletions

View File

@ -97,6 +97,8 @@ void AIGateway::heroMoved(const TryMoveHero & details, bool verbose)
if(!hero) if(!hero)
validateObject(details.id); //enemy hero may have left visible area validateObject(details.id); //enemy hero may have left visible area
nullkiller->invalidatePathfinderData();
const int3 from = hero ? hero->convertToVisitablePos(details.start) : (details.start - int3(0,1,0)); const int3 from = hero ? hero->convertToVisitablePos(details.start) : (details.start - int3(0,1,0));
const int3 to = hero ? hero->convertToVisitablePos(details.end) : (details.end - int3(0,1,0)); const int3 to = hero ? hero->convertToVisitablePos(details.end) : (details.end - int3(0,1,0));
@ -358,6 +360,7 @@ void AIGateway::newObject(const CGObjectInstance * obj)
{ {
LOG_TRACE(logAi); LOG_TRACE(logAi);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
nullkiller->invalidatePathfinderData();
if(obj->isVisitable()) if(obj->isVisitable())
addVisitableObj(obj); addVisitableObj(obj);
} }
@ -582,6 +585,7 @@ void AIGateway::yourTurn(QueryID queryID)
{ {
LOG_TRACE_PARAMS(logAi, "queryID '%i'", queryID); LOG_TRACE_PARAMS(logAi, "queryID '%i'", queryID);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
nullkiller->invalidatePathfinderData();
status.addQuery(queryID, "YourTurn"); status.addQuery(queryID, "YourTurn");
requestActionASAP([=](){ answerQuery(queryID, 0); }); requestActionASAP([=](){ answerQuery(queryID, 0); });
status.startedTurn(); status.startedTurn();

View File

@ -37,6 +37,7 @@ Nullkiller::Nullkiller()
: activeHero(nullptr) : activeHero(nullptr)
, scanDepth(ScanDepth::MAIN_FULL) , scanDepth(ScanDepth::MAIN_FULL)
, useHeroChain(true) , useHeroChain(true)
, pathfinderInvalidated(false)
, memory(std::make_unique<AIMemory>()) , memory(std::make_unique<AIMemory>())
{ {
@ -239,6 +240,11 @@ void Nullkiller::resetAiState()
} }
} }
void Nullkiller::invalidatePathfinderData()
{
pathfinderInvalidated = true;
}
void Nullkiller::updateAiState(int pass, bool fast) void Nullkiller::updateAiState(int pass, bool fast)
{ {
boost::this_thread::interruption_point(); boost::this_thread::interruption_point();
@ -253,7 +259,10 @@ void Nullkiller::updateAiState(int pass, bool fast)
decomposer->reset(); decomposer->reset();
buildAnalyzer->update(); buildAnalyzer->update();
if(!fast) if (!pathfinderInvalidated)
logAi->trace("Skipping paths regeneration - up to date");
if(!fast && pathfinderInvalidated)
{ {
memory->removeInvisibleObjects(cb.get()); memory->removeInvisibleObjects(cb.get());
@ -304,11 +313,13 @@ void Nullkiller::updateAiState(int pass, bool fast)
boost::this_thread::interruption_point(); boost::this_thread::interruption_point();
objectClusterizer->clusterize(); objectClusterizer->clusterize();
pathfinderInvalidated = false;
} }
armyManager->update(); armyManager->update();
logAi->debug("AI state updated in %ld", timeElapsed(start)); logAi->debug("AI state updated in %ld ms", timeElapsed(start));
} }
bool Nullkiller::isHeroLocked(const CGHeroInstance * hero) const bool Nullkiller::isHeroLocked(const CGHeroInstance * hero) const
@ -379,7 +390,7 @@ void Nullkiller::makeTurn()
Goals::TTask bestTask = taskptr(Goals::Invalid()); Goals::TTask bestTask = taskptr(Goals::Invalid());
while(true) for(int j = 1; j <= settings->getMaxPriorityPass() && cb->getPlayerStatus(playerID) == EPlayerStatus::INGAME; j++)
{ {
bestTasks.clear(); bestTasks.clear();

View File

@ -78,6 +78,7 @@ private:
AIGateway * gateway; AIGateway * gateway;
bool openMap; bool openMap;
bool useObjectGraph; bool useObjectGraph;
bool pathfinderInvalidated;
public: public:
static std::unique_ptr<ObjectGraph> baseGraph; static std::unique_ptr<ObjectGraph> baseGraph;
@ -121,6 +122,7 @@ public:
bool isOpenMap() const { return openMap; } bool isOpenMap() const { return openMap; }
bool isObjectGraphAllowed() const { return useObjectGraph; } bool isObjectGraphAllowed() const { return useObjectGraph; }
bool handleTrading(); bool handleTrading();
void invalidatePathfinderData();
private: private:
void resetAiState(); void resetAiState();

View File

@ -32,7 +32,8 @@ namespace NKAI
retreatThresholdRelative(0.3), retreatThresholdRelative(0.3),
retreatThresholdAbsolute(10000), retreatThresholdAbsolute(10000),
safeAttackRatio(1.1), safeAttackRatio(1.1),
maxpass(10), maxPass(10),
maxPriorityPass(10),
pathfinderBucketsCount(1), pathfinderBucketsCount(1),
pathfinderBucketSize(32), pathfinderBucketSize(32),
allowObjectGraph(true), allowObjectGraph(true),
@ -48,7 +49,8 @@ namespace NKAI
maxRoamingHeroes = node["maxRoamingHeroes"].Integer(); maxRoamingHeroes = node["maxRoamingHeroes"].Integer();
mainHeroTurnDistanceLimit = node["mainHeroTurnDistanceLimit"].Integer(); mainHeroTurnDistanceLimit = node["mainHeroTurnDistanceLimit"].Integer();
scoutHeroTurnDistanceLimit = node["scoutHeroTurnDistanceLimit"].Integer(); scoutHeroTurnDistanceLimit = node["scoutHeroTurnDistanceLimit"].Integer();
maxpass = node["maxpass"].Integer(); maxPass = node["maxPass"].Integer();
maxPriorityPass = node["maxPriorityPass"].Integer();
pathfinderBucketsCount = node["pathfinderBucketsCount"].Integer(); pathfinderBucketsCount = node["pathfinderBucketsCount"].Integer();
pathfinderBucketSize = node["pathfinderBucketSize"].Integer(); pathfinderBucketSize = node["pathfinderBucketSize"].Integer();
maxGoldPressure = node["maxGoldPressure"].Float(); maxGoldPressure = node["maxGoldPressure"].Float();

View File

@ -24,7 +24,8 @@ namespace NKAI
int maxRoamingHeroes; int maxRoamingHeroes;
int mainHeroTurnDistanceLimit; int mainHeroTurnDistanceLimit;
int scoutHeroTurnDistanceLimit; int scoutHeroTurnDistanceLimit;
int maxpass; int maxPass;
int maxPriorityPass;
int pathfinderBucketsCount; int pathfinderBucketsCount;
int pathfinderBucketSize; int pathfinderBucketSize;
float maxGoldPressure; float maxGoldPressure;
@ -41,7 +42,8 @@ namespace NKAI
public: public:
explicit Settings(int difficultyLevel); explicit Settings(int difficultyLevel);
int getMaxPass() const { return maxpass; } int getMaxPass() const { return maxPass; }
int getMaxPriorityPass() const { return maxPriorityPass; }
float getMaxGoldPressure() const { return maxGoldPressure; } float getMaxGoldPressure() const { return maxGoldPressure; }
float getRetreatThresholdRelative() const { return retreatThresholdRelative; } float getRetreatThresholdRelative() const { return retreatThresholdRelative; }
float getRetreatThresholdAbsolute() const { return retreatThresholdAbsolute; } float getRetreatThresholdAbsolute() const { return retreatThresholdAbsolute; }

View File

@ -106,7 +106,7 @@ void AIPathfinder::updatePaths(const std::map<const CGHeroInstance *, HeroRole>
if(!pathfinderSettings.useHeroChain) if(!pathfinderSettings.useHeroChain)
{ {
logAi->trace("Recalculated paths in %ld", timeElapsed(start)); logAi->trace("Recalculated paths in %ld ms", timeElapsed(start));
return; return;
} }
@ -141,7 +141,7 @@ void AIPathfinder::updatePaths(const std::map<const CGHeroInstance *, HeroRole>
} }
} while(storage->increaseHeroChainTurnLimit()); } while(storage->increaseHeroChainTurnLimit());
logAi->trace("Recalculated paths in %ld", timeElapsed(start)); logAi->trace("Recalculated paths in %ld ms", timeElapsed(start));
} }
void AIPathfinder::updateGraphs( void AIPathfinder::updateGraphs(

View File

@ -33,17 +33,18 @@
"pawn" : { "pawn" : {
"maxRoamingHeroes" : 4, //H3 value: 3, "maxRoamingHeroes" : 3, //H3 value: 3,
"maxpass" : 30, "maxPass" : 30,
"maxPriorityPass" : 10,
"mainHeroTurnDistanceLimit" : 10, "mainHeroTurnDistanceLimit" : 10,
"scoutHeroTurnDistanceLimit" : 5, "scoutHeroTurnDistanceLimit" : 5,
"maxGoldPressure" : 0.3, "maxGoldPressure" : 0.3,
"updateHitmapOnTileReveal" : false, "updateHitmapOnTileReveal" : false,
"useTroopsFromGarrisons" : true, "useTroopsFromGarrisons" : true,
"openMap": true, "openMap": true,
"allowObjectGraph": false, "allowObjectGraph": true,
"pathfinderBucketsCount" : 1, // old value: 3, "pathfinderBucketsCount" : 4, // old value: 3,
"pathfinderBucketSize" : 32, // old value: 7, "pathfinderBucketSize" : 8, // old value: 7,
"retreatThresholdRelative" : 0, "retreatThresholdRelative" : 0,
"retreatThresholdAbsolute" : 0, "retreatThresholdAbsolute" : 0,
"safeAttackRatio" : 1.1, "safeAttackRatio" : 1.1,
@ -52,17 +53,18 @@
}, },
"knight" : { "knight" : {
"maxRoamingHeroes" : 6, //H3 value: 3, "maxRoamingHeroes" : 3, //H3 value: 3,
"maxpass" : 30, "maxPass" : 30,
"maxPriorityPass" : 10,
"mainHeroTurnDistanceLimit" : 10, "mainHeroTurnDistanceLimit" : 10,
"scoutHeroTurnDistanceLimit" : 5, "scoutHeroTurnDistanceLimit" : 5,
"maxGoldPressure" : 0.3, "maxGoldPressure" : 0.3,
"updateHitmapOnTileReveal" : false, "updateHitmapOnTileReveal" : false,
"useTroopsFromGarrisons" : true, "useTroopsFromGarrisons" : true,
"openMap": true, "openMap": true,
"allowObjectGraph": false, "allowObjectGraph": true,
"pathfinderBucketsCount" : 1, // old value: 3, "pathfinderBucketsCount" : 4, // old value: 3,
"pathfinderBucketSize" : 32, // old value: 7, "pathfinderBucketSize" : 8, // old value: 7,
"retreatThresholdRelative" : 0.1, "retreatThresholdRelative" : 0.1,
"retreatThresholdAbsolute" : 5000, "retreatThresholdAbsolute" : 5000,
"safeAttackRatio" : 1.1, "safeAttackRatio" : 1.1,
@ -71,17 +73,18 @@
}, },
"rook" : { "rook" : {
"maxRoamingHeroes" : 8, //H3 value: 4 "maxRoamingHeroes" : 4, //H3 value: 4
"maxpass" : 30, "maxPass" : 30,
"maxPriorityPass" : 10,
"mainHeroTurnDistanceLimit" : 10, "mainHeroTurnDistanceLimit" : 10,
"scoutHeroTurnDistanceLimit" : 5, "scoutHeroTurnDistanceLimit" : 5,
"maxGoldPressure" : 0.3, "maxGoldPressure" : 0.3,
"updateHitmapOnTileReveal" : false, "updateHitmapOnTileReveal" : false,
"useTroopsFromGarrisons" : true, "useTroopsFromGarrisons" : true,
"openMap": true, "openMap": true,
"allowObjectGraph": false, "allowObjectGraph": true,
"pathfinderBucketsCount" : 1, // old value: 3, "pathfinderBucketsCount" : 4, // old value: 3,
"pathfinderBucketSize" : 32, // old value: 7, "pathfinderBucketSize" : 8, // old value: 7,
"retreatThresholdRelative" : 0.3, "retreatThresholdRelative" : 0.3,
"retreatThresholdAbsolute" : 10000, "retreatThresholdAbsolute" : 10000,
"safeAttackRatio" : 1.1, "safeAttackRatio" : 1.1,
@ -90,17 +93,18 @@
}, },
"queen" : { "queen" : {
"maxRoamingHeroes" : 8, //H3 value: 5 "maxRoamingHeroes" : 6, //H3 value: 5
"maxpass" : 30, "maxPass" : 30,
"maxPriorityPass" : 10,
"mainHeroTurnDistanceLimit" : 10, "mainHeroTurnDistanceLimit" : 10,
"scoutHeroTurnDistanceLimit" : 5, "scoutHeroTurnDistanceLimit" : 5,
"maxGoldPressure" : 0.3, "maxGoldPressure" : 0.3,
"updateHitmapOnTileReveal" : false, "updateHitmapOnTileReveal" : false,
"useTroopsFromGarrisons" : true, "useTroopsFromGarrisons" : true,
"openMap": true, "openMap": true,
"allowObjectGraph": false, "allowObjectGraph": true,
"pathfinderBucketsCount" : 1, // old value: 3, "pathfinderBucketsCount" : 4, // old value: 3,
"pathfinderBucketSize" : 32, // old value: 7, "pathfinderBucketSize" : 8, // old value: 7,
"retreatThresholdRelative" : 0.3, "retreatThresholdRelative" : 0.3,
"retreatThresholdAbsolute" : 10000, "retreatThresholdAbsolute" : 10000,
"safeAttackRatio" : 1.1, "safeAttackRatio" : 1.1,
@ -110,16 +114,17 @@
"king" : { "king" : {
"maxRoamingHeroes" : 8, //H3 value: 6 "maxRoamingHeroes" : 8, //H3 value: 6
"maxpass" : 30, "maxPass" : 30,
"maxPriorityPass" : 10,
"mainHeroTurnDistanceLimit" : 10, "mainHeroTurnDistanceLimit" : 10,
"scoutHeroTurnDistanceLimit" : 5, "scoutHeroTurnDistanceLimit" : 5,
"maxGoldPressure" : 0.3, "maxGoldPressure" : 0.3,
"updateHitmapOnTileReveal" : false, "updateHitmapOnTileReveal" : false,
"useTroopsFromGarrisons" : true, "useTroopsFromGarrisons" : true,
"openMap": true, "openMap": true,
"allowObjectGraph": false, "allowObjectGraph": true,
"pathfinderBucketsCount" : 1, // old value: 3, "pathfinderBucketsCount" : 4, // old value: 3,
"pathfinderBucketSize" : 32, // old value: 7, "pathfinderBucketSize" : 8, // old value: 7,
"retreatThresholdRelative" : 0.3, "retreatThresholdRelative" : 0.3,
"retreatThresholdAbsolute" : 10000, "retreatThresholdAbsolute" : 10000,
"safeAttackRatio" : 1.1, "safeAttackRatio" : 1.1,