| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 | 
							- #pragma once
 
- #include "AIUtility.h"
 
- #include "Goals.h"
 
- #include "../../lib/AI_Base.h"
 
- #include "../../CCallback.h"
 
- #include "../../lib/CThreadHelper.h"
 
- #include "../../lib/GameConstants.h"
 
- #include "../../lib/VCMI_Lib.h"
 
- #include "../../lib/CBuildingHandler.h"
 
- #include "../../lib/CCreatureHandler.h"
 
- #include "../../lib/CTownHandler.h"
 
- #include "../../lib/CSpellHandler.h"
 
- #include "../../lib/Connection.h"
 
- #include "../../lib/CGameState.h"
 
- #include "../../lib/mapping/CMap.h"
 
- #include "../../lib/NetPacks.h"
 
- #include "../../lib/CondSh.h"
 
- struct QuestInfo;
 
- /*
 
-  * VCAI.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
 
-  *
 
-  */
 
- class AIStatus
 
- {
 
- 	boost::mutex mx;
 
- 	boost::condition_variable cv;
 
- 	BattleState battle;
 
- 	std::map<QueryID, std::string> remainingQueries;
 
- 	std::map<int, QueryID> requestToQueryID; //IDs of answer-requests sent to server => query ids (so we can match answer confirmation from server to the query)
 
- 	std::vector<const CGObjectInstance*> objectsBeingVisited;
 
- 	bool ongoingHeroMovement;
 
- 	bool havingTurn;
 
- public:
 
- 	AIStatus();
 
- 	~AIStatus();
 
- 	void setBattle(BattleState BS);
 
- 	void setMove(bool ongoing);
 
- 	BattleState getBattle();
 
- 	void addQuery(QueryID ID, std::string description);
 
- 	void removeQuery(QueryID ID);
 
- 	int getQueriesCount();
 
- 	void startedTurn();
 
- 	void madeTurn();
 
- 	void waitTillFree();
 
- 	bool haveTurn();
 
- 	void attemptedAnsweringQuery(QueryID queryID, int answerRequestID);
 
- 	void receivedAnswerConfirmation(int answerRequestID, int result);
 
- 	void heroVisit(const CGObjectInstance *obj, bool started);
 
- 	template <typename Handler> void serialize(Handler &h, const int version)
 
- 	{
 
- 		h & battle & remainingQueries & requestToQueryID & havingTurn;
 
- 	}
 
- };
 
- enum {NOT_VISIBLE = 0, NOT_CHECKED = 1, NOT_AVAILABLE};
 
- struct SectorMap
 
- {
 
- 	//a sector is set of tiles that would be mutually reachable if all visitable objs would be passable (incl monsters)
 
- 	struct Sector
 
- 	{
 
- 		int id;
 
- 		std::vector<int3> tiles;
 
- 		std::vector<int3> embarkmentPoints; //tiles of other sectors onto which we can (dis)embark
 
- 		std::vector<const CGObjectInstance *> subterraneanGates;
 
- 		bool water; //all tiles of sector are land or water
 
- 		Sector()
 
- 		{
 
- 			id = -1;
 
- 		}
 
- 	};
 
- 	bool valid; //some kind of lazy eval
 
- 	std::map<int3, int3> parent;
 
- 	std::vector<std::vector<std::vector<unsigned char>>> sector;
 
- 	//std::vector<std::vector<std::vector<unsigned char>>> pathfinderSector;
 
- 	std::map<int, Sector> infoOnSectors;
 
- 	SectorMap();
 
- 	SectorMap(HeroPtr h);
 
- 	void update();
 
- 	void clear();
 
- 	void exploreNewSector(crint3 pos, int num, CCallback * cbp);
 
- 	void write(crstring fname);
 
- 	unsigned char &retreiveTile(crint3 pos);
 
- 	void makeParentBFS(crint3 source);
 
- 	int3 firstTileToGet(HeroPtr h, crint3 dst); //if h wants to reach tile dst, which tile he should visit to clear the way?
 
- 	int3 findFirstVisitableTile(HeroPtr h, crint3 dst);
 
- };
 
- //Set of buildings for different goals. Does not include any prerequisites.
 
- const BuildingID essential[] = {BuildingID::TAVERN, BuildingID::TOWN_HALL};
 
- const BuildingID goldSource[] = {BuildingID::TOWN_HALL, BuildingID::CITY_HALL, BuildingID::CAPITOL};
 
- 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};
 
- const BuildingID unitsUpgrade[] = { BuildingID::DWELL_LVL_1_UP, BuildingID::DWELL_LVL_2_UP, BuildingID::DWELL_LVL_3_UP,
 
- 	BuildingID::DWELL_LVL_4_UP, BuildingID::DWELL_LVL_5_UP, BuildingID::DWELL_LVL_6_UP, BuildingID::DWELL_LVL_7_UP};
 
- const BuildingID unitGrowth[] = { BuildingID::FORT, BuildingID::CITADEL, BuildingID::CASTLE, BuildingID::HORDE_1,
 
- 	BuildingID::HORDE_1_UPGR, BuildingID::HORDE_2, BuildingID::HORDE_2_UPGR};
 
- const BuildingID spells[] = {BuildingID::MAGES_GUILD_1, BuildingID::MAGES_GUILD_2, BuildingID::MAGES_GUILD_3,
 
- 	BuildingID::MAGES_GUILD_4, BuildingID::MAGES_GUILD_5};
 
- const BuildingID extra[] = {BuildingID::RESOURCE_SILO, BuildingID::SPECIAL_1, BuildingID::SPECIAL_2, BuildingID::SPECIAL_3,
 
- 	BuildingID::SPECIAL_4, BuildingID::SHIPYARD}; // all remaining buildings
 
- class VCAI : public CAdventureAI
 
- {
 
- public:
 
- 	//internal methods for town development
 
- 	//try build an unbuilt structure in maxDays at most (0 = indefinite)
 
- 	/*bool canBuildStructure(const CGTownInstance * t, BuildingID building, unsigned int maxDays=7);*/
 
- 	bool tryBuildStructure(const CGTownInstance * t, BuildingID building, unsigned int maxDays=7);
 
- 	//try build ANY unbuilt structure
 
- 	BuildingID canBuildAnyStructure(const CGTownInstance * t, std::vector<BuildingID> buildList, unsigned int maxDays=7);
 
- 	bool tryBuildAnyStructure(const CGTownInstance * t, std::vector<BuildingID> buildList, unsigned int maxDays=7);
 
- 	//try build first unbuilt structure
 
- 	bool tryBuildNextStructure(const CGTownInstance * t, std::vector<BuildingID> buildList, unsigned int maxDays=7);
 
- 	friend class FuzzyHelper;
 
- 	std::map<const CGObjectInstance *, const CGObjectInstance *> knownSubterraneanGates;
 
- 	//std::vector<const CGObjectInstance *> visitedThisWeek; //only OPWs
 
- 	std::map<HeroPtr, std::set<const CGTownInstance *> > townVisitsThisWeek;
 
- 	std::map<HeroPtr, Goals::TSubgoal> lockedHeroes; //TODO: allow non-elementar objectives
 
- 	std::map<HeroPtr, std::set<const CGObjectInstance *> > reservedHeroesMap; //objects reserved by specific heroes
 
- 	std::set<HeroPtr> heroesUnableToExplore; //these heroes will not be polled for exploration in current state of game
 
- 	//sets are faster to search, also do not contain duplicates
 
- 	std::set<const CGObjectInstance *> visitableObjs;
 
- 	std::set<const CGObjectInstance *> alreadyVisited;
 
- 	std::set<const CGObjectInstance *> reservedObjs; //to be visited by specific hero
 
- 	TResources saving;
 
- 	AIStatus status;
 
- 	std::string battlename;
 
- 	shared_ptr<CCallback> myCb;
 
- 	unique_ptr<boost::thread> makingTurn;
 
- 	VCAI(void);
 
- 	~VCAI(void);
 
- 	//TODO: use only smart pointers?
 
- 	void tryRealize(Goals::Explore & g);
 
- 	void tryRealize(Goals::RecruitHero & g);
 
- 	void tryRealize(Goals::VisitTile & g);
 
- 	void tryRealize(Goals::VisitHero & g);
 
- 	void tryRealize(Goals::BuildThis & g);
 
- 	void tryRealize(Goals::DigAtTile & g);
 
- 	void tryRealize(Goals::CollectRes & g);
 
- 	void tryRealize(Goals::Build & g);
 
- 	void tryRealize(Goals::Invalid & g);
 
- 	void tryRealize(Goals::AbstractGoal & g);
 
- 	int3 explorationBestNeighbour(int3 hpos, int radius, HeroPtr h);
 
- 	int3 explorationNewPoint(HeroPtr h);
 
- 	int3 explorationDesperate(HeroPtr h);
 
- 	bool canReachTile (const CGHeroInstance * h, int3 t);
 
- 	void recruitHero();
 
- 	virtual std::string getBattleAIName() const override;
 
- 	virtual void init(shared_ptr<CCallback> CB) override;
 
- 	virtual void yourTurn() override;
 
- 	virtual void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
 
- 	virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override; //TODO
 
- 	virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
 
- 	virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override; //all stacks operations between these objects become allowed, interface has to call onEnd when done
 
- 	virtual void saveGame(COSer & h, const int version) override; //saving
 
- 	virtual void loadGame(CISer & h, const int version) override; //loading
 
- 	virtual void finish() override;
 
- 	virtual void availableCreaturesChanged(const CGDwelling *town) override;
 
- 	virtual void heroMoved(const TryMoveHero & details) override;
 
- 	virtual void stackChagedCount(const StackLocation &location, const TQuantity &change, bool isAbsolute) override;
 
- 	virtual void heroInGarrisonChange(const CGTownInstance *town) override;
 
- 	virtual void centerView(int3 pos, int focusTime) override;
 
- 	virtual void tileHidden(const std::unordered_set<int3, ShashInt3> &pos) override;
 
- 	virtual void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) override;
 
- 	virtual void artifactAssembled(const ArtifactLocation &al) override;
 
- 	virtual void showTavernWindow(const CGObjectInstance *townOrTavern) override;
 
- 	virtual void showThievesGuildWindow (const CGObjectInstance * obj) override;
 
- 	virtual void playerBlocked(int reason, bool start) override;
 
- 	virtual void showPuzzleMap() override;
 
- 	virtual void showShipyardDialog(const IShipyard *obj) override;
 
- 	virtual void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
 
- 	virtual void artifactPut(const ArtifactLocation &al) override;
 
- 	virtual void artifactRemoved(const ArtifactLocation &al) override;
 
- 	virtual void stacksErased(const StackLocation &location) override;
 
- 	virtual void artifactDisassembled(const ArtifactLocation &al) override;
 
- 	virtual void heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start) override;
 
- 	virtual void availableArtifactsChanged(const CGBlackMarket *bm = nullptr) override;
 
- 	virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) override;
 
- 	virtual void tileRevealed(const std::unordered_set<int3, ShashInt3> &pos) override;
 
- 	virtual void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) override;
 
- 	virtual void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val) override;
 
- 	virtual void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) override;
 
- 	virtual void heroMovePointsChanged(const CGHeroInstance * hero) override;
 
- 	virtual void stackChangedType(const StackLocation &location, const CCreature &newType) override;
 
- 	virtual void stacksRebalanced(const StackLocation &src, const StackLocation &dst, TQuantity count) override;
 
- 	virtual void newObject(const CGObjectInstance * obj) override;
 
- 	virtual void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) override;
 
- 	virtual void playerBonusChanged(const Bonus &bonus, bool gain) override;
 
- 	virtual void newStackInserted(const StackLocation &location, const CStackInstance &stack) override;
 
- 	virtual void heroCreated(const CGHeroInstance*) override;
 
- 	virtual void advmapSpellCast(const CGHeroInstance * caster, int spellID) override;
 
- 	virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID) override;
 
- 	virtual void requestRealized(PackageApplied *pa) override;
 
- 	virtual void receivedResource(int type, int val) override;
 
- 	virtual void stacksSwapped(const StackLocation &loc1, const StackLocation &loc2) override;
 
- 	virtual void objectRemoved(const CGObjectInstance *obj) override;
 
- 	virtual void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) override;
 
- 	virtual void heroManaPointsChanged(const CGHeroInstance * hero) override;
 
- 	virtual void heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) override;
 
- 	virtual void battleResultsApplied() override;
 
- 	virtual void objectPropertyChanged(const SetObjectProperty * sop) override;
 
- 	virtual void buildChanged(const CGTownInstance *town, BuildingID buildingID, int what) override;
 
- 	virtual void heroBonusChanged(const CGHeroInstance *hero, const Bonus &bonus, bool gain) override;
 
- 	virtual void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) override;
 
- 	virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override;
 
- 	virtual void battleEnd(const BattleResult *br) override;
 
- 	void makeTurn();
 
- 	void makeTurnInternal();
 
- 	void performTypicalActions();
 
- 	void buildArmyIn(const CGTownInstance * t);
 
- 	void striveToGoal(Goals::TSubgoal ultimateGoal);
 
- 	Goals::TSubgoal striveToGoalInternal(Goals::TSubgoal ultimateGoal, bool onlyAbstract);
 
- 	void endTurn();
 
- 	void wander(HeroPtr h);
 
- 	void setGoal(HeroPtr h, Goals::TSubgoal goal);
 
- 	void completeGoal (Goals::TSubgoal goal); //safely removes goal from reserved hero
 
- 	void striveToQuest (const QuestInfo &q);
 
- 	void recruitHero(const CGTownInstance * t, bool throwing = false);
 
- 	bool isGoodForVisit(const CGObjectInstance *obj, HeroPtr h);
 
- 	std::vector<const CGObjectInstance *> getPossibleDestinations(HeroPtr h);
 
- 	void buildStructure(const CGTownInstance * t);
 
- 	//void recruitCreatures(const CGTownInstance * t);
 
- 	void recruitCreatures(const CGDwelling * d, const CArmedInstance * recruiter);
 
- 	bool canGetArmy (const CGHeroInstance * h, const CGHeroInstance * source); //can we get any better stacks from other hero?
 
- 	void pickBestCreatures(const CArmedInstance * army, const CArmedInstance * source); //called when we can't find a slot for new stack
 
- 	void moveCreaturesToHero(const CGTownInstance * t);
 
- 	bool goVisitObj(const CGObjectInstance * obj, HeroPtr h);
 
- 	void performObjectInteraction(const CGObjectInstance * obj, HeroPtr h);
 
- 	bool moveHeroToTile(int3 dst, HeroPtr h);
 
- 	void lostHero(HeroPtr h); //should remove all references to hero (assigned tasks and so on)
 
- 	void waitTillFree();
 
- 	void addVisitableObj(const CGObjectInstance *obj);
 
- 	void markObjectVisited (const CGObjectInstance *obj);
 
- 	void reserveObject (HeroPtr h, const CGObjectInstance *obj); //TODO: reserve all objects that heroes attempt to visit
 
- 	void unreserveObject (HeroPtr h, const CGObjectInstance *obj);
 
- 	void markHeroUnableToExplore (HeroPtr h);
 
- 	void markHeroAbleToExplore (HeroPtr h);
 
- 	bool isAbleToExplore (HeroPtr h);
 
- 	void clearHeroesUnableToExplore();
 
- 	void validateObject(const CGObjectInstance *obj); //checks if object is still visible and if not, removes references to it
 
- 	void validateObject(ObjectIdRef obj); //checks if object is still visible and if not, removes references to it
 
- 	void validateVisitableObjs();
 
- 	void retreiveVisitableObjs(std::vector<const CGObjectInstance *> &out, bool includeOwned = false) const;
 
- 	void retreiveVisitableObjs(std::set<const CGObjectInstance *> &out, bool includeOwned = false) const;
 
- 	std::vector<const CGObjectInstance *> getFlaggedObjects() const;
 
- 	const CGObjectInstance *lookForArt(int aid) const;
 
- 	bool isAccessible(const int3 &pos);
 
- 	HeroPtr getHeroWithGrail() const;
 
- 	const CGObjectInstance *getUnvisitedObj(const std::function<bool(const CGObjectInstance *)> &predicate);
 
- 	bool isAccessibleForHero(const int3 & pos, HeroPtr h, bool includeAllies = false) const;
 
- 	const CGTownInstance *findTownWithTavern() const;
 
- 	bool canRecruitAnyHero(const CGTownInstance * t = NULL) const;
 
- 	Goals::TSubgoal getGoal (HeroPtr h) const;
 
- 	bool canAct(HeroPtr h) const;
 
- 	std::vector<HeroPtr> getUnblockedHeroes() const;
 
- 	HeroPtr primaryHero() const;
 
- 	TResources freeResources() const; //owned resources minus gold reserve
 
- 	TResources estimateIncome() const;
 
- 	bool containsSavedRes(const TResources &cost) const;
 
- 	void checkHeroArmy (HeroPtr h);
 
- 	void requestSent(const CPackForServer *pack, int requestID) override;
 
- 	void answerQuery(QueryID queryID, int selection);
 
- 	//special function that can be called ONLY from game events handling thread and will send request ASAP
 
- 	void requestActionASAP(std::function<void()> whatToDo); 
 
- 	template <typename Handler> void registerGoals(Handler &h)
 
- 	{
 
- 		//h.template registerType<Goals::AbstractGoal, Goals::BoostHero>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::Build>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::BuildThis>();
 
- 		//h.template registerType<Goals::AbstractGoal, Goals::CIssueCommand>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::ClearWayTo>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::CollectRes>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::Conquer>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::DigAtTile>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::Explore>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::FindObj>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::GatherArmy>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::GatherTroops>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::GetArtOfType>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::GetObj>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::Invalid>();
 
- 		//h.template registerType<Goals::AbstractGoal, Goals::NotLose>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::RecruitHero>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::VisitHero>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::VisitTile>();
 
- 		h.template registerType<Goals::AbstractGoal, Goals::Win>();
 
- 	}
 
- 	template <typename Handler> void serializeInternal(Handler &h, const int version)
 
- 	{
 
- 		h & knownSubterraneanGates & townVisitsThisWeek & lockedHeroes & reservedHeroesMap; //FIXME: cannot instantiate abstract class
 
- 		h & visitableObjs & alreadyVisited & reservedObjs;
 
- 		h & saving & status & battlename;
 
- 		h & heroesUnableToExplore;
 
- 		//myCB is restored after load by init call
 
- 	}
 
- };
 
- class cannotFulfillGoalException : public std::exception
 
- {
 
- 	std::string msg;
 
- public:
 
- 	explicit cannotFulfillGoalException(crstring _Message) : msg(_Message)
 
- 	{
 
- 	}
 
- 	virtual ~cannotFulfillGoalException() throw ()
 
- 	{
 
- 	};
 
- 	const char *what() const throw () override
 
- 	{
 
- 		return msg.c_str();
 
- 	}
 
- };
 
- class goalFulfilledException : public std::exception
 
- {
 
- public:
 
- 	Goals::TSubgoal goal;
 
- 	explicit goalFulfilledException(Goals::TSubgoal Goal) : goal(Goal)
 
- 	{
 
- 	}
 
- 	virtual ~goalFulfilledException() throw ()
 
- 	{
 
- 	};
 
- 	const char *what() const throw () override
 
- 	{
 
- 		return goal->name().c_str();
 
- 	}
 
- };
 
- void makePossibleUpgrades(const CArmedInstance *obj);
 
 
  |