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)
|
||||
{
|
||||
ai->pathfinder->updatePaths(pair.second, false);
|
||||
ai->pathfinder->updatePaths(pair.second, PathfinderSettings());
|
||||
|
||||
foreach_tile_pos([&](const int3 & pos)
|
||||
{
|
||||
|
@ -15,13 +15,13 @@ struct HitMapInfo
|
||||
{
|
||||
uint64_t danger;
|
||||
uint8_t turn;
|
||||
const CGHeroInstance * hero;
|
||||
HeroPtr hero;
|
||||
|
||||
void reset()
|
||||
{
|
||||
danger = 0;
|
||||
turn = 255;
|
||||
hero = nullptr;
|
||||
hero = HeroPtr();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -25,6 +25,12 @@ extern boost::thread_specific_ptr<VCAI> ai;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
#if AI_TRACE_LEVEL >= 1
|
||||
#define MAXPASS 1000000
|
||||
#else
|
||||
#define MAXPASS 30
|
||||
#endif
|
||||
|
||||
Nullkiller::Nullkiller()
|
||||
{
|
||||
memory.reset(new AIMemory());
|
||||
@ -152,7 +158,7 @@ void Nullkiller::resetAiState()
|
||||
dangerHitMap->reset();
|
||||
}
|
||||
|
||||
void Nullkiller::updateAiState()
|
||||
void Nullkiller::updateAiState(int pass)
|
||||
{
|
||||
auto start = boost::chrono::high_resolution_clock::now();
|
||||
|
||||
@ -174,7 +180,10 @@ void Nullkiller::updateAiState()
|
||||
activeHeroes[hero] = heroManager->getHeroRole(hero);
|
||||
}
|
||||
|
||||
pathfinder->updatePaths(activeHeroes, true);
|
||||
PathfinderSettings cfg;
|
||||
cfg.useHeroChain = true;
|
||||
|
||||
pathfinder->updatePaths(activeHeroes, cfg);
|
||||
|
||||
armyManager->update();
|
||||
|
||||
@ -226,9 +235,9 @@ void Nullkiller::makeTurn()
|
||||
{
|
||||
resetAiState();
|
||||
|
||||
while(true)
|
||||
for(int i = 1; i <= MAXPASS; i++)
|
||||
{
|
||||
updateAiState();
|
||||
updateAiState(i);
|
||||
|
||||
Goals::TTaskVec bestTasks = {
|
||||
choseBestTask(sptr(BuyArmyBehavior())),
|
||||
|
@ -68,7 +68,7 @@ public:
|
||||
|
||||
private:
|
||||
void resetAiState();
|
||||
void updateAiState();
|
||||
void updateAiState(int pass);
|
||||
Goals::TTask choseBestTask(Goals::TSubgoal behavior) const;
|
||||
Goals::TTask choseBestTask(Goals::TTaskVec & tasks) const;
|
||||
};
|
||||
|
@ -84,6 +84,7 @@ void AINodeStorage::clear()
|
||||
heroChainPass = EHeroChainPass::INITIAL;
|
||||
heroChainTurn = 0;
|
||||
heroChainMaxTurns = 1;
|
||||
scoutTurnDistanceLimit = 255;
|
||||
}
|
||||
|
||||
const AIPathNode * AINodeStorage::getAINode(const CGPathNode * node) const
|
||||
@ -625,12 +626,12 @@ bool AINodeStorage::isDistanceLimitReached(const PathNodeInfo & source, CDestina
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,7 @@ private:
|
||||
int heroChainTurn;
|
||||
int heroChainMaxTurns;
|
||||
PlayerColor playerID;
|
||||
uint8_t scoutTurnDistanceLimit;
|
||||
|
||||
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.
|
||||
@ -174,6 +175,7 @@ public:
|
||||
std::vector<AIPath> getChainInfo(const int3 & pos, bool isOnLand) const;
|
||||
bool isTileAccessible(const HeroPtr & hero, const int3 & pos, const EPathfindingLayer layer) const;
|
||||
void setHeroes(std::map<const CGHeroInstance *, HeroRole> heroes);
|
||||
void setScoutTurnDistanceLimit(uint8_t distanceLimit) { scoutTurnDistanceLimit = distanceLimit; }
|
||||
void setTownsAndDwellings(
|
||||
const std::vector<const CGTownInstance *> & towns,
|
||||
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());
|
||||
}
|
||||
|
||||
void AIPathfinder::updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes, bool useHeroChain)
|
||||
void AIPathfinder::updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes, PathfinderSettings pathfinderSettings)
|
||||
{
|
||||
if(!storage)
|
||||
{
|
||||
@ -55,8 +55,9 @@ void AIPathfinder::updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes
|
||||
|
||||
storage->clear();
|
||||
storage->setHeroes(heroes);
|
||||
storage->setScoutTurnDistanceLimit(pathfinderSettings.scoutTurnDistanceLimit);
|
||||
|
||||
if(useHeroChain)
|
||||
if(pathfinderSettings.useHeroChain)
|
||||
{
|
||||
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++);
|
||||
cb->calculatePaths(config);
|
||||
|
||||
if(!useHeroChain)
|
||||
if(!pathfinderSettings.useHeroChain)
|
||||
return;
|
||||
|
||||
do
|
||||
|
@ -15,6 +15,17 @@
|
||||
|
||||
class Nullkiller;
|
||||
|
||||
struct PathfinderSettings
|
||||
{
|
||||
bool useHeroChain;
|
||||
uint8_t scoutTurnDistanceLimit;
|
||||
|
||||
PathfinderSettings()
|
||||
:useHeroChain(false),
|
||||
scoutTurnDistanceLimit(255)
|
||||
{ }
|
||||
};
|
||||
|
||||
class AIPathfinder
|
||||
{
|
||||
private:
|
||||
@ -26,6 +37,6 @@ public:
|
||||
AIPathfinder(CPlayerSpecificInfoCallback * cb, Nullkiller * ai);
|
||||
std::vector<AIPath> getPathInfo(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();
|
||||
};
|
||||
|
@ -135,6 +135,13 @@ namespace AIPathfinding
|
||||
return false;
|
||||
}
|
||||
|
||||
auto danger = nodeStorage->evaluateDanger(destination.coord, nodeStorage->getHero(destination.node), true);
|
||||
|
||||
if(danger)
|
||||
{
|
||||
return bypassBattle(source, destination, pathfinderConfig, pathfinderHelper);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user