mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-21 21:17:49 +02:00
Nullkiller: fix freeze on accessing guarded object
This commit is contained in:
parent
5bfe71c8f3
commit
645c393e25
@ -44,7 +44,7 @@ void DangerHitMapAnalyzer::updateHitMap()
|
|||||||
|
|
||||||
for(auto pair : heroes)
|
for(auto pair : heroes)
|
||||||
{
|
{
|
||||||
ai->pathfinder->updatePaths(pair.second, false);
|
ai->pathfinder->updatePaths(pair.second, PathfinderSettings());
|
||||||
|
|
||||||
foreach_tile_pos([&](const int3 & pos)
|
foreach_tile_pos([&](const int3 & pos)
|
||||||
{
|
{
|
||||||
|
@ -15,13 +15,13 @@ struct HitMapInfo
|
|||||||
{
|
{
|
||||||
uint64_t danger;
|
uint64_t danger;
|
||||||
uint8_t turn;
|
uint8_t turn;
|
||||||
const CGHeroInstance * hero;
|
HeroPtr hero;
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
danger = 0;
|
danger = 0;
|
||||||
turn = 255;
|
turn = 255;
|
||||||
hero = nullptr;
|
hero = HeroPtr();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,6 +25,12 @@ extern boost::thread_specific_ptr<VCAI> ai;
|
|||||||
|
|
||||||
using namespace Goals;
|
using namespace Goals;
|
||||||
|
|
||||||
|
#if AI_TRACE_LEVEL >= 1
|
||||||
|
#define MAXPASS 1000000
|
||||||
|
#else
|
||||||
|
#define MAXPASS 30
|
||||||
|
#endif
|
||||||
|
|
||||||
Nullkiller::Nullkiller()
|
Nullkiller::Nullkiller()
|
||||||
{
|
{
|
||||||
memory.reset(new AIMemory());
|
memory.reset(new AIMemory());
|
||||||
@ -152,7 +158,7 @@ void Nullkiller::resetAiState()
|
|||||||
dangerHitMap->reset();
|
dangerHitMap->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nullkiller::updateAiState()
|
void Nullkiller::updateAiState(int pass)
|
||||||
{
|
{
|
||||||
auto start = boost::chrono::high_resolution_clock::now();
|
auto start = boost::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
@ -174,7 +180,10 @@ void Nullkiller::updateAiState()
|
|||||||
activeHeroes[hero] = heroManager->getHeroRole(hero);
|
activeHeroes[hero] = heroManager->getHeroRole(hero);
|
||||||
}
|
}
|
||||||
|
|
||||||
pathfinder->updatePaths(activeHeroes, true);
|
PathfinderSettings cfg;
|
||||||
|
cfg.useHeroChain = true;
|
||||||
|
|
||||||
|
pathfinder->updatePaths(activeHeroes, cfg);
|
||||||
|
|
||||||
armyManager->update();
|
armyManager->update();
|
||||||
|
|
||||||
@ -226,9 +235,9 @@ void Nullkiller::makeTurn()
|
|||||||
{
|
{
|
||||||
resetAiState();
|
resetAiState();
|
||||||
|
|
||||||
while(true)
|
for(int i = 1; i <= MAXPASS; i++)
|
||||||
{
|
{
|
||||||
updateAiState();
|
updateAiState(i);
|
||||||
|
|
||||||
Goals::TTaskVec bestTasks = {
|
Goals::TTaskVec bestTasks = {
|
||||||
choseBestTask(sptr(BuyArmyBehavior())),
|
choseBestTask(sptr(BuyArmyBehavior())),
|
||||||
|
@ -68,7 +68,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void resetAiState();
|
void resetAiState();
|
||||||
void updateAiState();
|
void updateAiState(int pass);
|
||||||
Goals::TTask choseBestTask(Goals::TSubgoal behavior) const;
|
Goals::TTask choseBestTask(Goals::TSubgoal behavior) const;
|
||||||
Goals::TTask choseBestTask(Goals::TTaskVec & tasks) const;
|
Goals::TTask choseBestTask(Goals::TTaskVec & tasks) const;
|
||||||
};
|
};
|
||||||
|
@ -84,6 +84,7 @@ void AINodeStorage::clear()
|
|||||||
heroChainPass = EHeroChainPass::INITIAL;
|
heroChainPass = EHeroChainPass::INITIAL;
|
||||||
heroChainTurn = 0;
|
heroChainTurn = 0;
|
||||||
heroChainMaxTurns = 1;
|
heroChainMaxTurns = 1;
|
||||||
|
scoutTurnDistanceLimit = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AIPathNode * AINodeStorage::getAINode(const CGPathNode * node) const
|
const AIPathNode * AINodeStorage::getAINode(const CGPathNode * node) const
|
||||||
@ -625,12 +626,12 @@ bool AINodeStorage::isDistanceLimitReached(const PathNodeInfo & source, CDestina
|
|||||||
|
|
||||||
if(heroChainPass == EHeroChainPass::FINAL)
|
if(heroChainPass == EHeroChainPass::FINAL)
|
||||||
{
|
{
|
||||||
if(aiNode->actor->heroRole == HeroRole::SCOUT && destination.node->turns > 3)
|
if(aiNode->actor->heroRole == HeroRole::SCOUT && destination.node->turns > scoutTurnDistanceLimit)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if(heroChainPass == EHeroChainPass::INITIAL)
|
else if(heroChainPass == EHeroChainPass::INITIAL)
|
||||||
{
|
{
|
||||||
if(aiNode->actor->heroRole == HeroRole::SCOUT && destination.node->turns > 5)
|
if(aiNode->actor->heroRole == HeroRole::SCOUT && destination.node->turns > scoutTurnDistanceLimit)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +116,7 @@ private:
|
|||||||
int heroChainTurn;
|
int heroChainTurn;
|
||||||
int heroChainMaxTurns;
|
int heroChainMaxTurns;
|
||||||
PlayerColor playerID;
|
PlayerColor playerID;
|
||||||
|
uint8_t scoutTurnDistanceLimit;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// more than 1 chain layer for each hero allows us to have more than 1 path to each tile so we can chose more optimal one.
|
/// more than 1 chain layer for each hero allows us to have more than 1 path to each tile so we can chose more optimal one.
|
||||||
@ -174,6 +175,7 @@ public:
|
|||||||
std::vector<AIPath> getChainInfo(const int3 & pos, bool isOnLand) const;
|
std::vector<AIPath> getChainInfo(const int3 & pos, bool isOnLand) const;
|
||||||
bool isTileAccessible(const HeroPtr & hero, const int3 & pos, const EPathfindingLayer layer) const;
|
bool isTileAccessible(const HeroPtr & hero, const int3 & pos, const EPathfindingLayer layer) const;
|
||||||
void setHeroes(std::map<const CGHeroInstance *, HeroRole> heroes);
|
void setHeroes(std::map<const CGHeroInstance *, HeroRole> heroes);
|
||||||
|
void setScoutTurnDistanceLimit(uint8_t distanceLimit) { scoutTurnDistanceLimit = distanceLimit; }
|
||||||
void setTownsAndDwellings(
|
void setTownsAndDwellings(
|
||||||
const std::vector<const CGTownInstance *> & towns,
|
const std::vector<const CGTownInstance *> & towns,
|
||||||
const std::set<const CGObjectInstance *> & visitableObjs);
|
const std::set<const CGObjectInstance *> & visitableObjs);
|
||||||
|
@ -42,7 +42,7 @@ std::vector<AIPath> AIPathfinder::getPathInfo(const int3 & tile) const
|
|||||||
return storage->getChainInfo(tile, !tileInfo->isWater());
|
return storage->getChainInfo(tile, !tileInfo->isWater());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AIPathfinder::updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes, bool useHeroChain)
|
void AIPathfinder::updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes, PathfinderSettings pathfinderSettings)
|
||||||
{
|
{
|
||||||
if(!storage)
|
if(!storage)
|
||||||
{
|
{
|
||||||
@ -55,8 +55,9 @@ void AIPathfinder::updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes
|
|||||||
|
|
||||||
storage->clear();
|
storage->clear();
|
||||||
storage->setHeroes(heroes);
|
storage->setHeroes(heroes);
|
||||||
|
storage->setScoutTurnDistanceLimit(pathfinderSettings.scoutTurnDistanceLimit);
|
||||||
|
|
||||||
if(useHeroChain)
|
if(pathfinderSettings.useHeroChain)
|
||||||
{
|
{
|
||||||
storage->setTownsAndDwellings(cb->getTownsInfo(), ai->memory->visitableObjs);
|
storage->setTownsAndDwellings(cb->getTownsInfo(), ai->memory->visitableObjs);
|
||||||
}
|
}
|
||||||
@ -66,7 +67,7 @@ void AIPathfinder::updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes
|
|||||||
logAi->trace("Recalculate paths pass %d", pass++);
|
logAi->trace("Recalculate paths pass %d", pass++);
|
||||||
cb->calculatePaths(config);
|
cb->calculatePaths(config);
|
||||||
|
|
||||||
if(!useHeroChain)
|
if(!pathfinderSettings.useHeroChain)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
do
|
do
|
||||||
|
@ -15,6 +15,17 @@
|
|||||||
|
|
||||||
class Nullkiller;
|
class Nullkiller;
|
||||||
|
|
||||||
|
struct PathfinderSettings
|
||||||
|
{
|
||||||
|
bool useHeroChain;
|
||||||
|
uint8_t scoutTurnDistanceLimit;
|
||||||
|
|
||||||
|
PathfinderSettings()
|
||||||
|
:useHeroChain(false),
|
||||||
|
scoutTurnDistanceLimit(255)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
class AIPathfinder
|
class AIPathfinder
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -26,6 +37,6 @@ public:
|
|||||||
AIPathfinder(CPlayerSpecificInfoCallback * cb, Nullkiller * ai);
|
AIPathfinder(CPlayerSpecificInfoCallback * cb, Nullkiller * ai);
|
||||||
std::vector<AIPath> getPathInfo(const int3 & tile) const;
|
std::vector<AIPath> getPathInfo(const int3 & tile) const;
|
||||||
bool isTileAccessible(const HeroPtr & hero, const int3 & tile) const;
|
bool isTileAccessible(const HeroPtr & hero, const int3 & tile) const;
|
||||||
void updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes, bool useHeroChain = false);
|
void updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes, PathfinderSettings pathfinderSettings);
|
||||||
void init();
|
void init();
|
||||||
};
|
};
|
||||||
|
@ -135,6 +135,13 @@ namespace AIPathfinding
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto danger = nodeStorage->evaluateDanger(destination.coord, nodeStorage->getHero(destination.node), true);
|
||||||
|
|
||||||
|
if(danger)
|
||||||
|
{
|
||||||
|
return bypassBattle(source, destination, pathfinderConfig, pathfinderHelper);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user