| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 | 
							- /*
 
-  * AIUtility.h, part of VCMI engine
 
-  *
 
-  * Authors: listed in file AUTHORS in main folder
 
-  *
 
-  * License: GNU General Public License v2.0 or later
 
-  * Full text of license available in license.txt file, in main folder
 
-  *
 
-  */
 
- #pragma once
 
-  // Check windows
 
- #if _WIN32 || _WIN64
 
- #if _WIN64
 
- #define ENVIRONMENT64
 
- #else
 
- #define ENVIRONMENT32
 
- #endif
 
- #endif
 
- // Check GCC
 
- #if __GNUC__
 
- #if __x86_64__ || __ppc64__
 
- #define ENVIRONMENT64
 
- #else
 
- #define ENVIRONMENT32
 
- #endif
 
- #endif
 
- /*********************** TBB.h ********************/
 
- #include "tbb/blocked_range.h"
 
- #include "tbb/concurrent_hash_map.h"
 
- #include "tbb/concurrent_unordered_map.h"
 
- #include "tbb/concurrent_unordered_set.h"
 
- #include "tbb/concurrent_vector.h"
 
- #include "tbb/parallel_for.h"
 
- #include "tbb/parallel_invoke.h"
 
- /*********************** TBB.h ********************/
 
- #include "../../lib/GameLibrary.h"
 
- #include "../../lib/CCreatureHandler.h"
 
- #include "../../lib/spells/CSpellHandler.h"
 
- #include "../../lib/CStopWatch.h"
 
- #include "../../lib/mapObjects/CGHeroInstance.h"
 
- #include "../../CCallback.h"
 
- #include <chrono>
 
- using dwellingContent = std::pair<ui32, std::vector<CreatureID>>;
 
- namespace NKAI
 
- {
 
- struct creInfo;
 
- class AIGateway;
 
- class Nullkiller;
 
- const int GOLD_MINE_PRODUCTION = 1000;
 
- const int WOOD_ORE_MINE_PRODUCTION = 2;
 
- const int RESOURCE_MINE_PRODUCTION = 1;
 
- const int ACTUAL_RESOURCE_COUNT = 7;
 
- extern thread_local CCallback * cb;
 
- enum HeroRole
 
- {
 
- 	SCOUT = 0,
 
- 	MAIN = 1
 
- };
 
- //provisional class for AI to store a reference to an owned hero object
 
- //checks if it's valid on access, should be used in place of const CGHeroInstance*
 
- struct DLL_EXPORT HeroPtr
 
- {
 
- 	const CGHeroInstance * h;
 
- 	ObjectInstanceID hid;
 
- public:
 
- 	std::string name() const;
 
- 	HeroPtr();
 
- 	HeroPtr(const CGHeroInstance * H);
 
- 	~HeroPtr();
 
- 	operator bool() const
 
- 	{
 
- 		return validAndSet();
 
- 	}
 
- 	bool operator<(const HeroPtr & rhs) const;
 
- 	const CGHeroInstance * operator->() const;
 
- 	const CGHeroInstance * operator*() const; //not that consistent with -> but all interfaces use CGHeroInstance*, so it's convenient
 
- 	bool operator==(const HeroPtr & rhs) const;
 
- 	bool operator!=(const HeroPtr & rhs) const
 
- 	{
 
- 		return !(*this == rhs);
 
- 	}
 
- 	const CGHeroInstance * get(bool doWeExpectNull = false) const;
 
- 	const CGHeroInstance * get(const CPlayerSpecificInfoCallback * cb, bool doWeExpectNull = false) const;
 
- 	bool validAndSet() const;
 
- };
 
- enum BattleState
 
- {
 
- 	NO_BATTLE,
 
- 	UPCOMING_BATTLE,
 
- 	ONGOING_BATTLE,
 
- 	ENDING_BATTLE
 
- };
 
- // AI lives in a dangerous world. CGObjectInstances under pointer may got deleted/hidden.
 
- // This class stores object id, so we can detect when we lose access to the underlying object.
 
- struct ObjectIdRef
 
- {
 
- 	ObjectInstanceID id;
 
- 	const CGObjectInstance * operator->() const;
 
- 	operator const CGObjectInstance *() const;
 
- 	operator bool() const;
 
- 	ObjectIdRef(ObjectInstanceID _id);
 
- 	ObjectIdRef(const CGObjectInstance * obj);
 
- 	bool operator<(const ObjectIdRef & rhs) const;
 
- };
 
- template<Obj::Type id>
 
- bool objWithID(const CGObjectInstance * obj)
 
- {
 
- 	return obj->ID == id;
 
- }
 
- struct creInfo
 
- {
 
- 	int count;
 
- 	CreatureID creID;
 
- 	int level;
 
- };
 
- creInfo infoFromDC(const dwellingContent & dc);
 
- template<class Func>
 
- void foreach_tile_pos(const Func & foo)
 
- {
 
- 	// some micro-optimizations since this function gets called a LOT
 
- 	// callback pointer is thread-specific and slow to retrieve -> read map size only once
 
- 	int3 mapSize = cb->getMapSize();
 
- 	for(int z = 0; z < mapSize.z; z++)
 
- 	{
 
- 		for(int x = 0; x < mapSize.x; x++)
 
- 		{
 
- 			for(int y = 0; y < mapSize.y; y++)
 
- 			{
 
- 				foo(int3(x, y, z));
 
- 			}
 
- 		}
 
- 	}
 
- }
 
- template<class Func, class TCallback>
 
- void foreach_tile_pos(TCallback * cbp, const Func & foo) // avoid costly retrieval of thread-specific pointer
 
- {
 
- 	int3 mapSize = cbp->getMapSize();
 
- 	for(int z = 0; z < mapSize.z; z++)
 
- 	{
 
- 		for(int x = 0; x < mapSize.x; x++)
 
- 		{
 
- 			for(int y = 0; y < mapSize.y; y++)
 
- 			{
 
- 				foo(cbp, int3(x, y, z));
 
- 			}
 
- 		}
 
- 	}
 
- }
 
- template<class Func>
 
- void foreach_neighbour(const int3 & pos, const Func & foo)
 
- {
 
- 	CCallback * cbp = cb; // avoid costly retrieval of thread-specific pointer
 
- 	for(const int3 & dir : int3::getDirs())
 
- 	{
 
- 		const int3 n = pos + dir;
 
- 		if(cbp->isInTheMap(n))
 
- 			foo(pos + dir);
 
- 	}
 
- }
 
- template<class Func>
 
- void foreach_neighbour(CCallback * cbp, const int3 & pos, const Func & foo) // avoid costly retrieval of thread-specific pointer
 
- {
 
- 	for(const int3 & dir : int3::getDirs())
 
- 	{
 
- 		const int3 n = pos + dir;
 
- 		if(cbp->isInTheMap(n))
 
- 			foo(cbp, pos + dir);
 
- 	}
 
- }
 
- bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater);
 
- bool isObjectPassable(const Nullkiller * ai, const CGObjectInstance * obj);
 
- bool isObjectPassable(const CGObjectInstance * obj, PlayerColor playerColor, PlayerRelations objectRelations);
 
- bool isBlockVisitObj(const int3 & pos);
 
- bool isWeeklyRevisitable(const Nullkiller * ai, const CGObjectInstance * obj);
 
- bool isObjectRemovable(const CGObjectInstance * obj); //FIXME FIXME: move logic to object property!
 
- bool isSafeToVisit(const CGHeroInstance * h, uint64_t dangerStrength, float safeAttackRatio);
 
- bool isSafeToVisit(const CGHeroInstance * h, const CCreatureSet *, uint64_t dangerStrength, float safeAttackRatio);
 
- bool compareHeroStrength(const CGHeroInstance * h1, const CGHeroInstance * h2);
 
- bool compareArmyStrength(const CArmedInstance * a1, const CArmedInstance * a2);
 
- int64_t getArtifactScoreForHero(const CGHeroInstance * hero, const CArtifactInstance * artifact);
 
- int64_t getPotentialArtifactScore(const CArtifact * art);
 
- bool townHasFreeTavern(const CGTownInstance * town);
 
- uint64_t getHeroArmyStrengthWithCommander(const CGHeroInstance * hero, const CCreatureSet * heroArmy, int fortLevel = 0);
 
- uint64_t timeElapsed(std::chrono::time_point<std::chrono::high_resolution_clock> start);
 
- // todo: move to obj manager
 
- bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObjectInstance * obj);
 
- int getDuplicatingSlots(const CArmedInstance * army);
 
- template <class T>
 
- class SharedPool
 
- {
 
- public:
 
- 	struct External_Deleter
 
- 	{
 
- 		explicit External_Deleter(std::weak_ptr<SharedPool<T>* > pool)
 
- 			: pool(pool)
 
- 		{
 
- 		}
 
- 		void operator()(T * ptr)
 
- 		{
 
- 			std::unique_ptr<T> uptr(ptr);
 
- 			if(auto pool_ptr = pool.lock())
 
- 			{
 
- 				(*pool_ptr.get())->add(std::move(uptr));
 
- 			}
 
- 		}
 
- 	private:
 
- 		std::weak_ptr<SharedPool<T>* > pool;
 
- 	};
 
- public:
 
- 	using ptr_type = std::unique_ptr<T, External_Deleter>;
 
- 	SharedPool(std::function<std::unique_ptr<T>()> elementFactory):
 
- 		elementFactory(elementFactory), pool(), instance_tracker(new SharedPool<T> *(this))
 
- 	{}
 
- 	void add(std::unique_ptr<T> t)
 
- 	{
 
- 		std::lock_guard<std::mutex> lock(sync);
 
- 		pool.push_back(std::move(t));
 
- 	}
 
- 	ptr_type acquire()
 
- 	{
 
- 		std::lock_guard<std::mutex> lock(sync);
 
- 		bool poolIsEmpty = pool.empty();
 
- 		T * element = poolIsEmpty
 
- 			? elementFactory().release()
 
- 			: pool.back().release();
 
- 		ptr_type tmp(
 
- 			element,
 
- 			External_Deleter(std::weak_ptr<SharedPool<T>*>(instance_tracker)));
 
- 		if(!poolIsEmpty) pool.pop_back();
 
- 		return tmp;
 
- 	}
 
- 	bool empty() const
 
- 	{
 
- 		return pool.empty();
 
- 	}
 
- 	size_t size() const
 
- 	{
 
- 		return pool.size();
 
- 	}
 
- private:
 
- 	std::vector<std::unique_ptr<T>> pool;
 
- 	std::function<std::unique_ptr<T>()> elementFactory;
 
- 	std::shared_ptr<SharedPool<T> *> instance_tracker;
 
- 	std::mutex sync;
 
- };
 
- }
 
 
  |