mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	AI goals refactoring (#524)
This commit is contained in:
		
				
					committed by
					
						 ArseniyShestakov
						ArseniyShestakov
					
				
			
			
				
	
			
			
			
						parent
						
							2c1f3dd742
						
					
				
				
					commit
					e1b922f7b8
				
			| @@ -11,6 +11,7 @@ | ||||
| #include "AIUtility.h" | ||||
| #include "VCAI.h" | ||||
| #include "FuzzyHelper.h" | ||||
| #include "Goals/Goals.h" | ||||
|  | ||||
| #include "../../lib/UnlockGuard.h" | ||||
| #include "../../lib/CConfigHandler.h" | ||||
|   | ||||
| @@ -21,7 +21,26 @@ set(VCAI_SRCS | ||||
| 		MapObjectsEvaluator.cpp | ||||
| 		FuzzyEngines.cpp | ||||
| 		FuzzyHelper.cpp | ||||
| 		Goals.cpp | ||||
| 		Goals/AbstractGoal.cpp | ||||
| 		Goals/BuildBoat.cpp | ||||
| 		Goals/Build.cpp | ||||
| 		Goals/BuildThis.cpp | ||||
| 		Goals/Explore.cpp | ||||
| 		Goals/GatherArmy.cpp | ||||
| 		Goals/GatherTroops.cpp | ||||
| 		Goals/BuyArmy.cpp | ||||
| 		Goals/Win.cpp | ||||
| 		Goals/VisitTile.cpp | ||||
| 		Goals/VisitObj.cpp | ||||
| 		Goals/VisitHero.cpp | ||||
| 		Goals/CollectRes.cpp | ||||
| 		Goals/Trade.cpp | ||||
| 		Goals/RecruitHero.cpp | ||||
| 		Goals/Conquer.cpp | ||||
| 		Goals/ClearWayTo.cpp | ||||
| 		Goals/DigAtTile.cpp | ||||
| 		Goals/GetArtOfType.cpp | ||||
| 		Goals/FindObj.cpp | ||||
| 		main.cpp | ||||
| 		VCAI.cpp | ||||
| ) | ||||
| @@ -42,7 +61,29 @@ set(VCAI_HEADERS | ||||
| 		MapObjectsEvaluator.h | ||||
| 		FuzzyEngines.h | ||||
| 		FuzzyHelper.h | ||||
| 		Goals.h | ||||
| 		Goals/AbstractGoal.h | ||||
| 		Goals/CGoal.h | ||||
| 		Goals/Invalid.h | ||||
| 		Goals/BuildBoat.h | ||||
| 		Goals/Build.h | ||||
| 		Goals/BuildThis.h | ||||
| 		Goals/Explore.h | ||||
| 		Goals/GatherArmy.h | ||||
| 		Goals/GatherTroops.h | ||||
| 		Goals/BuyArmy.h | ||||
| 		Goals/Win.h | ||||
| 		Goals/VisitTile.h | ||||
| 		Goals/VisitObj.h | ||||
| 		Goals/VisitHero.h | ||||
| 		Goals/CollectRes.h | ||||
| 		Goals/Trade.h | ||||
| 		Goals/RecruitHero.h | ||||
| 		Goals/Conquer.h | ||||
| 		Goals/ClearWayTo.h | ||||
| 		Goals/DigAtTile.h | ||||
| 		Goals/GetArtOfType.h | ||||
| 		Goals/FindObj.h | ||||
| 		Goals/Goals.h | ||||
| 		VCAI.h | ||||
| ) | ||||
|  | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "FuzzyEngines.h" | ||||
| #include "Goals/Goals.h" | ||||
|  | ||||
| #include "../../lib/mapObjects/MapObjects.h" | ||||
| #include "VCAI.h" | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
| */ | ||||
| #pragma once | ||||
| #include "fl/Headers.h" | ||||
| #include "Goals.h" | ||||
| #include "Goals/AbstractGoal.h" | ||||
|  | ||||
| class CArmedInstance; | ||||
|  | ||||
|   | ||||
| @@ -11,7 +11,7 @@ | ||||
| #include "FuzzyHelper.h" | ||||
|  | ||||
| #include "../../lib/mapObjects/CommonConstructors.h" | ||||
| #include "Goals.h" | ||||
| #include "Goals/Goals.h" | ||||
| #include "VCAI.h" | ||||
|  | ||||
| FuzzyHelper * fh; | ||||
|   | ||||
							
								
								
									
										1663
									
								
								AI/VCAI/Goals.cpp
									
									
									
									
									
								
							
							
						
						
									
										1663
									
								
								AI/VCAI/Goals.cpp
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										698
									
								
								AI/VCAI/Goals.h
									
									
									
									
									
								
							
							
						
						
									
										698
									
								
								AI/VCAI/Goals.h
									
									
									
									
									
								
							| @@ -1,698 +0,0 @@ | ||||
| /* | ||||
|  * Goals.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 | ||||
|  | ||||
| #include "../../lib/VCMI_Lib.h" | ||||
| #include "../../lib/CBuildingHandler.h" | ||||
| #include "../../lib/CCreatureHandler.h" | ||||
| #include "../../lib/CTownHandler.h" | ||||
| #include "AIUtility.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| class AbstractGoal; | ||||
| class VisitTile; | ||||
|  | ||||
| class DLL_EXPORT TSubgoal : public std::shared_ptr<Goals::AbstractGoal> | ||||
| { | ||||
| 	public: | ||||
| 		bool operator==(const TSubgoal & rhs) const; | ||||
| 		bool operator<(const TSubgoal & rhs) const; | ||||
| 	//TODO: serialize? | ||||
| }; | ||||
|  | ||||
| typedef std::vector<TSubgoal> TGoalVec; | ||||
|  | ||||
| enum EGoals | ||||
| { | ||||
| 	INVALID = -1, | ||||
| 	WIN, DO_NOT_LOSE, CONQUER, BUILD, //build needs to get a real reasoning | ||||
| 	EXPLORE, GATHER_ARMY, | ||||
| 	BOOST_HERO, | ||||
| 	RECRUIT_HERO, | ||||
| 	BUILD_STRUCTURE, //if hero set, then in visited town | ||||
| 	COLLECT_RES, | ||||
| 	GATHER_TROOPS, // val of creatures with objid | ||||
|  | ||||
| 	OBJECT_GOALS_BEGIN, | ||||
| 	VISIT_OBJ, //visit or defeat or collect the object | ||||
| 	FIND_OBJ, //find and visit any obj with objid + resid //TODO: consider universal subid for various types (aid, bid) | ||||
| 	VISIT_HERO, //heroes can move around - set goal abstract and track hero every turn | ||||
|  | ||||
| 	GET_ART_TYPE, | ||||
|  | ||||
| 	//BUILD_STRUCTURE, | ||||
| 	ISSUE_COMMAND, | ||||
|  | ||||
| 	VISIT_TILE, //tile, in conjunction with hero elementar; assumes tile is reachable | ||||
| 	CLEAR_WAY_TO, | ||||
| 	DIG_AT_TILE,//elementar with hero on tile | ||||
| 	BUY_ARMY, //at specific town | ||||
| 	TRADE, //val resID at object objid | ||||
| 	BUILD_BOAT | ||||
| }; | ||||
|  | ||||
| 	//method chaining + clone pattern | ||||
| #define VSETTER(type, field) virtual AbstractGoal & set ## field(const type &rhs) {field = rhs; return *this;}; | ||||
| #define OSETTER(type, field) CGoal<T> & set ## field(const type &rhs) override { field = rhs; return *this; }; | ||||
|  | ||||
| #if 0 | ||||
| 	#define SETTER | ||||
| #endif // _DEBUG | ||||
|  | ||||
| enum {LOW_PR = -1}; | ||||
|  | ||||
| DLL_EXPORT TSubgoal sptr(const AbstractGoal & tmp); | ||||
|  | ||||
| struct DLL_EXPORT EvaluationContext | ||||
| { | ||||
| 	uint64_t movementCost; | ||||
| 	int manaCost; | ||||
| 	uint64_t danger; | ||||
|  | ||||
| 	EvaluationContext() | ||||
| 		:movementCost(0), danger(0), manaCost(0) | ||||
| 	{ | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT AbstractGoal | ||||
| { | ||||
| public: | ||||
| 	bool isElementar; VSETTER(bool, isElementar) | ||||
| 	bool isAbstract; VSETTER(bool, isAbstract) | ||||
| 	float priority; VSETTER(float, priority) | ||||
| 	int value; VSETTER(int, value) | ||||
| 	int resID; VSETTER(int, resID) | ||||
| 	int objid; VSETTER(int, objid) | ||||
| 	int aid; VSETTER(int, aid) | ||||
| 	int3 tile; VSETTER(int3, tile) | ||||
| 	HeroPtr hero; VSETTER(HeroPtr, hero) | ||||
| 	const CGTownInstance *town; VSETTER(CGTownInstance *, town) | ||||
| 	int bid; VSETTER(int, bid) | ||||
| 	TSubgoal parent; VSETTER(TSubgoal, parent) | ||||
| 	EvaluationContext evaluationContext; VSETTER(EvaluationContext, evaluationContext) | ||||
|  | ||||
| 	AbstractGoal(EGoals goal = INVALID) | ||||
| 		: goalType (goal), evaluationContext() | ||||
| 	{ | ||||
| 		priority = 0; | ||||
| 		isElementar = false; | ||||
| 		isAbstract = false; | ||||
| 		value = 0; | ||||
| 		aid = -1; | ||||
| 		resID = -1; | ||||
| 		objid = -1; | ||||
| 		tile = int3(-1, -1, -1); | ||||
| 		town = nullptr; | ||||
| 		bid = -1; | ||||
| 	} | ||||
| 	virtual ~AbstractGoal(){} | ||||
| 	//FIXME: abstract goal should be abstract, but serializer fails to instantiate subgoals in such case | ||||
| 	virtual AbstractGoal * clone() const | ||||
| 	{ | ||||
| 		return const_cast<AbstractGoal *>(this); | ||||
| 	} | ||||
| 	virtual TGoalVec getAllPossibleSubgoals() | ||||
| 	{ | ||||
| 		return TGoalVec(); | ||||
| 	} | ||||
| 	virtual TSubgoal whatToDoToAchieve() | ||||
| 	{ | ||||
| 		return sptr(AbstractGoal()); | ||||
| 	} | ||||
|  | ||||
| 	EGoals goalType; | ||||
|  | ||||
| 	virtual std::string name() const; | ||||
| 	virtual std::string completeMessage() const | ||||
| 	{ | ||||
| 		return "This goal is unspecified!"; | ||||
| 	} | ||||
|  | ||||
| 	bool invalid() const; | ||||
|  | ||||
| 	static TSubgoal goVisitOrLookFor(const CGObjectInstance * obj); //if obj is nullptr, then we'll explore | ||||
| 	static TSubgoal lookForArtSmart(int aid); //checks non-standard ways of obtaining art (merchants, quests, etc.) | ||||
|  | ||||
| 	///Visitor pattern | ||||
| 	//TODO: make accept work for std::shared_ptr... somehow | ||||
| 	virtual void accept(VCAI * ai); //unhandled goal will report standard error | ||||
| 	virtual float accept(FuzzyHelper * f); | ||||
|  | ||||
| 	virtual bool operator==(const AbstractGoal & g) const; | ||||
| 	bool operator<(AbstractGoal & g); //final | ||||
| 	virtual bool fulfillsMe(Goals::TSubgoal goal) //TODO: multimethod instead of type check | ||||
| 	{ | ||||
| 		return false; //use this method to check if goal is fulfilled by another (not equal) goal, operator == is handled spearately | ||||
| 	} | ||||
|  | ||||
| 	bool operator!=(const AbstractGoal & g) const | ||||
| 	{ | ||||
| 		return !(*this == g); | ||||
| 	} | ||||
|  | ||||
| 	template<typename Handler> void serialize(Handler & h, const int version) | ||||
| 	{ | ||||
| 		h & goalType; | ||||
| 		h & isElementar; | ||||
| 		h & isAbstract; | ||||
| 		h & priority; | ||||
| 		h & value; | ||||
| 		h & resID; | ||||
| 		h & objid; | ||||
| 		h & aid; | ||||
| 		h & tile; | ||||
| 		h & hero; | ||||
| 		h & town; | ||||
| 		h & bid; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| template<typename T> class DLL_EXPORT CGoal : public AbstractGoal | ||||
| { | ||||
| public: | ||||
| 	CGoal<T>(EGoals goal = INVALID) : AbstractGoal(goal) | ||||
| 	{ | ||||
| 		priority = 0; | ||||
| 		isElementar = false; | ||||
| 		isAbstract = false; | ||||
| 		value = 0; | ||||
| 		aid = -1; | ||||
| 		objid = -1; | ||||
| 		resID = -1; | ||||
| 		tile = int3(-1, -1, -1); | ||||
| 		town = nullptr; | ||||
| 	} | ||||
|  | ||||
| 	OSETTER(bool, isElementar) | ||||
| 	OSETTER(bool, isAbstract) | ||||
| 	OSETTER(float, priority) | ||||
| 	OSETTER(int, value) | ||||
| 	OSETTER(int, resID) | ||||
| 	OSETTER(int, objid) | ||||
| 	OSETTER(int, aid) | ||||
| 	OSETTER(int3, tile) | ||||
| 	OSETTER(HeroPtr, hero) | ||||
| 	OSETTER(CGTownInstance *, town) | ||||
| 	OSETTER(int, bid) | ||||
|  | ||||
| 	void accept(VCAI * ai) override; | ||||
| 	float accept(FuzzyHelper * f) override; | ||||
|  | ||||
| 	CGoal<T> * clone() const override | ||||
| 	{ | ||||
| 		return new T(static_cast<T const &>(*this)); //casting enforces template instantiation | ||||
| 	} | ||||
| 	TSubgoal iAmElementar() | ||||
| 	{ | ||||
| 		setisElementar(true); //FIXME: it's not const-correct, maybe we shoudl only set returned clone? | ||||
| 		TSubgoal ptr; | ||||
| 		ptr.reset(clone()); | ||||
| 		return ptr; | ||||
| 	} | ||||
| 	template<typename Handler> void serialize(Handler & h, const int version) | ||||
| 	{ | ||||
| 		h & static_cast<AbstractGoal &>(*this); | ||||
| 		//h & goalType & isElementar & isAbstract & priority; | ||||
| 		//h & value & resID & objid & aid & tile & hero & town & bid; | ||||
| 	} | ||||
|  | ||||
| 	virtual bool operator==(const AbstractGoal & g) const override | ||||
| 	{ | ||||
| 		if(goalType != g.goalType) | ||||
| 			return false; | ||||
|  | ||||
| 		return (*this) == (dynamic_cast<const T &>(g)); | ||||
| 	} | ||||
|  | ||||
| 	virtual bool operator==(const T & other) const = 0; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT Invalid : public CGoal<Invalid> | ||||
| { | ||||
| public: | ||||
| 	Invalid() | ||||
| 		: CGoal(Goals::INVALID) | ||||
| 	{ | ||||
| 		priority = -1e10; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override | ||||
| 	{ | ||||
| 		return TGoalVec(); | ||||
| 	} | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
|  | ||||
| 	virtual bool operator==(const Invalid & other) const override | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT Win : public CGoal<Win> | ||||
| { | ||||
| public: | ||||
| 	Win() | ||||
| 		: CGoal(Goals::WIN) | ||||
| 	{ | ||||
| 		priority = 100; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override | ||||
| 	{ | ||||
| 		return TGoalVec(); | ||||
| 	} | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
|  | ||||
| 	virtual bool operator==(const Win & other) const override | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT NotLose : public CGoal<NotLose> | ||||
| { | ||||
| public: | ||||
| 	NotLose() | ||||
| 		: CGoal(Goals::DO_NOT_LOSE) | ||||
| 	{ | ||||
| 		priority = 100; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override | ||||
| 	{ | ||||
| 		return TGoalVec(); | ||||
| 	} | ||||
| 	//TSubgoal whatToDoToAchieve() override; | ||||
|  | ||||
| 	virtual bool operator==(const NotLose & other) const override | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT Conquer : public CGoal<Conquer> | ||||
| { | ||||
| public: | ||||
| 	Conquer() | ||||
| 		: CGoal(Goals::CONQUER) | ||||
| 	{ | ||||
| 		priority = 10; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override; | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	virtual bool operator==(const Conquer & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT Build : public CGoal<Build> | ||||
| { | ||||
| public: | ||||
| 	Build() | ||||
| 		: CGoal(Goals::BUILD) | ||||
| 	{ | ||||
| 		priority = 1; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override; | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	bool fulfillsMe(TSubgoal goal) override; | ||||
|  | ||||
| 	virtual bool operator==(const Build & other) const override | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT BuildBoat : public CGoal<BuildBoat> | ||||
| { | ||||
| private: | ||||
| 	const IShipyard * shipyard; | ||||
|  | ||||
| public: | ||||
| 	BuildBoat(const IShipyard * shipyard) | ||||
| 		: CGoal(Goals::BUILD_BOAT), shipyard(shipyard) | ||||
| 	{ | ||||
| 		priority = 0; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override | ||||
| 	{ | ||||
| 		return TGoalVec(); | ||||
| 	} | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	void accept(VCAI * ai) override; | ||||
| 	std::string name() const override; | ||||
| 	std::string completeMessage() const override; | ||||
| 	virtual bool operator==(const BuildBoat & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT Explore : public CGoal<Explore> | ||||
| { | ||||
| public: | ||||
| 	Explore() | ||||
| 		: CGoal(Goals::EXPLORE) | ||||
| 	{ | ||||
| 		priority = 1; | ||||
| 	} | ||||
| 	Explore(HeroPtr h) | ||||
| 		: CGoal(Goals::EXPLORE) | ||||
| 	{ | ||||
| 		hero = h; | ||||
| 		priority = 1; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override; | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	std::string completeMessage() const override; | ||||
| 	bool fulfillsMe(TSubgoal goal) override; | ||||
| 	virtual bool operator==(const Explore & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT GatherArmy : public CGoal<GatherArmy> | ||||
| { | ||||
| public: | ||||
| 	GatherArmy() | ||||
| 		: CGoal(Goals::GATHER_ARMY) | ||||
| 	{ | ||||
| 	} | ||||
| 	GatherArmy(int val) | ||||
| 		: CGoal(Goals::GATHER_ARMY) | ||||
| 	{ | ||||
| 		value = val; | ||||
| 		priority = 2.5; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override; | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	std::string completeMessage() const override; | ||||
| 	virtual bool operator==(const GatherArmy & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT BuyArmy : public CGoal<BuyArmy> | ||||
| { | ||||
| private: | ||||
| 	BuyArmy() | ||||
| 		: CGoal(Goals::BUY_ARMY) | ||||
| 	{} | ||||
| public: | ||||
| 	BuyArmy(const CGTownInstance * Town, int val) | ||||
| 		: CGoal(Goals::BUY_ARMY) | ||||
| 	{ | ||||
| 		town = Town; //where to buy this army | ||||
| 		value = val; //expressed in AI unit strength | ||||
| 		priority = 3;//TODO: evaluate? | ||||
| 	} | ||||
| 	bool fulfillsMe(TSubgoal goal) override; | ||||
|  | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	std::string completeMessage() const override; | ||||
| 	virtual bool operator==(const BuyArmy & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT BoostHero : public CGoal<BoostHero> | ||||
| { | ||||
| public: | ||||
| 	BoostHero() | ||||
| 		: CGoal(Goals::INVALID) | ||||
| 	{ | ||||
| 		priority = -1e10; //TODO | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override | ||||
| 	{ | ||||
| 		return TGoalVec(); | ||||
| 	} | ||||
| 	virtual bool operator==(const BoostHero & other) const override; | ||||
| 	//TSubgoal whatToDoToAchieve() override {return sptr(Invalid());}; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT RecruitHero : public CGoal<RecruitHero> | ||||
| { | ||||
| public: | ||||
| 	RecruitHero() | ||||
| 		: CGoal(Goals::RECRUIT_HERO) | ||||
| 	{ | ||||
| 		priority = 1; | ||||
| 	} | ||||
|  | ||||
| 	TGoalVec getAllPossibleSubgoals() override | ||||
| 	{ | ||||
| 		return TGoalVec(); | ||||
| 	} | ||||
|  | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
|  | ||||
| 	virtual bool operator==(const RecruitHero & other) const override | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT BuildThis : public CGoal<BuildThis> | ||||
| { | ||||
| public: | ||||
| 	BuildThis() //should be private, but unit test uses it | ||||
| 		: CGoal(Goals::BUILD_STRUCTURE) | ||||
| 	{} | ||||
| 	BuildThis(BuildingID Bid, const CGTownInstance * tid) | ||||
| 		: CGoal(Goals::BUILD_STRUCTURE) | ||||
| 	{ | ||||
| 		bid = Bid; | ||||
| 		town = tid; | ||||
| 		priority = 1; | ||||
| 	} | ||||
| 	BuildThis(BuildingID Bid) | ||||
| 		: CGoal(Goals::BUILD_STRUCTURE) | ||||
| 	{ | ||||
| 		bid = Bid; | ||||
| 		priority = 1; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override | ||||
| 	{ | ||||
| 		return TGoalVec(); | ||||
| 	} | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	//bool fulfillsMe(TSubgoal goal) override; | ||||
| 	virtual bool operator==(const BuildThis & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT CollectRes : public CGoal<CollectRes> | ||||
| { | ||||
| public: | ||||
| 	CollectRes() | ||||
| 		: CGoal(Goals::COLLECT_RES) | ||||
| 	{ | ||||
| 	} | ||||
| 	CollectRes(int rid, int val) | ||||
| 		: CGoal(Goals::COLLECT_RES) | ||||
| 	{ | ||||
| 		resID = rid; | ||||
| 		value = val; | ||||
| 		priority = 2; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override; | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	TSubgoal whatToDoToTrade(); | ||||
| 	bool fulfillsMe(TSubgoal goal) override; //TODO: Trade | ||||
| 	virtual bool operator==(const CollectRes & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT Trade : public CGoal<Trade> | ||||
| { | ||||
| public: | ||||
| 	Trade() | ||||
| 		: CGoal(Goals::TRADE) | ||||
| 	{ | ||||
| 	} | ||||
| 	Trade(int rid, int val, int Objid) | ||||
| 		: CGoal(Goals::TRADE) | ||||
| 	{ | ||||
| 		resID = rid; | ||||
| 		value = val; | ||||
| 		objid = Objid; | ||||
| 		priority = 3; //trading is instant, but picking resources is free | ||||
| 	} | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	virtual bool operator==(const Trade & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT GatherTroops : public CGoal<GatherTroops> | ||||
| { | ||||
| public: | ||||
| 	GatherTroops() | ||||
| 		: CGoal(Goals::GATHER_TROOPS) | ||||
| 	{ | ||||
| 		priority = 2; | ||||
| 	} | ||||
| 	GatherTroops(int type, int val) | ||||
| 		: CGoal(Goals::GATHER_TROOPS) | ||||
| 	{ | ||||
| 		objid = type; | ||||
| 		value = val; | ||||
| 		priority = 2; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override; | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	bool fulfillsMe(TSubgoal goal) override; | ||||
| 	virtual bool operator==(const GatherTroops & other) const override; | ||||
|  | ||||
| private: | ||||
| 	int getCreaturesCount(const CArmedInstance * army); | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT VisitObj : public CGoal<VisitObj> //this goal was previously known as GetObj | ||||
| { | ||||
| public: | ||||
| 	VisitObj() = delete; // empty constructor not allowed | ||||
| 	VisitObj(int Objid); | ||||
|  | ||||
| 	TGoalVec getAllPossibleSubgoals() override; | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	bool fulfillsMe(TSubgoal goal) override; | ||||
| 	std::string completeMessage() const override; | ||||
| 	virtual bool operator==(const VisitObj & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT FindObj : public CGoal<FindObj> | ||||
| { | ||||
| public: | ||||
| 	FindObj() {} // empty constructor not allowed | ||||
|  | ||||
| 	FindObj(int ID) | ||||
| 		: CGoal(Goals::FIND_OBJ) | ||||
| 	{ | ||||
| 		objid = ID; | ||||
| 		resID = -1; //subid unspecified | ||||
| 		priority = 1; | ||||
| 	} | ||||
| 	FindObj(int ID, int subID) | ||||
| 		: CGoal(Goals::FIND_OBJ) | ||||
| 	{ | ||||
| 		objid = ID; | ||||
| 		resID = subID; | ||||
| 		priority = 1; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override | ||||
| 	{ | ||||
| 		return TGoalVec(); | ||||
| 	} | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	bool fulfillsMe(TSubgoal goal) override; | ||||
| 	virtual bool operator==(const FindObj & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT VisitHero : public CGoal<VisitHero> | ||||
| { | ||||
| public: | ||||
| 	VisitHero() | ||||
| 		: CGoal(Goals::VISIT_HERO) | ||||
| 	{ | ||||
| 	} | ||||
| 	VisitHero(int hid) | ||||
| 		: CGoal(Goals::VISIT_HERO) | ||||
| 	{ | ||||
| 		objid = hid; | ||||
| 		priority = 4; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override | ||||
| 	{ | ||||
| 		return TGoalVec(); | ||||
| 	} | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	bool fulfillsMe(TSubgoal goal) override; | ||||
| 	std::string completeMessage() const override; | ||||
| 	virtual bool operator==(const VisitHero & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT GetArtOfType : public CGoal<GetArtOfType> | ||||
| { | ||||
| public: | ||||
| 	GetArtOfType() | ||||
| 		: CGoal(Goals::GET_ART_TYPE) | ||||
| 	{ | ||||
| 	} | ||||
| 	GetArtOfType(int type) | ||||
| 		: CGoal(Goals::GET_ART_TYPE) | ||||
| 	{ | ||||
| 		aid = type; | ||||
| 		priority = 2; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override | ||||
| 	{ | ||||
| 		return TGoalVec(); | ||||
| 	} | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	virtual bool operator==(const GetArtOfType & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT VisitTile : public CGoal<VisitTile> | ||||
| 	//tile, in conjunction with hero elementar; assumes tile is reachable | ||||
| { | ||||
| public: | ||||
| 	VisitTile() {} // empty constructor not allowed | ||||
|  | ||||
| 	VisitTile(int3 Tile) | ||||
| 		: CGoal(Goals::VISIT_TILE) | ||||
| 	{ | ||||
| 		tile = Tile; | ||||
| 		priority = 5; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override; | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	std::string completeMessage() const override; | ||||
| 	virtual bool operator==(const VisitTile & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT ClearWayTo : public CGoal<ClearWayTo> | ||||
| { | ||||
| public: | ||||
| 	ClearWayTo() | ||||
| 		: CGoal(Goals::CLEAR_WAY_TO) | ||||
| 	{ | ||||
| 	} | ||||
| 	ClearWayTo(int3 Tile) | ||||
| 		: CGoal(Goals::CLEAR_WAY_TO) | ||||
| 	{ | ||||
| 		tile = Tile; | ||||
| 		priority = 5; | ||||
| 	} | ||||
| 	ClearWayTo(int3 Tile, HeroPtr h) | ||||
| 		: CGoal(Goals::CLEAR_WAY_TO) | ||||
| 	{ | ||||
| 		tile = Tile; | ||||
| 		hero = h; | ||||
| 		priority = 5; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override; | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	bool fulfillsMe(TSubgoal goal) override; | ||||
| 	virtual bool operator==(const ClearWayTo & other) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT DigAtTile : public CGoal<DigAtTile> | ||||
| 	//elementar with hero on tile | ||||
| { | ||||
| public: | ||||
| 	DigAtTile() | ||||
| 		: CGoal(Goals::DIG_AT_TILE) | ||||
| 	{ | ||||
| 	} | ||||
| 	DigAtTile(int3 Tile) | ||||
| 		: CGoal(Goals::DIG_AT_TILE) | ||||
| 	{ | ||||
| 		tile = Tile; | ||||
| 		priority = 20; | ||||
| 	} | ||||
| 	TGoalVec getAllPossibleSubgoals() override | ||||
| 	{ | ||||
| 		return TGoalVec(); | ||||
| 	} | ||||
| 	TSubgoal whatToDoToAchieve() override; | ||||
| 	virtual bool operator==(const DigAtTile & other) const override; | ||||
| }; | ||||
|  | ||||
| } | ||||
							
								
								
									
										192
									
								
								AI/VCAI/Goals/AbstractGoal.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								AI/VCAI/Goals/AbstractGoal.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,192 @@ | ||||
| /* | ||||
| * AbstractGoal.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "AbstractGoal.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../ResourceManager.h" | ||||
| #include "../BuildingManager.h" | ||||
| #include "../../../lib/mapping/CMap.h" //for victory conditions | ||||
| #include "../../../lib/CPathfinder.h" | ||||
| #include "../../../lib/StringConstants.h" | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| TSubgoal Goals::sptr(const AbstractGoal & tmp) | ||||
| { | ||||
| 	TSubgoal ptr; | ||||
| 	ptr.reset(tmp.clone()); | ||||
| 	return ptr; | ||||
| } | ||||
|  | ||||
| std::string AbstractGoal::name() const //TODO: virtualize | ||||
| { | ||||
| 	std::string desc; | ||||
| 	switch(goalType) | ||||
| 	{ | ||||
| 	case INVALID: | ||||
| 		return "INVALID"; | ||||
| 	case WIN: | ||||
| 		return "WIN"; | ||||
| 	case DO_NOT_LOSE: | ||||
| 		return "DO NOT LOOSE"; | ||||
| 	case CONQUER: | ||||
| 		return "CONQUER"; | ||||
| 	case BUILD: | ||||
| 		return "BUILD"; | ||||
| 	case EXPLORE: | ||||
| 		desc = "EXPLORE"; | ||||
| 		break; | ||||
| 	case GATHER_ARMY: | ||||
| 		desc = "GATHER ARMY"; | ||||
| 		break; | ||||
| 	case BUY_ARMY: | ||||
| 		return "BUY ARMY"; | ||||
| 		break; | ||||
| 	case BOOST_HERO: | ||||
| 		desc = "BOOST_HERO (unsupported)"; | ||||
| 		break; | ||||
| 	case RECRUIT_HERO: | ||||
| 		return "RECRUIT HERO"; | ||||
| 	case BUILD_STRUCTURE: | ||||
| 		return "BUILD STRUCTURE"; | ||||
| 	case COLLECT_RES: | ||||
| 		desc = "COLLECT RESOURCE " + GameConstants::RESOURCE_NAMES[resID] + " (" + boost::lexical_cast<std::string>(value) + ")"; | ||||
| 		break; | ||||
| 	case TRADE: | ||||
| 	{ | ||||
| 		auto obj = cb->getObjInstance(ObjectInstanceID(objid)); | ||||
| 		if (obj) | ||||
| 			desc = (boost::format("TRADE %d of %s at %s") % value % GameConstants::RESOURCE_NAMES[resID] % obj->getObjectName()).str(); | ||||
| 	} | ||||
| 	break; | ||||
| 	case GATHER_TROOPS: | ||||
| 		desc = "GATHER TROOPS"; | ||||
| 		break; | ||||
| 	case VISIT_OBJ: | ||||
| 	{ | ||||
| 		auto obj = cb->getObjInstance(ObjectInstanceID(objid)); | ||||
| 		if(obj) | ||||
| 			desc = "GET OBJ " + obj->getObjectName(); | ||||
| 	} | ||||
| 	break; | ||||
| 	case FIND_OBJ: | ||||
| 		desc = "FIND OBJ " + boost::lexical_cast<std::string>(objid); | ||||
| 		break; | ||||
| 	case VISIT_HERO: | ||||
| 	{ | ||||
| 		auto obj = cb->getObjInstance(ObjectInstanceID(objid)); | ||||
| 		if(obj) | ||||
| 			desc = "VISIT HERO " + obj->getObjectName(); | ||||
| 	} | ||||
| 	break; | ||||
| 	case GET_ART_TYPE: | ||||
| 		desc = "GET ARTIFACT OF TYPE " + VLC->arth->artifacts[aid]->Name(); | ||||
| 		break; | ||||
| 	case ISSUE_COMMAND: | ||||
| 		return "ISSUE COMMAND (unsupported)"; | ||||
| 	case VISIT_TILE: | ||||
| 		desc = "VISIT TILE " + tile.toString(); | ||||
| 		break; | ||||
| 	case CLEAR_WAY_TO: | ||||
| 		desc = "CLEAR WAY TO " + tile.toString(); | ||||
| 		break; | ||||
| 	case DIG_AT_TILE: | ||||
| 		desc = "DIG AT TILE " + tile.toString(); | ||||
| 		break; | ||||
| 	default: | ||||
| 		return boost::lexical_cast<std::string>(goalType); | ||||
| 	} | ||||
| 	if(hero.get(true)) //FIXME: used to crash when we lost hero and failed goal | ||||
| 		desc += " (" + hero->name + ")"; | ||||
| 	return desc; | ||||
| } | ||||
|  | ||||
| bool AbstractGoal::operator==(const AbstractGoal & g) const | ||||
| { | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| bool AbstractGoal::operator<(AbstractGoal & g) //for std::unique | ||||
| { | ||||
| 	//TODO: make sure it gets goals consistent with == operator | ||||
| 	if (goalType < g.goalType) | ||||
| 		return true; | ||||
| 	if (goalType > g.goalType) | ||||
| 		return false; | ||||
| 	if (hero < g.hero) | ||||
| 		return true; | ||||
| 	if (hero > g.hero) | ||||
| 		return false; | ||||
| 	if (tile < g.tile) | ||||
| 		return true; | ||||
| 	if (g.tile < tile) | ||||
| 		return false; | ||||
| 	if (objid < g.objid) | ||||
| 		return true; | ||||
| 	if (objid > g.objid) | ||||
| 		return false; | ||||
| 	if (town < g.town) | ||||
| 		return true; | ||||
| 	if (town > g.town) | ||||
| 		return false; | ||||
| 	if (value < g.value) | ||||
| 		return true; | ||||
| 	if (value > g.value) | ||||
| 		return false; | ||||
| 	if (priority < g.priority) | ||||
| 		return true; | ||||
| 	if (priority > g.priority) | ||||
| 		return false; | ||||
| 	if (resID < g.resID) | ||||
| 		return true; | ||||
| 	if (resID > g.resID) | ||||
| 		return false; | ||||
| 	if (bid < g.bid) | ||||
| 		return true; | ||||
| 	if (bid > g.bid) | ||||
| 		return false; | ||||
| 	if (aid < g.aid) | ||||
| 		return true; | ||||
| 	if (aid > g.aid) | ||||
| 		return false; | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| //TODO: find out why the following are not generated automatically on MVS? | ||||
| bool TSubgoal::operator==(const TSubgoal & rhs) const | ||||
| { | ||||
| 	return *get() == *rhs.get(); //comparison for Goals is overloaded, so they don't need to be identical to match | ||||
| } | ||||
|  | ||||
| bool TSubgoal::operator<(const TSubgoal & rhs) const | ||||
| { | ||||
| 	return get() < rhs.get(); //compae by value | ||||
| } | ||||
|  | ||||
| bool AbstractGoal::invalid() const | ||||
| { | ||||
| 	return goalType == EGoals::INVALID; | ||||
| } | ||||
|  | ||||
| void AbstractGoal::accept(VCAI * ai) | ||||
| { | ||||
| 	ai->tryRealize(*this); | ||||
| } | ||||
|  | ||||
| float AbstractGoal::accept(FuzzyHelper * f) | ||||
| { | ||||
| 	return f->evaluate(*this); | ||||
| } | ||||
							
								
								
									
										193
									
								
								AI/VCAI/Goals/AbstractGoal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								AI/VCAI/Goals/AbstractGoal.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,193 @@ | ||||
| /* | ||||
| * AbstractGoal.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 | ||||
|  | ||||
| #include "../../../lib/VCMI_Lib.h" | ||||
| #include "../../../lib/CBuildingHandler.h" | ||||
| #include "../../../lib/CCreatureHandler.h" | ||||
| #include "../../../lib/CTownHandler.h" | ||||
| #include "../AIUtility.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class AbstractGoal; | ||||
| 	class Explore; | ||||
| 	class RecruitHero; | ||||
| 	class VisitTile; | ||||
| 	class VisitObj; | ||||
| 	class VisitHero; | ||||
| 	class BuildThis; | ||||
| 	class DigAtTile; | ||||
| 	class CollectRes; | ||||
| 	class Build; | ||||
| 	class BuyArmy; | ||||
| 	class BuildBoat; | ||||
| 	class GatherArmy; | ||||
| 	class ClearWayTo; | ||||
| 	class Invalid; | ||||
| 	class Trade; | ||||
|  | ||||
| 	class DLL_EXPORT TSubgoal : public std::shared_ptr<AbstractGoal> | ||||
| 	{ | ||||
| 	public: | ||||
| 		bool operator==(const TSubgoal & rhs) const; | ||||
| 		bool operator<(const TSubgoal & rhs) const; | ||||
| 		//TODO: serialize? | ||||
| 	}; | ||||
|  | ||||
| 	typedef std::vector<TSubgoal> TGoalVec; | ||||
|  | ||||
| 	enum EGoals | ||||
| 	{ | ||||
| 		INVALID = -1, | ||||
| 		WIN, DO_NOT_LOSE, CONQUER, BUILD, //build needs to get a real reasoning | ||||
| 		EXPLORE, GATHER_ARMY, | ||||
| 		BOOST_HERO, | ||||
| 		RECRUIT_HERO, | ||||
| 		BUILD_STRUCTURE, //if hero set, then in visited town | ||||
| 		COLLECT_RES, | ||||
| 		GATHER_TROOPS, // val of creatures with objid | ||||
|  | ||||
| 		OBJECT_GOALS_BEGIN, | ||||
| 		VISIT_OBJ, //visit or defeat or collect the object | ||||
| 		FIND_OBJ, //find and visit any obj with objid + resid //TODO: consider universal subid for various types (aid, bid) | ||||
| 		VISIT_HERO, //heroes can move around - set goal abstract and track hero every turn | ||||
|  | ||||
| 		GET_ART_TYPE, | ||||
|  | ||||
| 		//BUILD_STRUCTURE, | ||||
| 		ISSUE_COMMAND, | ||||
|  | ||||
| 		VISIT_TILE, //tile, in conjunction with hero elementar; assumes tile is reachable | ||||
| 		CLEAR_WAY_TO, | ||||
| 		DIG_AT_TILE,//elementar with hero on tile | ||||
| 		BUY_ARMY, //at specific town | ||||
| 		TRADE, //val resID at object objid | ||||
| 		BUILD_BOAT | ||||
| 	}; | ||||
|  | ||||
| 	//method chaining + clone pattern | ||||
| #define VSETTER(type, field) virtual AbstractGoal & set ## field(const type &rhs) {field = rhs; return *this;}; | ||||
| #define OSETTER(type, field) CGoal<T> & set ## field(const type &rhs) override { field = rhs; return *this; }; | ||||
|  | ||||
| #if 0 | ||||
| #define SETTER | ||||
| #endif // _DEBUG | ||||
|  | ||||
| 	enum { LOW_PR = -1 }; | ||||
|  | ||||
| 	DLL_EXPORT TSubgoal sptr(const AbstractGoal & tmp); | ||||
|  | ||||
| 	struct DLL_EXPORT EvaluationContext | ||||
| 	{ | ||||
| 		uint64_t movementCost; | ||||
| 		int manaCost; | ||||
| 		uint64_t danger; | ||||
|  | ||||
| 		EvaluationContext() | ||||
| 			:movementCost(0), danger(0), manaCost(0) | ||||
| 		{ | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	class DLL_EXPORT AbstractGoal | ||||
| 	{ | ||||
| 	public: | ||||
| 		bool isElementar; VSETTER(bool, isElementar) | ||||
| 			bool isAbstract; VSETTER(bool, isAbstract) | ||||
| 			float priority; VSETTER(float, priority) | ||||
| 			int value; VSETTER(int, value) | ||||
| 			int resID; VSETTER(int, resID) | ||||
| 			int objid; VSETTER(int, objid) | ||||
| 			int aid; VSETTER(int, aid) | ||||
| 			int3 tile; VSETTER(int3, tile) | ||||
| 			HeroPtr hero; VSETTER(HeroPtr, hero) | ||||
| 			const CGTownInstance *town; VSETTER(CGTownInstance *, town) | ||||
| 			int bid; VSETTER(int, bid) | ||||
| 			TSubgoal parent; VSETTER(TSubgoal, parent) | ||||
| 			EvaluationContext evaluationContext; VSETTER(EvaluationContext, evaluationContext) | ||||
|  | ||||
| 			AbstractGoal(EGoals goal = EGoals::INVALID) | ||||
| 			: goalType(goal), evaluationContext() | ||||
| 		{ | ||||
| 			priority = 0; | ||||
| 			isElementar = false; | ||||
| 			isAbstract = false; | ||||
| 			value = 0; | ||||
| 			aid = -1; | ||||
| 			resID = -1; | ||||
| 			objid = -1; | ||||
| 			tile = int3(-1, -1, -1); | ||||
| 			town = nullptr; | ||||
| 			bid = -1; | ||||
| 		} | ||||
| 		virtual ~AbstractGoal() {} | ||||
| 		//FIXME: abstract goal should be abstract, but serializer fails to instantiate subgoals in such case | ||||
| 		virtual AbstractGoal * clone() const | ||||
| 		{ | ||||
| 			return const_cast<AbstractGoal *>(this); | ||||
| 		} | ||||
| 		virtual TGoalVec getAllPossibleSubgoals() | ||||
| 		{ | ||||
| 			return TGoalVec(); | ||||
| 		} | ||||
| 		virtual TSubgoal whatToDoToAchieve() | ||||
| 		{ | ||||
| 			return sptr(AbstractGoal()); | ||||
| 		} | ||||
|  | ||||
| 		EGoals goalType; | ||||
|  | ||||
| 		virtual std::string name() const; | ||||
| 		virtual std::string completeMessage() const | ||||
| 		{ | ||||
| 			return "This goal is unspecified!"; | ||||
| 		} | ||||
|  | ||||
| 		bool invalid() const; | ||||
|  | ||||
| 		///Visitor pattern | ||||
| 		//TODO: make accept work for std::shared_ptr... somehow | ||||
| 		virtual void accept(VCAI * ai); //unhandled goal will report standard error | ||||
| 		virtual float accept(FuzzyHelper * f); | ||||
|  | ||||
| 		virtual bool operator==(const AbstractGoal & g) const; | ||||
| 		bool operator<(AbstractGoal & g); //final | ||||
| 		virtual bool fulfillsMe(Goals::TSubgoal goal) //TODO: multimethod instead of type check | ||||
| 		{ | ||||
| 			return false; //use this method to check if goal is fulfilled by another (not equal) goal, operator == is handled spearately | ||||
| 		} | ||||
|  | ||||
| 		bool operator!=(const AbstractGoal & g) const | ||||
| 		{ | ||||
| 			return !(*this == g); | ||||
| 		} | ||||
|  | ||||
| 		template<typename Handler> void serialize(Handler & h, const int version) | ||||
| 		{ | ||||
| 			h & goalType; | ||||
| 			h & isElementar; | ||||
| 			h & isAbstract; | ||||
| 			h & priority; | ||||
| 			h & value; | ||||
| 			h & resID; | ||||
| 			h & objid; | ||||
| 			h & aid; | ||||
| 			h & tile; | ||||
| 			h & hero; | ||||
| 			h & town; | ||||
| 			h & bid; | ||||
| 		} | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										93
									
								
								AI/VCAI/Goals/Build.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								AI/VCAI/Goals/Build.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| /* | ||||
| * Build.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "Build.h" | ||||
| #include "BuildThis.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../ResourceManager.h" | ||||
| #include "../BuildingManager.h" | ||||
| #include "../../../lib/mapping/CMap.h" //for victory conditions | ||||
| #include "../../../lib/CPathfinder.h" | ||||
| #include "../../../lib/StringConstants.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| TGoalVec Build::getAllPossibleSubgoals() | ||||
| { | ||||
| 	TGoalVec ret; | ||||
|  | ||||
| 	for(const CGTownInstance * t : cb->getTownsInfo()) | ||||
| 	{ | ||||
| 		//start fresh with every town | ||||
| 		ai->ah->getBuildingOptions(t); | ||||
| 		auto immediateBuilding = ai->ah->immediateBuilding(); | ||||
| 		auto expensiveBuilding = ai->ah->expensiveBuilding(); | ||||
|  | ||||
| 		//handling for early town development to save money and focus on income | ||||
| 		if(!t->hasBuilt(ai->ah->getMaxPossibleGoldBuilding(t)) && expensiveBuilding.is_initialized()) | ||||
| 		{ | ||||
| 			auto potentialBuilding = expensiveBuilding.get(); | ||||
| 			switch(expensiveBuilding.get().bid) | ||||
| 			{ | ||||
| 			case BuildingID::TOWN_HALL: | ||||
| 			case BuildingID::CITY_HALL: | ||||
| 			case BuildingID::CAPITOL: | ||||
| 			case BuildingID::FORT: | ||||
| 			case BuildingID::CITADEL: | ||||
| 			case BuildingID::CASTLE: | ||||
| 				//If above buildings are next to be bought, but no money... do not buy anything else, try to gather resources for these. Simple but has to suffice for now. | ||||
| 				auto goal = ai->ah->whatToDo(potentialBuilding.price, sptr(BuildThis(potentialBuilding.bid, t).setpriority(2.25))); | ||||
| 				ret.push_back(goal); | ||||
| 				return ret; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if(immediateBuilding.is_initialized()) | ||||
| 		{ | ||||
| 			ret.push_back(sptr(BuildThis(immediateBuilding.get().bid, t).setpriority(2))); //prioritize buildings we can build quick | ||||
| 		} | ||||
| 		else //try build later | ||||
| 		{ | ||||
| 			if(expensiveBuilding.is_initialized()) | ||||
| 			{ | ||||
| 				auto potentialBuilding = expensiveBuilding.get(); //gather resources for any we can't afford | ||||
| 				auto goal = ai->ah->whatToDo(potentialBuilding.price, sptr(BuildThis(potentialBuilding.bid, t).setpriority(0.5))); | ||||
| 				ret.push_back(goal); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if(ret.empty()) | ||||
| 		throw cannotFulfillGoalException("BUILD has been realized as much as possible."); | ||||
| 	else | ||||
| 		return ret; | ||||
| } | ||||
|  | ||||
| TSubgoal Build::whatToDoToAchieve() | ||||
| { | ||||
| 	return fh->chooseSolution(getAllPossibleSubgoals()); | ||||
| } | ||||
|  | ||||
| bool Build::fulfillsMe(TSubgoal goal) | ||||
| { | ||||
| 	if(goal->goalType == BUILD || goal->goalType == BUILD_STRUCTURE) | ||||
| 		return (!town || town == goal->town); //building anything will do, in this town if set | ||||
| 	else | ||||
| 		return false; | ||||
| } | ||||
							
								
								
									
										37
									
								
								AI/VCAI/Goals/Build.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								AI/VCAI/Goals/Build.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| /* | ||||
| * Build.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT Build : public CGoal<Build> | ||||
| 	{ | ||||
| 	public: | ||||
| 		Build() | ||||
| 			: CGoal(Goals::BUILD) | ||||
| 		{ | ||||
| 			priority = 1; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override; | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		bool fulfillsMe(TSubgoal goal) override; | ||||
|  | ||||
| 		virtual bool operator==(const Build & other) const override | ||||
| 		{ | ||||
| 			return true; | ||||
| 		} | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										84
									
								
								AI/VCAI/Goals/BuildBoat.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								AI/VCAI/Goals/BuildBoat.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| /* | ||||
| * BuildBoat.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "BuildBoat.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../../lib/mapping/CMap.h" //for victory conditions | ||||
| #include "../../lib/CPathfinder.h" | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool BuildBoat::operator==(const BuildBoat & other) const | ||||
| { | ||||
| 	return shipyard->o->id == other.shipyard->o->id; | ||||
| } | ||||
|  | ||||
| TSubgoal BuildBoat::whatToDoToAchieve() | ||||
| { | ||||
| 	if(cb->getPlayerRelations(ai->playerID, shipyard->o->tempOwner) == PlayerRelations::ENEMIES) | ||||
| 	{ | ||||
| 		return fh->chooseSolution(ai->ah->howToVisitObj(shipyard->o)); | ||||
| 	} | ||||
|  | ||||
| 	if(shipyard->shipyardStatus() != IShipyard::GOOD) | ||||
| 	{ | ||||
| 		throw cannotFulfillGoalException("Shipyard is busy."); | ||||
| 	} | ||||
|  | ||||
| 	TResources boatCost; | ||||
| 	shipyard->getBoatCost(boatCost); | ||||
|  | ||||
| 	return ai->ah->whatToDo(boatCost, this->iAmElementar()); | ||||
| } | ||||
|  | ||||
| void BuildBoat::accept(VCAI * ai) | ||||
| { | ||||
| 	TResources boatCost; | ||||
| 	shipyard->getBoatCost(boatCost); | ||||
|  | ||||
| 	if(!cb->getResourceAmount().canAfford(boatCost)) | ||||
| 	{ | ||||
| 		throw cannotFulfillGoalException("Can not afford boat"); | ||||
| 	} | ||||
|  | ||||
| 	if(cb->getPlayerRelations(ai->playerID, shipyard->o->tempOwner) == PlayerRelations::ENEMIES) | ||||
| 	{ | ||||
| 		throw cannotFulfillGoalException("Can not build boat in enemy shipyard"); | ||||
| 	} | ||||
|  | ||||
| 	if(shipyard->shipyardStatus() != IShipyard::GOOD) | ||||
| 	{ | ||||
| 		throw cannotFulfillGoalException("Shipyard is busy."); | ||||
| 	} | ||||
|  | ||||
| 	logAi->trace( | ||||
| 		"Building boat at shipyard %s located at %s, estimated boat position %s",  | ||||
| 		shipyard->o->getObjectName(), | ||||
| 		shipyard->o->visitablePos().toString(), | ||||
| 		shipyard->bestLocation().toString()); | ||||
|  | ||||
| 	cb->buildBoat(shipyard); | ||||
| } | ||||
|  | ||||
| std::string BuildBoat::name() const | ||||
| { | ||||
| 	return "BuildBoat"; | ||||
| } | ||||
|  | ||||
| std::string BuildBoat::completeMessage() const | ||||
| { | ||||
| 	return "Boat have been built at " + shipyard->o->visitablePos().toString(); | ||||
| } | ||||
							
								
								
									
										37
									
								
								AI/VCAI/Goals/BuildBoat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								AI/VCAI/Goals/BuildBoat.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| /* | ||||
| * BuildBoat.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT BuildBoat : public CGoal<BuildBoat> | ||||
| 	{ | ||||
| 	private: | ||||
| 		const IShipyard * shipyard; | ||||
|  | ||||
| 	public: | ||||
| 		BuildBoat(const IShipyard * shipyard) | ||||
| 			: CGoal(Goals::BUILD_BOAT), shipyard(shipyard) | ||||
| 		{ | ||||
| 			priority = 0; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override | ||||
| 		{ | ||||
| 			return TGoalVec(); | ||||
| 		} | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		void accept(VCAI * ai) override; | ||||
| 		std::string name() const override; | ||||
| 		std::string completeMessage() const override; | ||||
| 		virtual bool operator==(const BuildBoat & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										74
									
								
								AI/VCAI/Goals/BuildThis.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								AI/VCAI/Goals/BuildThis.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| /* | ||||
| * BuildThis.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "BuildThis.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../ResourceManager.h" | ||||
| #include "../BuildingManager.h" | ||||
| #include "../../../lib/mapping/CMap.h" //for victory conditions | ||||
| #include "../../../lib/CPathfinder.h" | ||||
| #include "../../../lib/StringConstants.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool BuildThis::operator==(const BuildThis & other) const | ||||
| { | ||||
| 	return town == other.town && bid == other.bid; | ||||
| } | ||||
|  | ||||
| TSubgoal BuildThis::whatToDoToAchieve() | ||||
| { | ||||
| 	auto b = BuildingID(bid); | ||||
|  | ||||
| 	// find town if not set | ||||
| 	if(!town && hero) | ||||
| 		town = hero->visitedTown; | ||||
|  | ||||
| 	if(!town) | ||||
| 	{ | ||||
| 		for(const CGTownInstance * t : cb->getTownsInfo()) | ||||
| 		{ | ||||
| 			switch(cb->canBuildStructure(town, b)) | ||||
| 			{ | ||||
| 			case EBuildingState::ALLOWED: | ||||
| 				town = t; | ||||
| 				break; //TODO: look for prerequisites? this is not our reponsibility | ||||
| 			default: | ||||
| 				continue; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if(town) //we have specific town to build this | ||||
| 	{ | ||||
| 		switch(cb->canBuildStructure(town, b)) | ||||
| 		{ | ||||
| 		case EBuildingState::ALLOWED: | ||||
| 		case EBuildingState::NO_RESOURCES: | ||||
| 		{ | ||||
| 			auto res = town->town->buildings.at(BuildingID(bid))->resources; | ||||
| 			return ai->ah->whatToDo(res, iAmElementar()); //realize immediately or gather resources | ||||
| 		} | ||||
| 		break; | ||||
| 		default: | ||||
| 			throw cannotFulfillGoalException("Not possible to build"); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 		throw cannotFulfillGoalException("Cannot find town to build this"); | ||||
| } | ||||
							
								
								
									
										48
									
								
								AI/VCAI/Goals/BuildThis.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								AI/VCAI/Goals/BuildThis.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| /* | ||||
| * BuildThis.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT BuildThis : public CGoal<BuildThis> | ||||
| 	{ | ||||
| 	public: | ||||
| 		BuildThis() //should be private, but unit test uses it | ||||
| 			: CGoal(Goals::BUILD_STRUCTURE) | ||||
| 		{ | ||||
| 		} | ||||
| 		BuildThis(BuildingID Bid, const CGTownInstance * tid) | ||||
| 			: CGoal(Goals::BUILD_STRUCTURE) | ||||
| 		{ | ||||
| 			bid = Bid; | ||||
| 			town = tid; | ||||
| 			priority = 1; | ||||
| 		} | ||||
| 		BuildThis(BuildingID Bid) | ||||
| 			: CGoal(Goals::BUILD_STRUCTURE) | ||||
| 		{ | ||||
| 			bid = Bid; | ||||
| 			priority = 1; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override | ||||
| 		{ | ||||
| 			return TGoalVec(); | ||||
| 		} | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		//bool fulfillsMe(TSubgoal goal) override; | ||||
| 		virtual bool operator==(const BuildThis & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										45
									
								
								AI/VCAI/Goals/BuyArmy.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								AI/VCAI/Goals/BuyArmy.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| /* | ||||
| * BuyArmy.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "BuyArmy.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../../lib/mapObjects/CGTownInstance.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool BuyArmy::operator==(const BuyArmy & other) const | ||||
| { | ||||
| 	return town == other.town && objid == other.objid; | ||||
| } | ||||
|  | ||||
| bool BuyArmy::fulfillsMe(TSubgoal goal) | ||||
| { | ||||
| 	//if (hero && hero != goal->hero) | ||||
| 	//	return false; | ||||
| 	return town == goal->town && goal->value >= value; //can always buy more army | ||||
| } | ||||
| TSubgoal BuyArmy::whatToDoToAchieve() | ||||
| { | ||||
| 	//TODO: calculate the actual cost of units instead | ||||
| 	TResources price; | ||||
| 	price[Res::GOLD] = value * 0.4f; //some approximate value | ||||
| 	return ai->ah->whatToDo(price, iAmElementar()); //buy right now or gather resources | ||||
| } | ||||
|  | ||||
| std::string BuyArmy::completeMessage() const | ||||
| { | ||||
| 	return boost::format("Bought army of value %d in town of %s") % value, town->name; | ||||
| } | ||||
							
								
								
									
										41
									
								
								AI/VCAI/Goals/BuyArmy.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								AI/VCAI/Goals/BuyArmy.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
| * BuyArmy.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT BuyArmy : public CGoal<BuyArmy> | ||||
| 	{ | ||||
| 	private: | ||||
| 		BuyArmy() | ||||
| 			: CGoal(Goals::BUY_ARMY) | ||||
| 		{ | ||||
| 		} | ||||
| 	public: | ||||
| 		BuyArmy(const CGTownInstance * Town, int val) | ||||
| 			: CGoal(Goals::BUY_ARMY) | ||||
| 		{ | ||||
| 			town = Town; //where to buy this army | ||||
| 			value = val; //expressed in AI unit strength | ||||
| 			priority = 3;//TODO: evaluate? | ||||
| 		} | ||||
| 		bool fulfillsMe(TSubgoal goal) override; | ||||
|  | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		std::string completeMessage() const override; | ||||
| 		virtual bool operator==(const BuyArmy & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										87
									
								
								AI/VCAI/Goals/CGoal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								AI/VCAI/Goals/CGoal.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| /* | ||||
| * CGoal.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 | ||||
|  | ||||
| #include "AbstractGoal.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../VCAI.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	template<typename T> class DLL_EXPORT CGoal : public AbstractGoal | ||||
| 	{ | ||||
| 	public: | ||||
| 		CGoal<T>(EGoals goal = INVALID) : AbstractGoal(goal) | ||||
| 		{ | ||||
| 			priority = 0; | ||||
| 			isElementar = false; | ||||
| 			isAbstract = false; | ||||
| 			value = 0; | ||||
| 			aid = -1; | ||||
| 			objid = -1; | ||||
| 			resID = -1; | ||||
| 			tile = int3(-1, -1, -1); | ||||
| 			town = nullptr; | ||||
| 		} | ||||
|  | ||||
| 		OSETTER(bool, isElementar) | ||||
| 		OSETTER(bool, isAbstract) | ||||
| 		OSETTER(float, priority) | ||||
| 		OSETTER(int, value) | ||||
| 		OSETTER(int, resID) | ||||
| 		OSETTER(int, objid) | ||||
| 		OSETTER(int, aid) | ||||
| 		OSETTER(int3, tile) | ||||
| 		OSETTER(HeroPtr, hero) | ||||
| 		OSETTER(CGTownInstance *, town) | ||||
| 		OSETTER(int, bid) | ||||
|  | ||||
| 		void accept(VCAI * ai) override | ||||
| 		{ | ||||
| 			ai->tryRealize(static_cast<T &>(*this)); //casting enforces template instantiation | ||||
| 		} | ||||
|  | ||||
| 		float accept(FuzzyHelper * f) override | ||||
| 		{ | ||||
| 			return f->evaluate(static_cast<T &>(*this)); //casting enforces template instantiation | ||||
| 		} | ||||
|  | ||||
| 		CGoal<T> * clone() const override | ||||
| 		{ | ||||
| 			return new T(static_cast<T const &>(*this)); //casting enforces template instantiation | ||||
| 		} | ||||
| 		TSubgoal iAmElementar() | ||||
| 		{ | ||||
| 			setisElementar(true); //FIXME: it's not const-correct, maybe we shoudl only set returned clone? | ||||
| 			TSubgoal ptr; | ||||
| 			ptr.reset(clone()); | ||||
| 			return ptr; | ||||
| 		} | ||||
| 		template<typename Handler> void serialize(Handler & h, const int version) | ||||
| 		{ | ||||
| 			h & static_cast<AbstractGoal &>(*this); | ||||
| 			//h & goalType & isElementar & isAbstract & priority; | ||||
| 			//h & value & resID & objid & aid & tile & hero & town & bid; | ||||
| 		} | ||||
|  | ||||
| 		virtual bool operator==(const AbstractGoal & g) const override | ||||
| 		{ | ||||
| 			if(goalType != g.goalType) | ||||
| 				return false; | ||||
|  | ||||
| 			return (*this) == (dynamic_cast<const T &>(g)); | ||||
| 		} | ||||
|  | ||||
| 		virtual bool operator==(const T & other) const = 0; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										85
									
								
								AI/VCAI/Goals/ClearWayTo.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								AI/VCAI/Goals/ClearWayTo.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| /* | ||||
| * ClearWayTo.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "ClearWayTo.h" | ||||
| #include "Explore.h" | ||||
| #include "RecruitHero.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../AIhelper.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool ClearWayTo::operator==(const ClearWayTo & other) const | ||||
| { | ||||
| 	return other.hero.h == hero.h && other.tile == tile; | ||||
| } | ||||
|  | ||||
| TSubgoal ClearWayTo::whatToDoToAchieve() | ||||
| { | ||||
| 	assert(cb->isInTheMap(tile)); //set tile | ||||
| 	if(!cb->isVisible(tile)) | ||||
| 	{ | ||||
| 		logAi->error("Clear way should be used with visible tiles!"); | ||||
| 		return sptr(Explore()); | ||||
| 	} | ||||
|  | ||||
| 	return (fh->chooseSolution(getAllPossibleSubgoals())); | ||||
| } | ||||
|  | ||||
| bool ClearWayTo::fulfillsMe(TSubgoal goal) | ||||
| { | ||||
| 	if (goal->goalType == VISIT_TILE) | ||||
| 	{ | ||||
| 		if (!hero || hero == goal->hero) | ||||
| 			return tile == goal->tile; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| TGoalVec ClearWayTo::getAllPossibleSubgoals() | ||||
| { | ||||
| 	TGoalVec ret; | ||||
|  | ||||
| 	std::vector<const CGHeroInstance *> heroes; | ||||
| 	if(hero) | ||||
| 		heroes.push_back(hero.h); | ||||
| 	else | ||||
| 		heroes = cb->getHeroesInfo(); | ||||
|  | ||||
| 	for(auto h : heroes) | ||||
| 	{ | ||||
| 		//TODO: handle clearing way to allied heroes that are blocked | ||||
| 		//if ((hero && hero->visitablePos() == tile && hero == *h) || //we can't free the way ourselves | ||||
| 		//	h->visitablePos() == tile) //we are already on that tile! what does it mean? | ||||
| 		//	continue; | ||||
|  | ||||
| 		//if our hero is trapped, make sure we request clearing the way from OUR perspective | ||||
|  | ||||
| 		vstd::concatenate(ret, ai->ah->howToVisitTile(h, tile)); | ||||
| 	} | ||||
|  | ||||
| 	if(ret.empty() && ai->canRecruitAnyHero()) | ||||
| 		ret.push_back(sptr(RecruitHero())); | ||||
|  | ||||
| 	if(ret.empty()) | ||||
| 	{ | ||||
| 		logAi->warn("There is no known way to clear the way to tile %s", tile.toString()); | ||||
| 		throw goalFulfilledException(sptr(ClearWayTo(tile))); //make sure asigned hero gets unlocked | ||||
| 	} | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
							
								
								
									
										45
									
								
								AI/VCAI/Goals/ClearWayTo.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								AI/VCAI/Goals/ClearWayTo.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| /* | ||||
| * ClearWayTo.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT ClearWayTo : public CGoal<ClearWayTo> | ||||
| 	{ | ||||
| 	public: | ||||
| 		ClearWayTo() | ||||
| 			: CGoal(Goals::CLEAR_WAY_TO) | ||||
| 		{ | ||||
| 		} | ||||
| 		ClearWayTo(int3 Tile) | ||||
| 			: CGoal(Goals::CLEAR_WAY_TO) | ||||
| 		{ | ||||
| 			tile = Tile; | ||||
| 			priority = 5; | ||||
| 		} | ||||
| 		ClearWayTo(int3 Tile, HeroPtr h) | ||||
| 			: CGoal(Goals::CLEAR_WAY_TO) | ||||
| 		{ | ||||
| 			tile = Tile; | ||||
| 			hero = h; | ||||
| 			priority = 5; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override; | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		bool fulfillsMe(TSubgoal goal) override; | ||||
| 		virtual bool operator==(const ClearWayTo & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										208
									
								
								AI/VCAI/Goals/CollectRes.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								AI/VCAI/Goals/CollectRes.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | ||||
| /* | ||||
| * CollectRes.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "Goals.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../ResourceManager.h" | ||||
| #include "../BuildingManager.h" | ||||
| #include "../../../lib/mapping/CMap.h" //for victory conditions | ||||
| #include "../../../lib/CPathfinder.h" | ||||
| #include "../../../lib/StringConstants.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool CollectRes::operator==(const CollectRes & other) const | ||||
| { | ||||
| 	return resID == other.resID; | ||||
| } | ||||
|  | ||||
| TGoalVec CollectRes::getAllPossibleSubgoals() | ||||
| { | ||||
| 	TGoalVec ret; | ||||
|  | ||||
| 	auto givesResource = [this](const CGObjectInstance * obj) -> bool | ||||
| 	{ | ||||
| 		//TODO: move this logic to object side | ||||
| 		//TODO: remember mithril exists | ||||
| 		//TODO: water objects | ||||
| 		//TODO: Creature banks | ||||
|  | ||||
| 		//return false first from once-visitable, before checking if they were even visited | ||||
| 		switch (obj->ID.num) | ||||
| 		{ | ||||
| 		case Obj::TREASURE_CHEST: | ||||
| 			return resID == Res::GOLD; | ||||
| 			break; | ||||
| 		case Obj::RESOURCE: | ||||
| 			return obj->subID == resID; | ||||
| 			break; | ||||
| 		case Obj::MINE: | ||||
| 			return (obj->subID == resID && | ||||
| 				(cb->getPlayerRelations(obj->tempOwner, ai->playerID) == PlayerRelations::ENEMIES)); //don't capture our mines | ||||
| 			break; | ||||
| 		case Obj::CAMPFIRE: | ||||
| 			return true; //contains all resources | ||||
| 			break; | ||||
| 		case Obj::WINDMILL: | ||||
| 			switch (resID) | ||||
| 			{ | ||||
| 			case Res::GOLD: | ||||
| 			case Res::WOOD: | ||||
| 				return false; | ||||
| 			} | ||||
| 			break; | ||||
| 		case Obj::WATER_WHEEL: | ||||
| 			if (resID != Res::GOLD) | ||||
| 				return false; | ||||
| 			break; | ||||
| 		case Obj::MYSTICAL_GARDEN: | ||||
| 			if ((resID != Res::GOLD) && (resID != Res::GEMS)) | ||||
| 				return false; | ||||
| 			break; | ||||
| 		case Obj::LEAN_TO: | ||||
| 		case Obj::WAGON: | ||||
| 			if (resID != Res::GOLD) | ||||
| 				return false; | ||||
| 			break; | ||||
| 		default: | ||||
| 			return false; | ||||
| 			break; | ||||
| 		} | ||||
| 		return !vstd::contains(ai->alreadyVisited, obj); //for weekly / once visitable | ||||
| 	}; | ||||
|  | ||||
| 	std::vector<const CGObjectInstance *> objs; | ||||
| 	for (auto obj : ai->visitableObjs) | ||||
| 	{ | ||||
| 		if (givesResource(obj)) | ||||
| 			objs.push_back(obj); | ||||
| 	} | ||||
| 	for (auto h : cb->getHeroesInfo()) | ||||
| 	{ | ||||
| 		std::vector<const CGObjectInstance *> ourObjs(objs); //copy common objects | ||||
|  | ||||
| 		for (auto obj : ai->reservedHeroesMap[h]) //add objects reserved by this hero | ||||
| 		{ | ||||
| 			if (givesResource(obj)) | ||||
| 				ourObjs.push_back(obj); | ||||
| 		} | ||||
|  | ||||
| 		for (auto obj : ourObjs) | ||||
| 		{ | ||||
| 			auto waysToGo = ai->ah->howToVisitObj(h, ObjectIdRef(obj)); | ||||
|  | ||||
| 			vstd::concatenate(ret, waysToGo); | ||||
| 		} | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| TSubgoal CollectRes::whatToDoToAchieve() | ||||
| { | ||||
| 	auto goals = getAllPossibleSubgoals(); | ||||
| 	auto trade = whatToDoToTrade(); | ||||
| 	if (!trade->invalid()) | ||||
| 		goals.push_back(trade); | ||||
|  | ||||
| 	if (goals.empty()) | ||||
| 		return sptr(Explore()); //we can always do that | ||||
| 	else | ||||
| 		return fh->chooseSolution(goals); //TODO: evaluate trading | ||||
| } | ||||
|  | ||||
| TSubgoal CollectRes::whatToDoToTrade() | ||||
| { | ||||
| 	std::vector<const IMarket *> markets; | ||||
|  | ||||
| 	std::vector<const CGObjectInstance *> visObjs; | ||||
| 	ai->retrieveVisitableObjs(visObjs, true); | ||||
| 	for (const CGObjectInstance * obj : visObjs) | ||||
| 	{ | ||||
| 		if (const IMarket * m = IMarket::castFrom(obj, false)) | ||||
| 		{ | ||||
| 			if (obj->ID == Obj::TOWN && obj->tempOwner == ai->playerID && m->allowsTrade(EMarketMode::RESOURCE_RESOURCE)) | ||||
| 				markets.push_back(m); | ||||
| 			else if (obj->ID == Obj::TRADING_POST) | ||||
| 				markets.push_back(m); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	boost::sort(markets, [](const IMarket * m1, const IMarket * m2) -> bool | ||||
| 	{ | ||||
| 		return m1->getMarketEfficiency() < m2->getMarketEfficiency(); | ||||
| 	}); | ||||
|  | ||||
| 	markets.erase(boost::remove_if(markets, [](const IMarket * market) -> bool | ||||
| 	{ | ||||
| 		if (!(market->o->ID == Obj::TOWN && market->o->tempOwner == ai->playerID)) | ||||
| 		{ | ||||
| 			if (!ai->isAccessible(market->o->visitablePos())) | ||||
| 				return true; | ||||
| 		} | ||||
| 		return false; | ||||
| 	}), markets.end()); | ||||
|  | ||||
| 	if (!markets.size()) | ||||
| 	{ | ||||
| 		for (const CGTownInstance * t : cb->getTownsInfo()) | ||||
| 		{ | ||||
| 			if (cb->canBuildStructure(t, BuildingID::MARKETPLACE) == EBuildingState::ALLOWED) | ||||
| 				return sptr(BuildThis(BuildingID::MARKETPLACE, t).setpriority(2)); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		const IMarket * m = markets.back(); | ||||
| 		//attempt trade at back (best prices) | ||||
| 		int howManyCanWeBuy = 0; | ||||
| 		for (Res::ERes i = Res::WOOD; i <= Res::GOLD; vstd::advance(i, 1)) | ||||
| 		{ | ||||
| 			if (i == resID) | ||||
| 				continue; | ||||
| 			int toGive = -1, toReceive = -1; | ||||
| 			m->getOffer(i, resID, toGive, toReceive, EMarketMode::RESOURCE_RESOURCE); | ||||
| 			assert(toGive > 0 && toReceive > 0); | ||||
| 			howManyCanWeBuy += toReceive * (ai->ah->freeResources()[i] / toGive); | ||||
| 		} | ||||
|  | ||||
| 		if (howManyCanWeBuy >= value) | ||||
| 		{ | ||||
| 			auto backObj = cb->getTopObj(m->o->visitablePos()); //it'll be a hero if we have one there; otherwise marketplace | ||||
| 			assert(backObj); | ||||
| 			auto objid = m->o->id.getNum(); | ||||
| 			if (backObj->tempOwner != ai->playerID) //top object not owned | ||||
| 			{ | ||||
| 				return sptr(VisitObj(objid)); //just go there | ||||
| 			} | ||||
| 			else //either it's our town, or we have hero there | ||||
| 			{ | ||||
| 				return sptr(Trade(resID, value, objid).setisElementar(true)); //we can do this immediately | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return sptr(Invalid()); //cannot trade | ||||
| } | ||||
|  | ||||
| bool CollectRes::fulfillsMe(TSubgoal goal) | ||||
| { | ||||
| 	if (goal->resID == resID) | ||||
| 		if (goal->value >= value) | ||||
| 			return true; | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
							
								
								
									
										40
									
								
								AI/VCAI/Goals/CollectRes.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								AI/VCAI/Goals/CollectRes.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| /* | ||||
| * CollectRes.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT CollectRes : public CGoal<CollectRes> | ||||
| 	{ | ||||
| 	public: | ||||
| 		CollectRes() | ||||
| 			: CGoal(Goals::COLLECT_RES) | ||||
| 		{ | ||||
| 		} | ||||
| 		CollectRes(int rid, int val) | ||||
| 			: CGoal(Goals::COLLECT_RES) | ||||
| 		{ | ||||
| 			resID = rid; | ||||
| 			value = val; | ||||
| 			priority = 2; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override; | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		TSubgoal whatToDoToTrade(); | ||||
| 		bool fulfillsMe(TSubgoal goal) override; //TODO: Trade | ||||
| 		virtual bool operator==(const CollectRes & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										88
									
								
								AI/VCAI/Goals/Conquer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								AI/VCAI/Goals/Conquer.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| /* | ||||
| * Conquer.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "Goals.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../ResourceManager.h" | ||||
| #include "../BuildingManager.h" | ||||
| #include "../../../lib/mapping/CMap.h" //for victory conditions | ||||
| #include "../../../lib/CPathfinder.h" | ||||
| #include "../../../lib/StringConstants.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool Conquer::operator==(const Conquer & other) const | ||||
| { | ||||
| 	return other.hero.h == hero.h; | ||||
| } | ||||
|  | ||||
| TSubgoal Conquer::whatToDoToAchieve() | ||||
| { | ||||
| 	return fh->chooseSolution(getAllPossibleSubgoals()); | ||||
| } | ||||
|  | ||||
| TGoalVec Conquer::getAllPossibleSubgoals() | ||||
| { | ||||
| 	TGoalVec ret; | ||||
|  | ||||
| 	auto conquerable = [](const CGObjectInstance * obj) -> bool | ||||
| 	{ | ||||
| 		if(cb->getPlayerRelations(ai->playerID, obj->tempOwner) == PlayerRelations::ENEMIES) | ||||
| 		{ | ||||
| 			switch(obj->ID.num) | ||||
| 			{ | ||||
| 			case Obj::TOWN: | ||||
| 			case Obj::HERO: | ||||
| 			case Obj::CREATURE_GENERATOR1: | ||||
| 			case Obj::MINE: //TODO: check ai->knownSubterraneanGates | ||||
| 				return true; | ||||
| 			} | ||||
| 		} | ||||
| 		return false; | ||||
| 	}; | ||||
|  | ||||
| 	std::vector<const CGObjectInstance *> objs; | ||||
| 	for(auto obj : ai->visitableObjs) | ||||
| 	{ | ||||
| 		if(conquerable(obj)) | ||||
| 			objs.push_back(obj); | ||||
| 	} | ||||
|  | ||||
| 	for(auto h : cb->getHeroesInfo()) | ||||
| 	{ | ||||
| 		std::vector<const CGObjectInstance *> ourObjs(objs); //copy common objects | ||||
|  | ||||
| 		for(auto obj : ai->reservedHeroesMap[h]) //add objects reserved by this hero | ||||
| 		{ | ||||
| 			if(conquerable(obj)) | ||||
| 				ourObjs.push_back(obj); | ||||
| 		} | ||||
| 		for(auto obj : ourObjs) | ||||
| 		{ | ||||
| 			auto waysToGo = ai->ah->howToVisitObj(h, ObjectIdRef(obj)); | ||||
|  | ||||
| 			vstd::concatenate(ret, waysToGo); | ||||
| 		} | ||||
| 	} | ||||
| 	if(!objs.empty() && ai->canRecruitAnyHero()) //probably no point to recruit hero if we see no objects to capture | ||||
| 		ret.push_back(sptr(RecruitHero())); | ||||
|  | ||||
| 	if(ret.empty()) | ||||
| 		ret.push_back(sptr(Explore())); //we need to find an enemy | ||||
| 	return ret; | ||||
| } | ||||
							
								
								
									
										32
									
								
								AI/VCAI/Goals/Conquer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								AI/VCAI/Goals/Conquer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| /* | ||||
| * Conquer.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT Conquer : public CGoal<Conquer> | ||||
| 	{ | ||||
| 	public: | ||||
| 		Conquer() | ||||
| 			: CGoal(Goals::CONQUER) | ||||
| 		{ | ||||
| 			priority = 10; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override; | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		virtual bool operator==(const Conquer & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										39
									
								
								AI/VCAI/Goals/DigAtTile.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								AI/VCAI/Goals/DigAtTile.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| /* | ||||
| * DigAtTile.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "DigAtTile.h" | ||||
| #include "VisitTile.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool DigAtTile::operator==(const DigAtTile & other) const | ||||
| { | ||||
| 	return other.hero.h == hero.h && other.tile == tile; | ||||
| } | ||||
|  | ||||
| TSubgoal DigAtTile::whatToDoToAchieve() | ||||
| { | ||||
| 	const CGObjectInstance * firstObj = vstd::frontOrNull(cb->getVisitableObjs(tile)); | ||||
| 	if(firstObj && firstObj->ID == Obj::HERO && firstObj->tempOwner == ai->playerID) //we have hero at dest | ||||
| 	{ | ||||
| 		const CGHeroInstance * h = dynamic_cast<const CGHeroInstance *>(firstObj); | ||||
| 		sethero(h).setisElementar(true); | ||||
| 		return sptr(*this); | ||||
| 	} | ||||
|  | ||||
| 	return sptr(VisitTile(tile)); | ||||
| } | ||||
							
								
								
									
										41
									
								
								AI/VCAI/Goals/DigAtTile.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								AI/VCAI/Goals/DigAtTile.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
| * DigAtTile.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT DigAtTile : public CGoal<DigAtTile> | ||||
| 		//elementar with hero on tile | ||||
| 	{ | ||||
| 	public: | ||||
| 		DigAtTile() | ||||
| 			: CGoal(Goals::DIG_AT_TILE) | ||||
| 		{ | ||||
| 		} | ||||
| 		DigAtTile(int3 Tile) | ||||
| 			: CGoal(Goals::DIG_AT_TILE) | ||||
| 		{ | ||||
| 			tile = Tile; | ||||
| 			priority = 20; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override | ||||
| 		{ | ||||
| 			return TGoalVec(); | ||||
| 		} | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		virtual bool operator==(const DigAtTile & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										181
									
								
								AI/VCAI/Goals/Explore.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								AI/VCAI/Goals/Explore.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,181 @@ | ||||
| /* | ||||
| * Explore.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "Goals.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../ResourceManager.h" | ||||
| #include "../BuildingManager.h" | ||||
| #include "../../../lib/mapping/CMap.h" //for victory conditions | ||||
| #include "../../../lib/CPathfinder.h" | ||||
| #include "../../../lib/StringConstants.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool Explore::operator==(const Explore & other) const | ||||
| { | ||||
| 	return other.hero.h == hero.h; | ||||
| } | ||||
|  | ||||
| std::string Explore::completeMessage() const | ||||
| { | ||||
| 	return "Hero " + hero.get()->name + " completed exploration"; | ||||
| } | ||||
|  | ||||
| TSubgoal Explore::whatToDoToAchieve() | ||||
| { | ||||
| 	auto ret = fh->chooseSolution(getAllPossibleSubgoals()); | ||||
| 	if(hero) //use best step for this hero | ||||
| 	{ | ||||
| 		return ret; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		if(ret->hero.get(true)) | ||||
| 			return sptr(sethero(ret->hero.h).setisAbstract(true)); //choose this hero and then continue with him | ||||
| 		else | ||||
| 			return ret; //other solutions, like buying hero from tavern | ||||
| 	} | ||||
| } | ||||
|  | ||||
| TGoalVec Explore::getAllPossibleSubgoals() | ||||
| { | ||||
| 	TGoalVec ret; | ||||
| 	std::vector<const CGHeroInstance *> heroes; | ||||
|  | ||||
| 	if(hero) | ||||
| 	{ | ||||
| 		heroes.push_back(hero.h); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		//heroes = ai->getUnblockedHeroes(); | ||||
| 		heroes = cb->getHeroesInfo(); | ||||
| 		vstd::erase_if(heroes, [](const HeroPtr h) | ||||
| 		{ | ||||
| 			if(ai->getGoal(h)->goalType == EXPLORE) //do not reassign hero who is already explorer | ||||
| 				return true; | ||||
|  | ||||
| 			if(!ai->isAbleToExplore(h)) | ||||
| 				return true; | ||||
|  | ||||
| 			return !h->movement; //saves time, immobile heroes are useless anyway | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	//try to use buildings that uncover map | ||||
| 	std::vector<const CGObjectInstance *> objs; | ||||
| 	for(auto obj : ai->visitableObjs) | ||||
| 	{ | ||||
| 		if(!vstd::contains(ai->alreadyVisited, obj)) | ||||
| 		{ | ||||
| 			switch(obj->ID.num) | ||||
| 			{ | ||||
| 			case Obj::REDWOOD_OBSERVATORY: | ||||
| 			case Obj::PILLAR_OF_FIRE: | ||||
| 			case Obj::CARTOGRAPHER: | ||||
| 				objs.push_back(obj); | ||||
| 				break; | ||||
| 			case Obj::MONOLITH_ONE_WAY_ENTRANCE: | ||||
| 			case Obj::MONOLITH_TWO_WAY: | ||||
| 			case Obj::SUBTERRANEAN_GATE: | ||||
| 				auto tObj = dynamic_cast<const CGTeleport *>(obj); | ||||
| 				assert(ai->knownTeleportChannels.find(tObj->channel) != ai->knownTeleportChannels.end()); | ||||
| 				if(TeleportChannel::IMPASSABLE != ai->knownTeleportChannels[tObj->channel]->passability) | ||||
| 					objs.push_back(obj); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			switch(obj->ID.num) | ||||
| 			{ | ||||
| 			case Obj::MONOLITH_TWO_WAY: | ||||
| 			case Obj::SUBTERRANEAN_GATE: | ||||
| 				auto tObj = dynamic_cast<const CGTeleport *>(obj); | ||||
| 				if(TeleportChannel::IMPASSABLE == ai->knownTeleportChannels[tObj->channel]->passability) | ||||
| 					break; | ||||
| 				for(auto exit : ai->knownTeleportChannels[tObj->channel]->exits) | ||||
| 				{ | ||||
| 					if(!cb->getObj(exit)) | ||||
| 					{ // Always attempt to visit two-way teleports if one of channel exits is not visible | ||||
| 						objs.push_back(obj); | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	auto primaryHero = ai->primaryHero().h; | ||||
| 	for(auto h : heroes) | ||||
| 	{ | ||||
| 		for(auto obj : objs) //double loop, performance risk? | ||||
| 		{ | ||||
| 			auto waysToVisitObj = ai->ah->howToVisitObj(h, obj); | ||||
|  | ||||
| 			vstd::concatenate(ret, waysToVisitObj); | ||||
| 		} | ||||
|  | ||||
| 		int3 t = whereToExplore(h); | ||||
| 		if(t.valid()) | ||||
| 		{ | ||||
| 			ret.push_back(sptr(VisitTile(t).sethero(h))); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			//FIXME: possible issues when gathering army to break | ||||
| 			if(hero.h == h || //exporation is assigned to this hero | ||||
| 				(!hero && h == primaryHero)) //not assigned to specific hero, let our main hero do the job | ||||
| 			{ | ||||
| 				t = ai->explorationDesperate(h);  //check this only ONCE, high cost | ||||
| 				if (t.valid()) //don't waste time if we are completely blocked | ||||
| 				{ | ||||
| 					auto waysToVisitTile = ai->ah->howToVisitTile(h, t); | ||||
|  | ||||
| 					vstd::concatenate(ret, waysToVisitTile); | ||||
| 					continue; | ||||
| 				} | ||||
| 			} | ||||
| 			ai->markHeroUnableToExplore(h); //there is no freely accessible tile, do not poll this hero anymore | ||||
| 		} | ||||
| 	} | ||||
| 	//we either don't have hero yet or none of heroes can explore | ||||
| 	if((!hero || ret.empty()) && ai->canRecruitAnyHero()) | ||||
| 		ret.push_back(sptr(RecruitHero())); | ||||
|  | ||||
| 	if(ret.empty()) | ||||
| 	{ | ||||
| 		throw goalFulfilledException(sptr(Explore().sethero(hero))); | ||||
| 	} | ||||
| 	//throw cannotFulfillGoalException("Cannot explore - no possible ways found!"); | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| bool Explore::fulfillsMe(TSubgoal goal) | ||||
| { | ||||
| 	if(goal->goalType == EXPLORE) | ||||
| 	{ | ||||
| 		if(goal->hero) | ||||
| 			return hero == goal->hero; | ||||
| 		else | ||||
| 			return true; //cancel ALL exploration | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
							
								
								
									
										40
									
								
								AI/VCAI/Goals/Explore.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								AI/VCAI/Goals/Explore.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| /* | ||||
| * Explore.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT Explore : public CGoal<Explore> | ||||
| 	{ | ||||
| 	public: | ||||
| 		Explore() | ||||
| 			: CGoal(Goals::EXPLORE) | ||||
| 		{ | ||||
| 			priority = 1; | ||||
| 		} | ||||
| 		Explore(HeroPtr h) | ||||
| 			: CGoal(Goals::EXPLORE) | ||||
| 		{ | ||||
| 			hero = h; | ||||
| 			priority = 1; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override; | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		std::string completeMessage() const override; | ||||
| 		bool fulfillsMe(TSubgoal goal) override; | ||||
| 		virtual bool operator==(const Explore & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										70
									
								
								AI/VCAI/Goals/FindObj.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								AI/VCAI/Goals/FindObj.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| /* | ||||
| * FindObj.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "FindObj.h" | ||||
| #include "VisitObj.h" | ||||
| #include "Explore.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool FindObj::operator==(const FindObj & other) const | ||||
| { | ||||
| 	return other.hero.h == hero.h && other.objid == objid; | ||||
| } | ||||
|  | ||||
| TSubgoal FindObj::whatToDoToAchieve() | ||||
| { | ||||
| 	const CGObjectInstance * o = nullptr; | ||||
| 	if(resID > -1) //specified | ||||
| 	{ | ||||
| 		for(const CGObjectInstance * obj : ai->visitableObjs) | ||||
| 		{ | ||||
| 			if(obj->ID == objid && obj->subID == resID) | ||||
| 			{ | ||||
| 				o = obj; | ||||
| 				break; //TODO: consider multiple objects and choose best | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		for(const CGObjectInstance * obj : ai->visitableObjs) | ||||
| 		{ | ||||
| 			if(obj->ID == objid) | ||||
| 			{ | ||||
| 				o = obj; | ||||
| 				break; //TODO: consider multiple objects and choose best | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	if(o && ai->isAccessible(o->pos)) //we don't use isAccessibleForHero as we don't know which hero it is | ||||
| 		return sptr(VisitObj(o->id.getNum())); | ||||
| 	else | ||||
| 		return sptr(Explore()); | ||||
| } | ||||
|  | ||||
| bool FindObj::fulfillsMe(TSubgoal goal) | ||||
| { | ||||
| 	if (goal->goalType == VISIT_TILE) //visiting tile visits object at same time | ||||
| 	{ | ||||
| 		if (!hero || hero == goal->hero) | ||||
| 			for (auto obj : cb->getVisitableObjs(goal->tile)) //check if any object on that tile matches criteria | ||||
| 				if (obj->visitablePos() == goal->tile) //object could be removed | ||||
| 					if (obj->ID == objid && obj->subID == resID) //same type and subtype | ||||
| 						return true; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
							
								
								
									
										47
									
								
								AI/VCAI/Goals/FindObj.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								AI/VCAI/Goals/FindObj.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| /* | ||||
| * FindObj.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT FindObj : public CGoal<FindObj> | ||||
| 	{ | ||||
| 	public: | ||||
| 		FindObj() {} // empty constructor not allowed | ||||
|  | ||||
| 		FindObj(int ID) | ||||
| 			: CGoal(Goals::FIND_OBJ) | ||||
| 		{ | ||||
| 			objid = ID; | ||||
| 			resID = -1; //subid unspecified | ||||
| 			priority = 1; | ||||
| 		} | ||||
| 		FindObj(int ID, int subID) | ||||
| 			: CGoal(Goals::FIND_OBJ) | ||||
| 		{ | ||||
| 			objid = ID; | ||||
| 			resID = subID; | ||||
| 			priority = 1; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override | ||||
| 		{ | ||||
| 			return TGoalVec(); | ||||
| 		} | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		bool fulfillsMe(TSubgoal goal) override; | ||||
| 		virtual bool operator==(const FindObj & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										196
									
								
								AI/VCAI/Goals/GatherArmy.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								AI/VCAI/Goals/GatherArmy.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,196 @@ | ||||
| /* | ||||
| * GatherArmy.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "Goals.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../ResourceManager.h" | ||||
| #include "../BuildingManager.h" | ||||
| #include "../../../lib/mapping/CMap.h" //for victory conditions | ||||
| #include "../../../lib/CPathfinder.h" | ||||
| #include "../../../lib/StringConstants.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool GatherArmy::operator==(const GatherArmy & other) const | ||||
| { | ||||
| 	return other.hero.h == hero.h || town == other.town; | ||||
| } | ||||
|  | ||||
| std::string GatherArmy::completeMessage() const | ||||
| { | ||||
| 	return "Hero " + hero.get()->name + " gathered army of value " + boost::lexical_cast<std::string>(value); | ||||
| } | ||||
|  | ||||
| TSubgoal GatherArmy::whatToDoToAchieve() | ||||
| { | ||||
| 	//TODO: find hero if none set | ||||
| 	assert(hero.h); | ||||
|  | ||||
| 	return fh->chooseSolution(getAllPossibleSubgoals()); //find dwelling. use current hero to prevent him from doing nothing. | ||||
| } | ||||
|  | ||||
| static const BuildingID unitsSource[] = { BuildingID::DWELL_LVL_1, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3, | ||||
| 	BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7}; | ||||
|  | ||||
| TGoalVec GatherArmy::getAllPossibleSubgoals() | ||||
| { | ||||
| 	//get all possible towns, heroes and dwellings we may use | ||||
| 	TGoalVec ret; | ||||
|  | ||||
| 	if(!hero.validAndSet()) | ||||
| 	{ | ||||
| 		return ret; | ||||
| 	} | ||||
|  | ||||
| 	//TODO: include evaluation of monsters gather in calculation | ||||
| 	for(auto t : cb->getTownsInfo()) | ||||
| 	{ | ||||
| 		auto pos = t->visitablePos(); | ||||
| 		if(ai->isAccessibleForHero(pos, hero)) | ||||
| 		{ | ||||
| 			//grab army from town | ||||
| 			if(!t->visitingHero && howManyReinforcementsCanGet(hero, t)) | ||||
| 			{ | ||||
| 				if(!vstd::contains(ai->townVisitsThisWeek[hero], t)) | ||||
| 					ret.push_back(sptr(VisitTile(pos).sethero(hero))); | ||||
| 			} | ||||
| 			//buy army in town | ||||
| 			if (!t->visitingHero || t->visitingHero == hero.get(true)) | ||||
| 			{ | ||||
| 				ui32 val = std::min<ui32>(value, howManyReinforcementsCanBuy(hero, t)); | ||||
| 				if (val) | ||||
| 				{ | ||||
| 					auto goal = sptr(BuyArmy(t, val).sethero(hero)); | ||||
| 					if(!ai->ah->containsObjective(goal)) //avoid loops caused by reserving same objective twice | ||||
| 						ret.push_back(goal); | ||||
| 					else | ||||
| 						logAi->debug("Can not buy army, because of ai->ah->containsObjective"); | ||||
| 				} | ||||
| 			} | ||||
| 			//build dwelling | ||||
| 			//TODO: plan building over multiple turns? | ||||
| 			//auto bid = ah->canBuildAnyStructure(t, std::vector<BuildingID>(unitsSource, unitsSource + ARRAY_COUNT(unitsSource)), 8 - cb->getDate(Date::DAY_OF_WEEK)); | ||||
|  | ||||
| 			//Do not use below code for now, rely on generic Build. Code below needs to know a lot of town/resource context to do more good than harm | ||||
| 			/*auto bid = ai->ah->canBuildAnyStructure(t, std::vector<BuildingID>(unitsSource, unitsSource + ARRAY_COUNT(unitsSource)), 1); | ||||
| 			if (bid.is_initialized()) | ||||
| 			{ | ||||
| 				auto goal = sptr(BuildThis(bid.get(), t).setpriority(priority)); | ||||
| 				if (!ai->ah->containsObjective(goal)) //avoid loops caused by reserving same objective twice | ||||
| 					ret.push_back(goal); | ||||
| 				else | ||||
| 					logAi->debug("Can not build a structure, because of ai->ah->containsObjective"); | ||||
| 			}*/ | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	auto otherHeroes = cb->getHeroesInfo(); | ||||
| 	auto heroDummy = hero; | ||||
| 	vstd::erase_if(otherHeroes, [heroDummy](const CGHeroInstance * h) | ||||
| 	{ | ||||
| 		if(h == heroDummy.h) | ||||
| 			return true; | ||||
| 		else if(!ai->isAccessibleForHero(heroDummy->visitablePos(), h, true)) | ||||
| 			return true; | ||||
| 		else if(!ai->canGetArmy(heroDummy.h, h)) //TODO: return actual aiValue | ||||
| 			return true; | ||||
| 		else if(ai->getGoal(h)->goalType == GATHER_ARMY) | ||||
| 			return true; | ||||
| 		else | ||||
| 		   return false; | ||||
| 	}); | ||||
| 	for(auto h : otherHeroes) | ||||
| 	{ | ||||
| 		// Go to the other hero if we are faster | ||||
| 		if (!vstd::contains(ai->visitedHeroes[hero], h) | ||||
| 			&& ai->isAccessibleForHero(h->visitablePos(), hero, true)) //visit only once each turn //FIXME: this is only bug workaround | ||||
| 			ret.push_back(sptr(VisitHero(h->id.getNum()).setisAbstract(true).sethero(hero))); | ||||
| 		// Let the other hero come to us | ||||
| 		if (!vstd::contains(ai->visitedHeroes[h], hero)) | ||||
| 			ret.push_back(sptr(VisitHero(hero->id.getNum()).setisAbstract(true).sethero(h))); | ||||
| 	} | ||||
|  | ||||
| 	std::vector<const CGObjectInstance *> objs; | ||||
| 	for(auto obj : ai->visitableObjs) | ||||
| 	{ | ||||
| 		if(obj->ID == Obj::CREATURE_GENERATOR1) | ||||
| 		{ | ||||
| 			auto relationToOwner = cb->getPlayerRelations(obj->getOwner(), ai->playerID); | ||||
|  | ||||
| 			//Use flagged dwellings only when there are available creatures that we can afford | ||||
| 			if(relationToOwner == PlayerRelations::SAME_PLAYER) | ||||
| 			{ | ||||
| 				auto dwelling = dynamic_cast<const CGDwelling *>(obj); | ||||
|  | ||||
| 				ui32 val = std::min<ui32>(value, howManyReinforcementsCanBuy(hero, dwelling)); | ||||
|  | ||||
| 				if(val) | ||||
| 				{ | ||||
| 					for(auto & creLevel : dwelling->creatures) | ||||
| 					{ | ||||
| 						if(creLevel.first) | ||||
| 						{ | ||||
| 							for(auto & creatureID : creLevel.second) | ||||
| 							{ | ||||
| 								auto creature = VLC->creh->creatures[creatureID]; | ||||
| 								if(ai->ah->freeResources().canAfford(creature->cost)) | ||||
| 									objs.push_back(obj); //TODO: reserve resources? | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	for(auto h : cb->getHeroesInfo()) | ||||
| 	{ | ||||
| 		for(auto obj : objs) | ||||
| 		{ | ||||
| 			//find safe dwelling | ||||
| 			if(ai->isGoodForVisit(obj, h)) | ||||
| 			{ | ||||
| 				vstd::concatenate(ret, ai->ah->howToVisitObj(h, obj)); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if(ai->canRecruitAnyHero() && ai->ah->freeGold() > GameConstants::HERO_GOLD_COST) //this is not stupid in early phase of game | ||||
| 	{ | ||||
| 		if(auto t = ai->findTownWithTavern()) | ||||
| 		{ | ||||
| 			for(auto h : cb->getAvailableHeroes(t)) //we assume that all towns have same set of heroes | ||||
| 			{ | ||||
| 				if(h && h->getTotalStrength() > 500) //do not buy heroes with single creatures for GatherArmy | ||||
| 				{ | ||||
| 					ret.push_back(sptr(RecruitHero())); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if(ret.empty()) | ||||
| 	{ | ||||
| 		if(hero == ai->primaryHero()) | ||||
| 			ret.push_back(sptr(Explore())); | ||||
| 		else | ||||
| 			throw cannotFulfillGoalException("No ways to gather army"); | ||||
| 	} | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
							
								
								
									
										38
									
								
								AI/VCAI/Goals/GatherArmy.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								AI/VCAI/Goals/GatherArmy.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| /* | ||||
| * GatherArmy.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT GatherArmy : public CGoal<GatherArmy> | ||||
| 	{ | ||||
| 	public: | ||||
| 		GatherArmy() | ||||
| 			: CGoal(Goals::GATHER_ARMY) | ||||
| 		{ | ||||
| 		} | ||||
| 		GatherArmy(int val) | ||||
| 			: CGoal(Goals::GATHER_ARMY) | ||||
| 		{ | ||||
| 			value = val; | ||||
| 			priority = 2.5; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override; | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		std::string completeMessage() const override; | ||||
| 		virtual bool operator==(const GatherArmy & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										139
									
								
								AI/VCAI/Goals/GatherTroops.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								AI/VCAI/Goals/GatherTroops.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,139 @@ | ||||
| /* | ||||
| * GatherTroops.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "Goals.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../ResourceManager.h" | ||||
| #include "../BuildingManager.h" | ||||
| #include "../../../lib/mapping/CMap.h" //for victory conditions | ||||
| #include "../../../lib/CPathfinder.h" | ||||
| #include "../../../lib/StringConstants.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool GatherTroops::operator==(const GatherTroops & other) const | ||||
| { | ||||
| 	return objid == other.objid; | ||||
| } | ||||
|  | ||||
| int GatherTroops::getCreaturesCount(const CArmedInstance * army) | ||||
| { | ||||
| 	int count = 0; | ||||
|  | ||||
| 	for(auto stack : army->Slots()) | ||||
| 	{ | ||||
| 		if(objid == stack.second->getCreatureID().num) | ||||
| 		{ | ||||
| 			count += stack.second->count; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return count; | ||||
| } | ||||
|  | ||||
| TSubgoal GatherTroops::whatToDoToAchieve() | ||||
| { | ||||
| 	auto heroes = cb->getHeroesInfo(true); | ||||
|  | ||||
| 	for(auto hero : heroes) | ||||
| 	{ | ||||
| 		if(getCreaturesCount(hero) >= this->value) | ||||
| 		{ | ||||
| 			logAi->trace("Completing GATHER_TROOPS by hero %s", hero->name); | ||||
|  | ||||
| 			throw goalFulfilledException(sptr(*this)); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	TGoalVec solutions = getAllPossibleSubgoals(); | ||||
|  | ||||
| 	if(solutions.empty()) | ||||
| 		return sptr(Explore()); | ||||
|  | ||||
| 	return fh->chooseSolution(solutions); | ||||
| } | ||||
|  | ||||
|  | ||||
| TGoalVec GatherTroops::getAllPossibleSubgoals() | ||||
| { | ||||
| 	TGoalVec solutions; | ||||
|  | ||||
| 	for(const CGTownInstance * t : cb->getTownsInfo()) | ||||
| 	{ | ||||
| 		int count = getCreaturesCount(t->getUpperArmy()); | ||||
|  | ||||
| 		if(count >= this->value) | ||||
| 		{ | ||||
| 			vstd::concatenate(solutions, ai->ah->howToVisitObj(t)); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		auto creature = VLC->creh->creatures[objid]; | ||||
| 		if(t->subID == creature->faction) //TODO: how to force AI to build unupgraded creatures? :O | ||||
| 		{ | ||||
| 			auto creatures = vstd::tryAt(t->town->creatures, creature->level - 1); | ||||
| 			if(!creatures) | ||||
| 				continue; | ||||
|  | ||||
| 			int upgradeNumber = vstd::find_pos(*creatures, creature->idNumber); | ||||
| 			if(upgradeNumber < 0) | ||||
| 				continue; | ||||
|  | ||||
| 			BuildingID bid(BuildingID::DWELL_FIRST + creature->level - 1 + upgradeNumber * GameConstants::CREATURES_PER_TOWN); | ||||
| 			if(t->hasBuilt(bid)) //this assumes only creatures with dwellings are assigned to faction | ||||
| 			{ | ||||
| 				solutions.push_back(sptr(BuyArmy(t, creature->AIValue * this->value).setobjid(objid))); | ||||
| 			} | ||||
| 			/*else //disable random building requests for now - this code needs to know a lot of town/resource context to do more good than harm | ||||
| 			{	 | ||||
| 				return sptr(BuildThis(bid, t).setpriority(priority)); | ||||
| 			}*/ | ||||
| 		} | ||||
| 	} | ||||
| 	for(auto obj : ai->visitableObjs) | ||||
| 	{ | ||||
| 		auto d = dynamic_cast<const CGDwelling *>(obj); | ||||
|  | ||||
| 		if(!d || obj->ID == Obj::TOWN) | ||||
| 			continue; | ||||
|  | ||||
| 		for(auto creature : d->creatures) | ||||
| 		{ | ||||
| 			if(creature.first) //there are more than 0 creatures avaliabe | ||||
| 			{ | ||||
| 				for(auto type : creature.second) | ||||
| 				{ | ||||
| 					if(type == objid && ai->ah->freeResources().canAfford(VLC->creh->creatures[type]->cost)) | ||||
| 						vstd::concatenate(solutions, ai->ah->howToVisitObj(obj)); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return solutions; | ||||
| 	//TODO: exchange troops between heroes | ||||
| } | ||||
|  | ||||
| bool GatherTroops::fulfillsMe(TSubgoal goal) | ||||
| { | ||||
| 	if (!hero || hero == goal->hero) //we got army for desired hero or any hero | ||||
| 		if (goal->objid == objid) //same creature type //TODO: consider upgrades? | ||||
| 			if (goal->value >= value) //notify every time we get resources? | ||||
| 				return true; | ||||
| 	return false; | ||||
| } | ||||
							
								
								
									
										43
									
								
								AI/VCAI/Goals/GatherTroops.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								AI/VCAI/Goals/GatherTroops.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| /* | ||||
| * GatherTroops.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT GatherTroops : public CGoal<GatherTroops> | ||||
| 	{ | ||||
| 	public: | ||||
| 		GatherTroops() | ||||
| 			: CGoal(Goals::GATHER_TROOPS) | ||||
| 		{ | ||||
| 			priority = 2; | ||||
| 		} | ||||
| 		GatherTroops(int type, int val) | ||||
| 			: CGoal(Goals::GATHER_TROOPS) | ||||
| 		{ | ||||
| 			objid = type; | ||||
| 			value = val; | ||||
| 			priority = 2; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override; | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		bool fulfillsMe(TSubgoal goal) override; | ||||
| 		virtual bool operator==(const GatherTroops & other) const override; | ||||
|  | ||||
| 	private: | ||||
| 		int getCreaturesCount(const CArmedInstance * army); | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										31
									
								
								AI/VCAI/Goals/GetArtOfType.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								AI/VCAI/Goals/GetArtOfType.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| /* | ||||
| * GetArtOfType.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "GetArtOfType.h" | ||||
| #include "FindObj.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool GetArtOfType::operator==(const GetArtOfType & other) const | ||||
| { | ||||
| 	return other.hero.h == hero.h && other.objid == objid; | ||||
| } | ||||
|  | ||||
| TSubgoal GetArtOfType::whatToDoToAchieve() | ||||
| { | ||||
| 	return sptr(FindObj(Obj::ARTIFACT, aid)); | ||||
| } | ||||
							
								
								
									
										40
									
								
								AI/VCAI/Goals/GetArtOfType.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								AI/VCAI/Goals/GetArtOfType.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| /* | ||||
| * GetArtOfType.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT GetArtOfType : public CGoal<GetArtOfType> | ||||
| 	{ | ||||
| 	public: | ||||
| 		GetArtOfType() | ||||
| 			: CGoal(Goals::GET_ART_TYPE) | ||||
| 		{ | ||||
| 		} | ||||
| 		GetArtOfType(int type) | ||||
| 			: CGoal(Goals::GET_ART_TYPE) | ||||
| 		{ | ||||
| 			aid = type; | ||||
| 			priority = 2; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override | ||||
| 		{ | ||||
| 			return TGoalVec(); | ||||
| 		} | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		virtual bool operator==(const GetArtOfType & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										32
									
								
								AI/VCAI/Goals/Goals.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								AI/VCAI/Goals/Goals.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| /* | ||||
| * Goals.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
| #include "Invalid.h" | ||||
| #include "BuildBoat.h" | ||||
| #include "Build.h" | ||||
| #include "BuildThis.h" | ||||
| #include "Conquer.h" | ||||
| #include "GatherArmy.h" | ||||
| #include "Win.h" | ||||
| #include "VisitObj.h" | ||||
| #include "VisitTile.h" | ||||
| #include "VisitHero.h" | ||||
| #include "Explore.h" | ||||
| #include "BuyArmy.h" | ||||
| #include "GatherTroops.h" | ||||
| #include "Trade.h" | ||||
| #include "CollectRes.h" | ||||
| #include "RecruitHero.h" | ||||
| #include "GetArtOfType.h" | ||||
| #include "ClearWayTo.h" | ||||
| #include "DigAtTile.h" | ||||
| #include "FindObj.h" | ||||
							
								
								
									
										41
									
								
								AI/VCAI/Goals/Invalid.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								AI/VCAI/Goals/Invalid.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
| * Invalid.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT Invalid : public CGoal<Invalid> | ||||
| 	{ | ||||
| 	public: | ||||
| 		Invalid() | ||||
| 			: CGoal(Goals::INVALID) | ||||
| 		{ | ||||
| 			priority = -1e10; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override | ||||
| 		{ | ||||
| 			return TGoalVec(); | ||||
| 		} | ||||
| 		TSubgoal whatToDoToAchieve() override | ||||
| 		{ | ||||
| 			return iAmElementar(); | ||||
| 		} | ||||
|  | ||||
| 		virtual bool operator==(const Invalid & other) const override | ||||
| 		{ | ||||
| 			return true; | ||||
| 		} | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										38
									
								
								AI/VCAI/Goals/RecruitHero.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								AI/VCAI/Goals/RecruitHero.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| /* | ||||
| * RecruitHero.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "Goals.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../ResourceManager.h" | ||||
| #include "../BuildingManager.h" | ||||
| #include "../../../lib/mapping/CMap.h" //for victory conditions | ||||
| #include "../../../lib/CPathfinder.h" | ||||
| #include "../../../lib/StringConstants.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| TSubgoal RecruitHero::whatToDoToAchieve() | ||||
| { | ||||
| 	const CGTownInstance * t = ai->findTownWithTavern(); | ||||
| 	if(!t) | ||||
| 		return sptr(BuildThis(BuildingID::TAVERN).setpriority(2)); | ||||
|  | ||||
| 	TResources res; | ||||
| 	res[Res::GOLD] = GameConstants::HERO_GOLD_COST; | ||||
| 	return ai->ah->whatToDo(res, iAmElementar()); //either buy immediately, or collect res | ||||
| } | ||||
							
								
								
									
										41
									
								
								AI/VCAI/Goals/RecruitHero.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								AI/VCAI/Goals/RecruitHero.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
| * RecruitHero.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT RecruitHero : public CGoal<RecruitHero> | ||||
| 	{ | ||||
| 	public: | ||||
| 		RecruitHero() | ||||
| 			: CGoal(Goals::RECRUIT_HERO) | ||||
| 		{ | ||||
| 			priority = 1; | ||||
| 		} | ||||
|  | ||||
| 		TGoalVec getAllPossibleSubgoals() override | ||||
| 		{ | ||||
| 			return TGoalVec(); | ||||
| 		} | ||||
|  | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
|  | ||||
| 		virtual bool operator==(const RecruitHero & other) const override | ||||
| 		{ | ||||
| 			return true; | ||||
| 		} | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										23
									
								
								AI/VCAI/Goals/Trade.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								AI/VCAI/Goals/Trade.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| /* | ||||
| * Trade.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "Trade.h" | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool Trade::operator==(const Trade & other) const | ||||
| { | ||||
| 	return resID == other.resID; | ||||
| } | ||||
|  | ||||
| TSubgoal Trade::whatToDoToAchieve() | ||||
| { | ||||
| 	return iAmElementar(); | ||||
| } | ||||
							
								
								
									
										38
									
								
								AI/VCAI/Goals/Trade.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								AI/VCAI/Goals/Trade.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| /* | ||||
| * Trade.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT Trade : public CGoal<Trade> | ||||
| 	{ | ||||
| 	public: | ||||
| 		Trade() | ||||
| 			: CGoal(Goals::TRADE) | ||||
| 		{ | ||||
| 		} | ||||
| 		Trade(int rid, int val, int Objid) | ||||
| 			: CGoal(Goals::TRADE) | ||||
| 		{ | ||||
| 			resID = rid; | ||||
| 			value = val; | ||||
| 			objid = Objid; | ||||
| 			priority = 3; //trading is instant, but picking resources is free | ||||
| 		} | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		virtual bool operator==(const Trade & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										74
									
								
								AI/VCAI/Goals/VisitHero.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								AI/VCAI/Goals/VisitHero.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| /* | ||||
| * VisitHero.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "VisitHero.h" | ||||
| #include "Explore.h" | ||||
| #include "Invalid.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../ResourceManager.h" | ||||
| #include "../BuildingManager.h" | ||||
| #include "../../../lib/mapping/CMap.h" //for victory conditions | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool VisitHero::operator==(const VisitHero & other) const | ||||
| { | ||||
| 	return other.hero.h == hero.h && other.objid == objid; | ||||
| } | ||||
|  | ||||
| std::string VisitHero::completeMessage() const | ||||
| { | ||||
| 	return "hero " + hero.get()->name + " visited hero " + boost::lexical_cast<std::string>(objid); | ||||
| } | ||||
|  | ||||
| TSubgoal VisitHero::whatToDoToAchieve() | ||||
| { | ||||
| 	const CGObjectInstance * obj = cb->getObj(ObjectInstanceID(objid)); | ||||
| 	if(!obj) | ||||
| 		return sptr(Explore()); | ||||
| 	int3 pos = obj->visitablePos(); | ||||
|  | ||||
| 	if(hero && ai->isAccessibleForHero(pos, hero, true) && isSafeToVisit(hero, pos)) //enemy heroes can get reinforcements | ||||
| 	{ | ||||
| 		if(hero->pos == pos) | ||||
| 			logAi->error("Hero %s tries to visit himself.", hero.name); | ||||
| 		else | ||||
| 		{ | ||||
| 			//can't use VISIT_TILE here as tile appears blocked by target hero | ||||
| 			//FIXME: elementar goal should not be abstract | ||||
| 			return sptr(VisitHero(objid).sethero(hero).settile(pos).setisElementar(true)); | ||||
| 		} | ||||
| 	} | ||||
| 	return sptr(Invalid()); | ||||
| } | ||||
|  | ||||
| bool VisitHero::fulfillsMe(TSubgoal goal) | ||||
| { | ||||
| 	//TODO: VisitObj shoudl not be used for heroes, but... | ||||
| 	if(goal->goalType == VISIT_TILE) | ||||
| 	{ | ||||
| 		auto obj = cb->getObj(ObjectInstanceID(objid)); | ||||
| 		if (!obj) | ||||
| 		{ | ||||
| 			logAi->error("Hero %s: VisitHero::fulfillsMe at %s: object %d not found", hero.name, goal->tile.toString(), objid); | ||||
| 			return false; | ||||
| 		} | ||||
| 		return obj->visitablePos() == goal->tile; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
							
								
								
									
										42
									
								
								AI/VCAI/Goals/VisitHero.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								AI/VCAI/Goals/VisitHero.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| /* | ||||
| * VisitHero.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT VisitHero : public CGoal<VisitHero> | ||||
| 	{ | ||||
| 	public: | ||||
| 		VisitHero() | ||||
| 			: CGoal(Goals::VISIT_HERO) | ||||
| 		{ | ||||
| 		} | ||||
| 		VisitHero(int hid) | ||||
| 			: CGoal(Goals::VISIT_HERO) | ||||
| 		{ | ||||
| 			objid = hid; | ||||
| 			priority = 4; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override | ||||
| 		{ | ||||
| 			return TGoalVec(); | ||||
| 		} | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		bool fulfillsMe(TSubgoal goal) override; | ||||
| 		std::string completeMessage() const override; | ||||
| 		virtual bool operator==(const VisitHero & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										112
									
								
								AI/VCAI/Goals/VisitObj.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								AI/VCAI/Goals/VisitObj.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| /* | ||||
| * VisitObj.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "Goals.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../ResourceManager.h" | ||||
| #include "../BuildingManager.h" | ||||
| #include "../../../lib/mapping/CMap.h" //for victory conditions | ||||
| #include "../../../lib/CPathfinder.h" | ||||
| #include "../../../lib/StringConstants.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool VisitObj::operator==(const VisitObj & other) const | ||||
| { | ||||
| 	return other.hero.h == hero.h && other.objid == objid; | ||||
| } | ||||
|  | ||||
| std::string VisitObj::completeMessage() const | ||||
| { | ||||
| 	return "hero " + hero.get()->name + " captured Object ID = " + boost::lexical_cast<std::string>(objid); | ||||
| } | ||||
|  | ||||
| TGoalVec VisitObj::getAllPossibleSubgoals() | ||||
| { | ||||
| 	TGoalVec goalList; | ||||
| 	const CGObjectInstance * obj = cb->getObjInstance(ObjectInstanceID(objid)); | ||||
| 	if(!obj) | ||||
| 	{ | ||||
| 		throw cannotFulfillGoalException("Object is missing - goal is invalid now!"); | ||||
| 	} | ||||
|  | ||||
| 	int3 pos = obj->visitablePos(); | ||||
| 	if(hero) | ||||
| 	{ | ||||
| 		if(ai->isAccessibleForHero(pos, hero)) | ||||
| 		{ | ||||
| 			if(isSafeToVisit(hero, pos)) | ||||
| 				goalList.push_back(sptr(VisitObj(obj->id.getNum()).sethero(hero))); | ||||
| 			else | ||||
| 				goalList.push_back(sptr(GatherArmy(evaluateDanger(pos, hero.h) * SAFE_ATTACK_CONSTANT).sethero(hero).setisAbstract(true))); | ||||
|  | ||||
| 			return goalList; | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		for(auto potentialVisitor : cb->getHeroesInfo()) | ||||
| 		{ | ||||
| 			if(ai->isAccessibleForHero(pos, potentialVisitor)) | ||||
| 			{ | ||||
| 				if(isSafeToVisit(potentialVisitor, pos)) | ||||
| 					goalList.push_back(sptr(VisitObj(obj->id.getNum()).sethero(potentialVisitor))); | ||||
| 				else | ||||
| 					goalList.push_back(sptr(GatherArmy(evaluateDanger(pos, potentialVisitor) * SAFE_ATTACK_CONSTANT).sethero(potentialVisitor).setisAbstract(true))); | ||||
| 			} | ||||
| 		} | ||||
| 		if(!goalList.empty()) | ||||
| 		{ | ||||
| 			return goalList; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	goalList.push_back(sptr(ClearWayTo(pos))); | ||||
| 	return goalList; | ||||
| } | ||||
|  | ||||
| TSubgoal VisitObj::whatToDoToAchieve() | ||||
| { | ||||
| 	auto bestGoal = fh->chooseSolution(getAllPossibleSubgoals()); | ||||
|  | ||||
| 	if(bestGoal->goalType == VISIT_OBJ && bestGoal->hero) | ||||
| 		bestGoal->setisElementar(true); | ||||
|  | ||||
| 	return bestGoal; | ||||
| } | ||||
|  | ||||
| VisitObj::VisitObj(int Objid) : CGoal(VISIT_OBJ) | ||||
| { | ||||
| 	objid = Objid; | ||||
| 	tile = ai->myCb->getObjInstance(ObjectInstanceID(objid))->visitablePos(); | ||||
| 	priority = 3; | ||||
| } | ||||
|  | ||||
| bool VisitObj::fulfillsMe(TSubgoal goal) | ||||
| { | ||||
| 	if(goal->goalType == VISIT_TILE) | ||||
| 	{ | ||||
| 		if (!hero || hero == goal->hero) | ||||
| 		{ | ||||
| 			auto obj = cb->getObjInstance(ObjectInstanceID(objid)); | ||||
| 			if (obj && obj->visitablePos() == goal->tile) //object could be removed | ||||
| 				return true; | ||||
| 		} | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
							
								
								
									
										32
									
								
								AI/VCAI/Goals/VisitObj.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								AI/VCAI/Goals/VisitObj.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| /* | ||||
| * VisitObj.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT VisitObj : public CGoal<VisitObj> //this goal was previously known as GetObj | ||||
| 	{ | ||||
| 	public: | ||||
| 		VisitObj() = delete; // empty constructor not allowed | ||||
| 		VisitObj(int Objid); | ||||
|  | ||||
| 		TGoalVec getAllPossibleSubgoals() override; | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		bool fulfillsMe(TSubgoal goal) override; | ||||
| 		std::string completeMessage() const override; | ||||
| 		virtual bool operator==(const VisitObj & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										98
									
								
								AI/VCAI/Goals/VisitTile.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								AI/VCAI/Goals/VisitTile.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| /* | ||||
| * VisitTile.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "Goals.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../ResourceManager.h" | ||||
| #include "../BuildingManager.h" | ||||
| #include "../../../lib/mapping/CMap.h" //for victory conditions | ||||
| #include "../../../lib/CPathfinder.h" | ||||
| #include "../../../lib/StringConstants.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| bool VisitTile::operator==(const VisitTile & other) const | ||||
| { | ||||
| 	return other.hero.h == hero.h && other.tile == tile; | ||||
| } | ||||
|  | ||||
| std::string VisitTile::completeMessage() const | ||||
| { | ||||
| 	return "Hero " + hero.get()->name + " visited tile " + tile.toString(); | ||||
| } | ||||
|  | ||||
| TSubgoal VisitTile::whatToDoToAchieve() | ||||
| { | ||||
| 	auto ret = fh->chooseSolution(getAllPossibleSubgoals()); | ||||
|  | ||||
| 	if(ret->hero) | ||||
| 	{ | ||||
| 		if(isSafeToVisit(ret->hero, tile) && ai->isAccessibleForHero(tile, ret->hero)) | ||||
| 		{ | ||||
| 			ret->setisElementar(true); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			return sptr(GatherArmy(evaluateDanger(tile, *ret->hero) * SAFE_ATTACK_CONSTANT) | ||||
| 				    .sethero(ret->hero).setisAbstract(true)); | ||||
| 		} | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| TGoalVec VisitTile::getAllPossibleSubgoals() | ||||
| { | ||||
| 	assert(cb->isInTheMap(tile)); | ||||
|  | ||||
| 	TGoalVec ret; | ||||
| 	if(!cb->isVisible(tile)) | ||||
| 		ret.push_back(sptr(Explore())); //what sense does it make? | ||||
| 	else | ||||
| 	{ | ||||
| 		std::vector<const CGHeroInstance *> heroes; | ||||
| 		if(hero) | ||||
| 			heroes.push_back(hero.h); //use assigned hero if any | ||||
| 		else | ||||
| 			heroes = cb->getHeroesInfo(); //use most convenient hero | ||||
|  | ||||
| 		for(auto h : heroes) | ||||
| 		{ | ||||
| 			if(ai->isAccessibleForHero(tile, h)) | ||||
| 				ret.push_back(sptr(VisitTile(tile).sethero(h))); | ||||
| 		} | ||||
| 		if(ai->canRecruitAnyHero()) | ||||
| 			ret.push_back(sptr(RecruitHero())); | ||||
| 	} | ||||
| 	if(ret.empty()) | ||||
| 	{ | ||||
| 		auto obj = vstd::frontOrNull(cb->getVisitableObjs(tile)); | ||||
| 		if(obj && obj->ID == Obj::HERO && obj->tempOwner == ai->playerID) //our own hero stands on that tile | ||||
| 		{ | ||||
| 			if(hero.get(true) && hero->id == obj->id) //if it's assigned hero, visit tile. If it's different hero, we can't visit tile now | ||||
| 				ret.push_back(sptr(VisitTile(tile).sethero(dynamic_cast<const CGHeroInstance *>(obj)).setisElementar(true))); | ||||
| 			else | ||||
| 				throw cannotFulfillGoalException("Tile is already occupied by another hero "); //FIXME: we should give up this tile earlier | ||||
| 		} | ||||
| 		else | ||||
| 			ret.push_back(sptr(ClearWayTo(tile))); | ||||
| 	} | ||||
|  | ||||
| 	//important - at least one sub-goal must handle case which is impossible to fulfill (unreachable tile) | ||||
| 	return ret; | ||||
| } | ||||
							
								
								
									
										37
									
								
								AI/VCAI/Goals/VisitTile.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								AI/VCAI/Goals/VisitTile.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| /* | ||||
| * VisitTile.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT VisitTile : public CGoal<VisitTile> | ||||
| 		//tile, in conjunction with hero elementar; assumes tile is reachable | ||||
| 	{ | ||||
| 	public: | ||||
| 		VisitTile() {} // empty constructor not allowed | ||||
|  | ||||
| 		VisitTile(int3 Tile) | ||||
| 			: CGoal(Goals::VISIT_TILE) | ||||
| 		{ | ||||
| 			tile = Tile; | ||||
| 			priority = 5; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override; | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
| 		std::string completeMessage() const override; | ||||
| 		virtual bool operator==(const VisitTile & other) const override; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										191
									
								
								AI/VCAI/Goals/Win.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								AI/VCAI/Goals/Win.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| /* | ||||
| * Win.cpp, 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 | ||||
| * | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "Goals.h" | ||||
| #include "../VCAI.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../AIhelper.h" | ||||
| #include "../FuzzyHelper.h" | ||||
| #include "../ResourceManager.h" | ||||
| #include "../BuildingManager.h" | ||||
| #include "../../../lib/mapping/CMap.h" //for victory conditions | ||||
| #include "../../../lib/CPathfinder.h" | ||||
| #include "../../../lib/StringConstants.h" | ||||
|  | ||||
|  | ||||
| extern boost::thread_specific_ptr<CCallback> cb; | ||||
| extern boost::thread_specific_ptr<VCAI> ai; | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| using namespace Goals; | ||||
|  | ||||
| TSubgoal Win::whatToDoToAchieve() | ||||
| { | ||||
| 	auto toBool = [=](const EventCondition &) | ||||
| 	{ | ||||
| 		// TODO: proper implementation | ||||
| 		// Right now even already fulfilled goals will be included into generated list | ||||
| 		// Proper check should test if event condition is already fulfilled | ||||
| 		// Easiest way to do this is to call CGameState::checkForVictory but this function should not be | ||||
| 		// used on client side or in AI code | ||||
| 		return false; | ||||
| 	}; | ||||
|  | ||||
| 	std::vector<EventCondition> goals; | ||||
|  | ||||
| 	for(const TriggeredEvent & event : cb->getMapHeader()->triggeredEvents) | ||||
| 	{ | ||||
| 		//TODO: try to eliminate human player(s) using loss conditions that have isHuman element | ||||
|  | ||||
| 		if(event.effect.type == EventEffect::VICTORY) | ||||
| 		{ | ||||
| 			boost::range::copy(event.trigger.getFulfillmentCandidates(toBool), std::back_inserter(goals)); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	//TODO: instead of returning first encountered goal AI should generate list of possible subgoals | ||||
| 	for(const EventCondition & goal : goals) | ||||
| 	{ | ||||
| 		switch(goal.condition) | ||||
| 		{ | ||||
| 		case EventCondition::HAVE_ARTIFACT: | ||||
| 			return sptr(GetArtOfType(goal.objectType)); | ||||
| 		case EventCondition::DESTROY: | ||||
| 		{ | ||||
| 			if(goal.object) | ||||
| 			{ | ||||
| 				auto obj = cb->getObj(goal.object->id); | ||||
| 				if(obj) | ||||
| 					if(obj->getOwner() == ai->playerID) //we can't capture our own object | ||||
| 						return sptr(Conquer()); | ||||
|  | ||||
|  | ||||
| 				return sptr(VisitObj(goal.object->id.getNum())); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				// TODO: destroy all objects of type goal.objectType | ||||
| 				// This situation represents "kill all creatures" condition from H3 | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		case EventCondition::HAVE_BUILDING: | ||||
| 		{ | ||||
| 			// TODO build other buildings apart from Grail | ||||
| 			// goal.objectType = buidingID to build | ||||
| 			// goal.object = optional, town in which building should be built | ||||
| 			// Represents "Improve town" condition from H3 (but unlike H3 it consists from 2 separate conditions) | ||||
|  | ||||
| 			if(goal.objectType == BuildingID::GRAIL) | ||||
| 			{ | ||||
| 				if(auto h = ai->getHeroWithGrail()) | ||||
| 				{ | ||||
| 					//hero is in a town that can host Grail | ||||
| 					if(h->visitedTown && !vstd::contains(h->visitedTown->forbiddenBuildings, BuildingID::GRAIL)) | ||||
| 					{ | ||||
| 						const CGTownInstance * t = h->visitedTown; | ||||
| 						return sptr(BuildThis(BuildingID::GRAIL, t).setpriority(10)); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						auto towns = cb->getTownsInfo(); | ||||
| 						towns.erase(boost::remove_if(towns, | ||||
| 									     [](const CGTownInstance * t) -> bool | ||||
| 							{ | ||||
| 								return vstd::contains(t->forbiddenBuildings, BuildingID::GRAIL); | ||||
| 							}), | ||||
| 							    towns.end()); | ||||
| 						boost::sort(towns, CDistanceSorter(h.get())); | ||||
| 						if(towns.size()) | ||||
| 						{ | ||||
| 							return sptr(VisitTile(towns.front()->visitablePos()).sethero(h)); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				double ratio = 0; | ||||
| 				// maybe make this check a bit more complex? For example: | ||||
| 				// 0.75 -> dig randomly within 3 tiles radius | ||||
| 				// 0.85 -> radius now 2 tiles | ||||
| 				// 0.95 -> 1 tile radius, position is fully known | ||||
| 				// AFAIK H3 AI does something like this | ||||
| 				int3 grailPos = cb->getGrailPos(&ratio); | ||||
| 				if(ratio > 0.99) | ||||
| 				{ | ||||
| 					return sptr(DigAtTile(grailPos)); | ||||
| 				} //TODO: use FIND_OBJ | ||||
| 				else if(const CGObjectInstance * obj = ai->getUnvisitedObj(objWithID<Obj::OBELISK>)) //there are unvisited Obelisks | ||||
| 					return sptr(VisitObj(obj->id.getNum())); | ||||
| 				else | ||||
| 					return sptr(Explore()); | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		case EventCondition::CONTROL: | ||||
| 		{ | ||||
| 			if(goal.object) | ||||
| 			{ | ||||
| 				auto objRelations = cb->getPlayerRelations(ai->playerID, goal.object->tempOwner); | ||||
| 				 | ||||
| 				if(objRelations == PlayerRelations::ENEMIES) | ||||
| 				{ | ||||
| 					return sptr(VisitObj(goal.object->id.getNum())); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					// TODO: Defance | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				//TODO: control all objects of type "goal.objectType" | ||||
| 				// Represents H3 condition "Flag all mines" | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		case EventCondition::HAVE_RESOURCES: | ||||
| 			//TODO mines? piles? marketplace? | ||||
| 			//save? | ||||
| 			return sptr(CollectRes(static_cast<Res::ERes>(goal.objectType), goal.value)); | ||||
| 		case EventCondition::HAVE_CREATURES: | ||||
| 			return sptr(GatherTroops(goal.objectType, goal.value)); | ||||
| 		case EventCondition::TRANSPORT: | ||||
| 		{ | ||||
| 			//TODO. merge with bring Grail to town? So AI will first dig grail, then transport it using this goal and builds it | ||||
| 			// Represents "transport artifact" condition: | ||||
| 			// goal.objectType = type of artifact | ||||
| 			// goal.object = destination-town where artifact should be transported | ||||
| 			break; | ||||
| 		} | ||||
| 		case EventCondition::STANDARD_WIN: | ||||
| 			return sptr(Conquer()); | ||||
|  | ||||
| 		// Conditions that likely don't need any implementation | ||||
| 		case EventCondition::DAYS_PASSED: | ||||
| 			break; // goal.value = number of days for condition to trigger | ||||
| 		case EventCondition::DAYS_WITHOUT_TOWN: | ||||
| 			break; // goal.value = number of days to trigger this | ||||
| 		case EventCondition::IS_HUMAN: | ||||
| 			break; // Should be only used in calculation of candidates (see toBool lambda) | ||||
| 		case EventCondition::CONST_VALUE: | ||||
| 			break; | ||||
|  | ||||
| 		case EventCondition::HAVE_0: | ||||
| 		case EventCondition::HAVE_BUILDING_0: | ||||
| 		case EventCondition::DESTROY_0: | ||||
| 			//TODO: support new condition format | ||||
| 			return sptr(Conquer()); | ||||
| 		default: | ||||
| 			assert(0); | ||||
| 		} | ||||
| 	} | ||||
| 	return sptr(Invalid()); | ||||
| } | ||||
							
								
								
									
										39
									
								
								AI/VCAI/Goals/Win.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								AI/VCAI/Goals/Win.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| /* | ||||
| * Win.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 | ||||
|  | ||||
| #include "CGoal.h" | ||||
|  | ||||
| struct HeroPtr; | ||||
| class VCAI; | ||||
| class FuzzyHelper; | ||||
|  | ||||
| namespace Goals | ||||
| { | ||||
| 	class DLL_EXPORT Win : public CGoal<Win> | ||||
| 	{ | ||||
| 	public: | ||||
| 		Win() | ||||
| 			: CGoal(Goals::WIN) | ||||
| 		{ | ||||
| 			priority = 100; | ||||
| 		} | ||||
| 		TGoalVec getAllPossibleSubgoals() override | ||||
| 		{ | ||||
| 			return TGoalVec(); | ||||
| 		} | ||||
| 		TSubgoal whatToDoToAchieve() override; | ||||
|  | ||||
| 		virtual bool operator==(const Win & other) const override | ||||
| 		{ | ||||
| 			return true; | ||||
| 		} | ||||
| 	}; | ||||
| } | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
| * AIhelper.h, part of VCMI engine | ||||
| * AINodeStorage.cpp, part of VCMI engine | ||||
| * | ||||
| * Authors: listed in file AUTHORS in main folder | ||||
| * | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
| * AIhelper.h, part of VCMI engine | ||||
| * AINodeStorage.h, part of VCMI engine | ||||
| * | ||||
| * Authors: listed in file AUTHORS in main folder | ||||
| * | ||||
| @@ -13,7 +13,7 @@ | ||||
| #include "../../../lib/CPathfinder.h" | ||||
| #include "../../../lib/mapObjects/CGHeroInstance.h" | ||||
| #include "../AIUtility.h" | ||||
| #include "../Goals.h" | ||||
| #include "../Goals/AbstractGoal.h" | ||||
|  | ||||
| class ISpecialAction | ||||
| { | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
| * AIhelper.h, part of VCMI engine | ||||
| * AIPathfinder.cpp, part of VCMI engine | ||||
| * | ||||
| * Authors: listed in file AUTHORS in main folder | ||||
| * | ||||
| @@ -67,4 +67,4 @@ std::vector<AIPath> AIPathfinder::getPathInfo(HeroPtr hero, int3 tile) | ||||
| 	} | ||||
|  | ||||
| 	return nodeStorage->getChainInfo(tile, !tileInfo->isWater()); | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
| * AIhelper.h, part of VCMI engine | ||||
| * AIPathfinder.h, part of VCMI engine | ||||
| * | ||||
| * Authors: listed in file AUTHORS in main folder | ||||
| * | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
| * AIhelper.h, part of VCMI engine | ||||
| * AIPathfinderConfig.cpp, part of VCMI engine | ||||
| * | ||||
| * Authors: listed in file AUTHORS in main folder | ||||
| * | ||||
| @@ -9,6 +9,7 @@ | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "AIPathfinderConfig.h" | ||||
| #include "../Goals/Goals.h" | ||||
| #include "../../../CCallback.h" | ||||
| #include "../../../lib/mapping/CMap.h" | ||||
| #include "../../../lib/mapObjects/MapObjects.h" | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
| * AIhelper.h, part of VCMI engine | ||||
| * AIPathfinderConfig.h, part of VCMI engine | ||||
| * | ||||
| * Authors: listed in file AUTHORS in main folder | ||||
| * | ||||
| @@ -23,4 +23,4 @@ namespace AIPathfinding | ||||
| 			VCAI * ai, | ||||
| 			std::shared_ptr<AINodeStorage> nodeStorage); | ||||
| 	}; | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
| * AIhelper.h, part of VCMI engine | ||||
| * PathfindingManager.cpp, part of VCMI engine | ||||
| * | ||||
| * Authors: listed in file AUTHORS in main folder | ||||
| * | ||||
| @@ -11,6 +11,7 @@ | ||||
| #include "PathfindingManager.h" | ||||
| #include "AIPathfinder.h" | ||||
| #include "AIPathfinderConfig.h" | ||||
| #include "Goals/Goals.h" | ||||
| #include "../../../lib/CGameInfoCallback.h" | ||||
| #include "../../../lib/mapping/CMap.h" | ||||
|  | ||||
| @@ -227,4 +228,4 @@ void PathfindingManager::resetPaths() | ||||
| { | ||||
| 	logAi->debug("AIPathfinder has been reseted."); | ||||
| 	pathfinder->clear(); | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
| * AIhelper.h, part of VCMI engine | ||||
| * PathfindingManager.h, part of VCMI engine | ||||
| * | ||||
| * Authors: listed in file AUTHORS in main folder | ||||
| * | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| */ | ||||
| #include "StdInc.h" | ||||
| #include "ResourceManager.h" | ||||
| #include "Goals/Goals.h" | ||||
|  | ||||
| #include "../../CCallback.h" | ||||
| #include "../../lib/mapObjects/MapObjects.h" | ||||
|   | ||||
| @@ -10,7 +10,6 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "AIUtility.h" | ||||
| #include "Goals.h" | ||||
| #include "../../lib/GameConstants.h" | ||||
| #include "../../lib/VCMI_Lib.h" | ||||
| #include "VCAI.h" | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
| #include "FuzzyHelper.h" | ||||
| #include "ResourceManager.h" | ||||
| #include "BuildingManager.h" | ||||
| #include "Goals/Goals.h" | ||||
|  | ||||
| #include "../../lib/UnlockGuard.h" | ||||
| #include "../../lib/mapObjects/MapObjects.h" | ||||
|   | ||||
| @@ -10,8 +10,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "AIUtility.h" | ||||
| #include "SectorMap.h" | ||||
| #include "Goals.h" | ||||
| #include "Goals/AbstractGoal.h" | ||||
| #include "../../lib/AI_Base.h" | ||||
| #include "../../CCallback.h" | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user