1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

AI pathfinding calculated in parallel

This commit is contained in:
Andrii Danylchenko 2019-02-09 15:09:21 +02:00
parent 35f696b695
commit 675406589c
11 changed files with 51 additions and 17 deletions

View File

@ -216,6 +216,11 @@ ui64 evaluateDanger(crint3 tile)
}
ui64 evaluateDanger(crint3 tile, const CGHeroInstance * visitor)
{
return evaluateDanger(tile, visitor, cb.get());
}
ui64 evaluateDanger(crint3 tile, const CGHeroInstance * visitor, const CPlayerSpecificInfoCallback * cb)
{
const TerrainTile * t = cb->getTile(tile, false);
if(!t) //we can know about guard but can't check its tile (the edge of fow)

View File

@ -167,6 +167,7 @@ bool isWeeklyRevisitable(const CGObjectInstance * obj);
bool shouldVisit(HeroPtr h, const CGObjectInstance * obj);
ui64 evaluateDanger(const CGObjectInstance * obj);
ui64 evaluateDanger(crint3 tile, const CGHeroInstance * visitor, const CPlayerSpecificInfoCallback * cb);
ui64 evaluateDanger(crint3 tile, const CGHeroInstance * visitor);
bool isObjectRemovable(const CGObjectInstance * obj); //FIXME FIXME: move logic to object property!
bool isSafeToVisit(HeroPtr h, uint64_t dangerStrength);

View File

@ -202,6 +202,8 @@ TacticalAdvantageEngine::TacticalAdvantageEngine()
float TacticalAdvantageEngine::getTacticalAdvantage(const CArmedInstance * we, const CArmedInstance * enemy)
{
boost::unique_lock<boost::mutex> lock(mx);
float output = 1;
try
{

View File

@ -35,6 +35,7 @@ private:
fl::InputVariable * bankPresent;
fl::InputVariable * castleWalls;
fl::OutputVariable * threat;
boost::mutex mx;
};
class HeroMovementGoalEngineBase : public engineBase //in future - maybe derive from some (GoalEngineBase : public engineBase) class for handling non-movement goals with common utility for goal engines

View File

@ -17,9 +17,6 @@
#include "../../../lib/PathfinderUtil.h"
#include "../../../lib/CPlayerState.h"
extern boost::thread_specific_ptr<CCallback> cb;
AINodeStorage::AINodeStorage(const int3 & Sizes)
: sizes(Sizes)
{
@ -187,9 +184,10 @@ std::vector<CGPathNode *> AINodeStorage::calculateNeighbours(
return neighbours;
}
void AINodeStorage::setHero(HeroPtr heroPtr)
void AINodeStorage::setHero(HeroPtr heroPtr, const CPlayerSpecificInfoCallback * _cb)
{
hero = heroPtr.get();
cb = _cb;
}
std::vector<CGPathNode *> AINodeStorage::calculateTeleportations(

View File

@ -59,6 +59,7 @@ private:
/// 1-3 - position on map, 4 - layer (air, water, land), 5 - chain (normal, battle, spellcast and combinations)
boost::multi_array<AIPathNode, 5> nodes;
const CPlayerSpecificInfoCallback * cb;
const CGHeroInstance * hero;
STRONG_INLINE
@ -102,7 +103,7 @@ public:
std::vector<AIPath> getChainInfo(const int3 & pos, bool isOnLand) const;
bool isTileAccessible(const int3 & pos, const EPathfindingLayer layer) const;
void setHero(HeroPtr heroPtr);
void setHero(HeroPtr heroPtr, const CPlayerSpecificInfoCallback * cb);
const CGHeroInstance * getHero() const
{

View File

@ -53,6 +53,15 @@ void AIPathfinder::updatePaths(std::vector<HeroPtr> heroes)
{
storageMap.clear();
auto calculatePaths = [&](const CGHeroInstance * hero, std::shared_ptr<AIPathfinding::AIPathfinderConfig> config)
{
logAi->debug("Recalculate paths for %s", hero->name);
cb->calculatePaths(config, hero);
};
std::vector<Task> calculationTasks;
// TODO: go parallel?
for(HeroPtr hero : heroes)
{
@ -69,12 +78,29 @@ void AIPathfinder::updatePaths(std::vector<HeroPtr> heroes)
}
storageMap[hero] = nodeStorage;
nodeStorage->setHero(hero.get());
nodeStorage->setHero(hero, cb);
auto config = std::make_shared<AIPathfinding::AIPathfinderConfig>(cb, ai, nodeStorage);
logAi->debug("Recalculate paths for %s", hero->name);
cb->calculatePaths(config, hero.get());
calculationTasks.push_back(std::bind(calculatePaths, hero.get(), config));
}
int threadsCount = std::min(
boost::thread::hardware_concurrency(),
(uint32_t)calculationTasks.size());
if(threadsCount == 1)
{
for(auto task : calculationTasks)
{
task();
}
}
else
{
CThreadHelper helper(&calculationTasks, threadsCount);
helper.run();
}
}
@ -95,7 +121,7 @@ void AIPathfinder::updatePaths(const HeroPtr & hero)
}
storageMap[hero] = nodeStorage;
nodeStorage->setHero(hero.get());
nodeStorage->setHero(hero, cb);
}
else
{

View File

@ -28,7 +28,7 @@ namespace AIPathfinding
}
void SummonBoatAction::applyOnDestination(
const HeroPtr & hero,
const CGHeroInstance * hero,
CDestinationNodeInfo & destination,
const PathNodeInfo & source,
AIPathNode * dstMode,
@ -38,7 +38,7 @@ namespace AIPathfinding
dstMode->theNodeBefore = source.node;
}
bool SummonBoatAction::isAffordableBy(const HeroPtr & hero, const AIPathNode * source) const
bool SummonBoatAction::isAffordableBy(const CGHeroInstance * hero, const AIPathNode * source) const
{
#ifdef VCMI_TRACE_PATHFINDER
logAi->trace(
@ -52,7 +52,7 @@ namespace AIPathfinding
return hero->mana >= source->manaCost + getManaCost(hero);
}
uint32_t SummonBoatAction::getManaCost(const HeroPtr & hero) const
uint32_t SummonBoatAction::getManaCost(const CGHeroInstance * hero) const
{
SpellID summonBoat = SpellID::SUMMON_BOAT;

View File

@ -44,16 +44,16 @@ namespace AIPathfinding
virtual Goals::TSubgoal whatToDo(const HeroPtr & hero) const override;
virtual void applyOnDestination(
const HeroPtr & hero,
const CGHeroInstance * hero,
CDestinationNodeInfo & destination,
const PathNodeInfo & source,
AIPathNode * dstMode,
const AIPathNode * srcNode) const override;
bool isAffordableBy(const HeroPtr & hero, const AIPathNode * source) const;
bool isAffordableBy(const CGHeroInstance * hero, const AIPathNode * source) const;
private:
uint32_t getManaCost(const HeroPtr & hero) const;
uint32_t getManaCost(const CGHeroInstance * hero) const;
};
class BuildBoatAction : public VirtualBoatAction

View File

@ -21,7 +21,7 @@ public:
virtual Goals::TSubgoal whatToDo(const HeroPtr & hero) const = 0;
virtual void applyOnDestination(
const HeroPtr & hero,
const CGHeroInstance * hero,
CDestinationNodeInfo & destination,
const PathNodeInfo & source,
AIPathNode * dstMode,

View File

@ -122,7 +122,7 @@ namespace AIPathfinding
}
auto hero = nodeStorage->getHero();
auto danger = evaluateDanger(destination.coord, hero);
auto danger = evaluateDanger(destination.coord, hero, cb);
destination.node = battleNode;
nodeStorage->commit(destination, source);