mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	AI pathfinding calculated in parallel
This commit is contained in:
		| @@ -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) | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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 | ||||
| 	{ | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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( | ||||
|   | ||||
| @@ -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 | ||||
| 	{ | ||||
|   | ||||
| @@ -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 | ||||
| 	{ | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user