2017-07-13 10:26:03 +02:00
/*
* 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
*
*/
2012-02-14 21:04:45 +03:00
# pragma once
2012-09-06 13:39:48 +03:00
2013-10-18 23:17:25 +03:00
# include "AIUtility.h"
2018-12-01 10:30:37 +02:00
# include "Goals/AbstractGoal.h"
2012-09-06 13:39:48 +03:00
# include "../../lib/AI_Base.h"
# include "../../CCallback.h"
# include "../../lib/CThreadHelper.h"
2013-12-23 23:46:01 +03:00
# include "../../lib/GameConstants.h"
2012-09-06 13:39:48 +03:00
# include "../../lib/VCMI_Lib.h"
# include "../../lib/CBuildingHandler.h"
# include "../../lib/CCreatureHandler.h"
# include "../../lib/CTownHandler.h"
2015-12-02 21:05:10 +02:00
# include "../../lib/mapObjects/MiscObjects.h"
2015-02-02 10:25:26 +02:00
# include "../../lib/spells/CSpellHandler.h"
2012-09-06 13:39:48 +03:00
# include "../../lib/CondSh.h"
2018-08-12 13:31:31 +02:00
# include "Pathfinding/AIPathfinder.h"
2013-05-09 14:09:23 +03:00
2022-07-26 15:07:42 +02:00
VCMI_LIB_NAMESPACE_BEGIN
2013-10-18 23:17:25 +03:00
struct QuestInfo ;
2012-07-01 02:48:40 +03:00
2022-07-26 15:07:42 +02:00
VCMI_LIB_NAMESPACE_END
2018-09-02 17:04:38 +02:00
class AIhelper ;
2012-02-14 21:04:45 +03:00
class AIStatus
{
boost : : mutex mx ;
boost : : condition_variable cv ;
BattleState battle ;
2013-05-27 13:53:28 +03:00
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)
2018-04-07 10:44:14 +02:00
std : : vector < const CGObjectInstance * > objectsBeingVisited ;
2013-09-28 02:46:58 +03:00
bool ongoingHeroMovement ;
2015-03-08 16:23:56 +02:00
bool ongoingChannelProbing ; // true if AI currently explore bidirectional teleport channel exits
2012-07-15 18:34:00 +03:00
2012-02-14 21:04:45 +03:00
bool havingTurn ;
public :
AIStatus ( ) ;
~ AIStatus ( ) ;
void setBattle ( BattleState BS ) ;
2013-09-28 02:46:58 +03:00
void setMove ( bool ongoing ) ;
2015-03-08 16:23:56 +02:00
void setChannelProbing ( bool ongoing ) ;
bool channelProbing ( ) ;
2012-02-14 21:04:45 +03:00
BattleState getBattle ( ) ;
2013-05-27 13:53:28 +03:00
void addQuery ( QueryID ID , std : : string description ) ;
void removeQuery ( QueryID ID ) ;
2012-02-14 21:04:45 +03:00
int getQueriesCount ( ) ;
void startedTurn ( ) ;
void madeTurn ( ) ;
void waitTillFree ( ) ;
bool haveTurn ( ) ;
2013-05-27 13:53:28 +03:00
void attemptedAnsweringQuery ( QueryID queryID , int answerRequestID ) ;
2012-07-15 18:34:00 +03:00
void receivedAnswerConfirmation ( int answerRequestID , int result ) ;
2018-04-07 10:44:14 +02:00
void heroVisit ( const CGObjectInstance * obj , bool started ) ;
2013-05-09 14:09:23 +03:00
2018-04-07 10:44:14 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
2013-05-09 14:09:23 +03:00
{
2017-07-31 15:35:42 +02:00
h & battle ;
h & remainingQueries ;
h & requestToQueryID ;
h & havingTurn ;
2013-05-09 14:09:23 +03:00
}
2012-02-14 21:04:45 +03:00
} ;
2018-07-26 12:06:55 +02:00
class DLL_EXPORT VCAI : public CAdventureAI
2012-02-14 21:04:45 +03:00
{
2013-12-23 23:46:01 +03:00
public :
2012-05-19 19:22:34 +03:00
2012-03-03 13:08:01 +03:00
friend class FuzzyHelper ;
2018-07-26 12:06:55 +02:00
friend class ResourceManager ;
2018-07-29 18:27:21 +02:00
friend class BuildingManager ;
2012-03-03 13:08:01 +03:00
2018-04-07 10:44:14 +02:00
std : : map < TeleportChannelID , std : : shared_ptr < TeleportChannel > > knownTeleportChannels ;
2012-02-14 21:04:45 +03:00
std : : map < const CGObjectInstance * , const CGObjectInstance * > knownSubterraneanGates ;
2015-03-08 16:47:58 +02:00
ObjectInstanceID destinationTeleport ;
2015-12-02 16:56:26 +02:00
int3 destinationTeleportPos ;
2015-03-08 16:47:58 +02:00
std : : vector < ObjectInstanceID > teleportChannelProbingList ; //list of teleport channel exits that not visible and need to be (re-)explored
2013-04-21 15:11:13 +03:00
//std::vector<const CGObjectInstance *> visitedThisWeek; //only OPWs
2018-04-07 10:44:14 +02:00
std : : map < HeroPtr , std : : set < const CGTownInstance * > > townVisitsThisWeek ;
2012-02-14 21:04:45 +03:00
2018-08-05 09:21:41 +02:00
//part of mainLoop, but accessible from outisde
std : : vector < Goals : : TSubgoal > basicGoals ;
Goals : : TGoalVec goalsToRemove ;
Goals : : TGoalVec goalsToAdd ;
std : : map < Goals : : TSubgoal , Goals : : TGoalVec > ultimateGoalsFromBasic ; //theoreticlaly same goal can fulfill multiple basic goals
std : : set < HeroPtr > invalidPathHeroes ; //FIXME, just a workaround
2013-11-23 21:16:25 +03:00
std : : map < HeroPtr , Goals : : TSubgoal > lockedHeroes ; //TODO: allow non-elementar objectives
2018-04-07 10:44:14 +02:00
std : : map < HeroPtr , std : : set < const CGObjectInstance * > > reservedHeroesMap ; //objects reserved by specific heroes
2014-03-23 19:00:43 +03:00
std : : set < HeroPtr > heroesUnableToExplore ; //these heroes will not be polled for exploration in current state of game
2012-02-14 21:04:45 +03:00
2013-12-25 16:38:20 +03:00
//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
2018-08-05 09:21:41 +02:00
std : : map < HeroPtr , std : : set < HeroPtr > > visitedHeroes ; //visited this turn //FIXME: this is just bug workaround
2012-02-14 21:04:45 +03:00
AIStatus status ;
std : : string battlename ;
2015-12-29 04:43:33 +02:00
std : : shared_ptr < CCallback > myCb ;
2012-02-14 21:04:45 +03:00
2015-12-29 04:43:33 +02:00
std : : unique_ptr < boost : : thread > makingTurn ;
2019-05-26 17:55:22 +02:00
private :
boost : : mutex turnInterruptionMutex ;
public :
2019-01-07 23:33:31 +02:00
ObjectInstanceID selectedObject ;
2012-03-05 22:11:28 +03:00
2018-09-02 17:04:38 +02:00
AIhelper * ah ;
2018-01-13 10:43:26 +02:00
VCAI ( ) ;
virtual ~ VCAI ( ) ;
2012-02-14 21:04:45 +03:00
2013-11-23 21:16:25 +03:00
//TODO: use only smart pointers?
void tryRealize ( Goals : : Explore & g ) ;
void tryRealize ( Goals : : RecruitHero & g ) ;
void tryRealize ( Goals : : VisitTile & g ) ;
2018-08-10 16:42:55 +02:00
void tryRealize ( Goals : : VisitObj & g ) ;
2013-11-23 21:16:25 +03:00
void tryRealize ( Goals : : VisitHero & g ) ;
void tryRealize ( Goals : : BuildThis & g ) ;
void tryRealize ( Goals : : DigAtTile & g ) ;
2018-08-04 10:20:40 +02:00
void tryRealize ( Goals : : Trade & g ) ;
2018-07-26 12:06:55 +02:00
void tryRealize ( Goals : : BuyArmy & g ) ;
2013-11-23 21:16:25 +03:00
void tryRealize ( Goals : : Invalid & g ) ;
void tryRealize ( Goals : : AbstractGoal & g ) ;
2012-02-14 21:04:45 +03:00
2018-08-12 13:31:31 +02:00
bool isTileNotReserved ( const CGHeroInstance * h , int3 t ) const ; //the tile is not occupied by allied hero and the object is not reserved
2012-02-14 21:04:45 +03:00
2018-07-26 12:06:55 +02:00
std : : string getBattleAIName ( ) const override ;
2013-06-26 14:18:27 +03:00
2022-12-07 21:50:45 +02:00
void initGameInterface ( std : : shared_ptr < Environment > ENV , std : : shared_ptr < CCallback > CB ) override ;
2023-08-28 02:42:05 +02:00
void yourTurn ( QueryID queryID ) override ;
2013-06-26 14:18:27 +03:00
2023-08-19 20:43:50 +02:00
void heroGotLevel ( const CGHeroInstance * hero , 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
2018-07-26 12:06:55 +02:00
void commanderGotLevel ( const CCommanderInstance * commander , std : : vector < ui32 > skills , QueryID queryID ) override ; //TODO
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.
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
void showTeleportDialog ( TeleportChannelID channel , TTeleportExitsList exits , bool impassable , QueryID askID ) override ;
2017-06-06 06:53:51 +02:00
void showMapObjectSelectDialog ( QueryID askID , const Component & icon , const MetaString & title , const MetaString & description , const std : : vector < ObjectInstanceID > & objects ) override ;
2018-07-26 12:06:55 +02:00
void saveGame ( BinarySerializer & h , const int version ) override ; //saving
void loadGame ( BinaryDeserializer & h , const int version ) override ; //loading
void finish ( ) override ;
void availableCreaturesChanged ( const CGDwelling * town ) override ;
2022-01-25 13:19:48 +02:00
void heroMoved ( const TryMoveHero & details , bool verbose = true ) override ;
2018-07-26 12:06:55 +02:00
void heroInGarrisonChange ( const CGTownInstance * town ) override ;
void centerView ( int3 pos , int focusTime ) override ;
2023-04-16 00:48:49 +02:00
void tileHidden ( const std : : unordered_set < int3 > & pos ) override ;
2018-07-26 12:06:55 +02:00
void artifactMoved ( const ArtifactLocation & src , const ArtifactLocation & dst ) override ;
void artifactAssembled ( const ArtifactLocation & al ) override ;
void showTavernWindow ( const CGObjectInstance * townOrTavern ) override ;
void showThievesGuildWindow ( const CGObjectInstance * obj ) override ;
void playerBlocked ( int reason , bool start ) override ;
void showPuzzleMap ( ) override ;
void showShipyardDialog ( const IShipyard * obj ) override ;
void gameOver ( PlayerColor player , const EVictoryLossCheckResult & victoryLossCheckResult ) override ;
void artifactPut ( const ArtifactLocation & al ) override ;
void artifactRemoved ( const ArtifactLocation & al ) override ;
void artifactDisassembled ( const ArtifactLocation & al ) override ;
void heroVisit ( const CGHeroInstance * visitor , const CGObjectInstance * visitedObj , bool start ) override ;
void availableArtifactsChanged ( const CGBlackMarket * bm = nullptr ) override ;
void heroVisitsTown ( const CGHeroInstance * hero , const CGTownInstance * town ) override ;
2023-04-16 00:48:49 +02:00
void tileRevealed ( const std : : unordered_set < int3 > & pos ) override ;
2018-07-26 12:06:55 +02:00
void heroExchangeStarted ( ObjectInstanceID hero1 , ObjectInstanceID hero2 , QueryID query ) override ;
2023-08-19 20:43:50 +02:00
void heroPrimarySkillChanged ( const CGHeroInstance * hero , PrimarySkill which , si64 val ) override ;
2018-07-26 12:06:55 +02:00
void showRecruitmentDialog ( const CGDwelling * dwelling , const CArmedInstance * dst , int level ) override ;
void heroMovePointsChanged ( const CGHeroInstance * hero ) override ;
void garrisonsChanged ( ObjectInstanceID id1 , ObjectInstanceID id2 ) override ;
void newObject ( const CGObjectInstance * obj ) override ;
void showHillFortWindow ( const CGObjectInstance * object , const CGHeroInstance * visitor ) override ;
void playerBonusChanged ( const Bonus & bonus , bool gain ) override ;
void heroCreated ( const CGHeroInstance * ) override ;
2023-09-04 12:03:15 +02:00
void advmapSpellCast ( const CGHeroInstance * caster , SpellID spellID ) override ;
2023-03-06 01:30:21 +02:00
void showInfoDialog ( EInfoWindowMode type , const std : : string & text , const std : : vector < Component > & components , int soundID ) override ;
2018-07-26 12:06:55 +02:00
void requestRealized ( PackageApplied * pa ) override ;
void receivedResource ( ) override ;
void objectRemoved ( const CGObjectInstance * obj ) override ;
void showUniversityWindow ( const IMarket * market , const CGHeroInstance * visitor ) override ;
void heroManaPointsChanged ( const CGHeroInstance * hero ) override ;
void heroSecondarySkillChanged ( const CGHeroInstance * hero , int which , int val ) override ;
void battleResultsApplied ( ) override ;
2023-07-04 19:02:41 +02:00
void beforeObjectPropertyChanged ( const SetObjectProperty * sop ) override ;
2018-07-26 12:06:55 +02:00
void objectPropertyChanged ( const SetObjectProperty * sop ) override ;
void buildChanged ( const CGTownInstance * town , BuildingID buildingID , int what ) override ;
void heroBonusChanged ( const CGHeroInstance * hero , const Bonus & bonus , bool gain ) override ;
void showMarketWindow ( const IMarket * market , const CGHeroInstance * visitor ) override ;
2023-02-21 14:38:08 +02:00
void showWorldViewEx ( const std : : vector < ObjectPosInfo > & objectPositions , bool showTerrain ) override ;
2013-06-26 14:18:27 +03:00
2023-08-28 17:59:12 +02:00
void battleStart ( const BattleID & battleID , const CCreatureSet * army1 , const CCreatureSet * army2 , int3 tile , const CGHeroInstance * hero1 , const CGHeroInstance * hero2 , bool side , bool replayAllowed ) override ;
void battleEnd ( const BattleID & battleID , const BattleResult * br , QueryID queryID ) override ;
std : : optional < BattleAction > makeSurrenderRetreatDecision ( const BattleID & battleID , const BattleStateInfoForRetreat & battleState ) override ;
2012-02-14 21:04:45 +03:00
2018-07-26 12:06:55 +02:00
void makeTurn ( ) ;
2018-08-05 09:21:41 +02:00
void mainLoop ( ) ;
2012-02-14 21:04:45 +03:00
void performTypicalActions ( ) ;
void buildArmyIn ( const CGTownInstance * t ) ;
2013-11-23 15:30:10 +03:00
void striveToGoal ( Goals : : TSubgoal ultimateGoal ) ;
2018-08-05 09:21:41 +02:00
Goals : : TSubgoal decomposeGoal ( Goals : : TSubgoal ultimateGoal ) ;
2012-02-14 21:04:45 +03:00
void endTurn ( ) ;
2012-07-01 02:48:40 +03:00
void wander ( HeroPtr h ) ;
2013-11-23 21:16:25 +03:00
void setGoal ( HeroPtr h , Goals : : TSubgoal goal ) ;
2016-11-27 19:10:20 +02:00
void evaluateGoal ( HeroPtr h ) ; //evaluates goal assigned to hero, if any
2018-04-07 10:44:14 +02:00
void completeGoal ( Goals : : TSubgoal goal ) ; //safely removes goal from reserved hero
2012-02-14 21:04:45 +03:00
2013-02-09 20:37:38 +03:00
void recruitHero ( const CGTownInstance * t , bool throwing = false ) ;
2023-04-16 19:42:56 +02:00
bool isGoodForVisit ( const CGObjectInstance * obj , HeroPtr h , std : : optional < float > movementCostLimit = std : : nullopt ) ;
2018-08-12 13:31:31 +02:00
bool isGoodForVisit ( const CGObjectInstance * obj , HeroPtr h , const AIPath & path ) const ;
2012-03-05 22:11:28 +03:00
//void recruitCreatures(const CGTownInstance * t);
2014-09-19 00:18:49 +03:00
void recruitCreatures ( const CGDwelling * d , const CArmedInstance * recruiter ) ;
2012-03-06 21:49:23 +03:00
void pickBestCreatures ( const CArmedInstance * army , const CArmedInstance * source ) ; //called when we can't find a slot for new stack
2015-04-07 22:48:35 +02:00
void pickBestArtifacts ( const CGHeroInstance * h , const CGHeroInstance * other = nullptr ) ;
2012-02-14 21:04:45 +03:00
void moveCreaturesToHero ( const CGTownInstance * t ) ;
2012-07-01 02:48:40 +03:00
void performObjectInteraction ( const CGObjectInstance * obj , HeroPtr h ) ;
bool moveHeroToTile ( int3 dst , HeroPtr h ) ;
2018-07-29 18:27:21 +02:00
void buildStructure ( const CGTownInstance * t , BuildingID building ) ; //TODO: move to BuildingManager
2012-02-14 21:04:45 +03:00
2012-07-01 02:48:40 +03:00
void lostHero ( HeroPtr h ) ; //should remove all references to hero (assigned tasks and so on)
2012-02-14 21:04:45 +03:00
void waitTillFree ( ) ;
2018-04-07 10:44:14 +02:00
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 ) ;
2014-03-23 19:00:43 +03:00
2018-04-07 10:44:14 +02:00
void markHeroUnableToExplore ( HeroPtr h ) ;
void markHeroAbleToExplore ( HeroPtr h ) ;
bool isAbleToExplore ( HeroPtr h ) ;
2015-10-26 17:38:17 +02:00
void clearPathsInfo ( ) ;
2014-03-23 19:00:43 +03:00
2018-04-07 10:44:14 +02:00
void validateObject ( const CGObjectInstance * obj ) ; //checks if object is still visible and if not, removes references to it
2013-04-21 15:11:13 +03:00
void validateObject ( ObjectIdRef obj ) ; //checks if object is still visible and if not, removes references to it
2012-02-14 21:04:45 +03:00
void validateVisitableObjs ( ) ;
2018-04-07 10:44:14 +02:00
void retrieveVisitableObjs ( std : : vector < const CGObjectInstance * > & out , bool includeOwned = false ) const ;
2018-02-10 20:52:23 +02:00
void retrieveVisitableObjs ( ) ;
2018-07-26 12:06:55 +02:00
virtual std : : vector < const CGObjectInstance * > getFlaggedObjects ( ) const ;
2012-02-14 21:04:45 +03:00
2018-04-07 10:44:14 +02:00
const CGObjectInstance * lookForArt ( int aid ) const ;
2018-08-12 13:31:31 +02:00
bool isAccessible ( const int3 & pos ) const ;
2012-07-01 02:48:40 +03:00
HeroPtr getHeroWithGrail ( ) const ;
2012-02-16 20:10:58 +03:00
2018-04-07 10:44:14 +02:00
const CGObjectInstance * getUnvisitedObj ( const std : : function < bool ( const CGObjectInstance * ) > & predicate ) ;
2012-07-01 02:48:40 +03:00
bool isAccessibleForHero ( const int3 & pos , HeroPtr h , bool includeAllies = false ) const ;
2015-10-26 17:38:17 +02:00
//optimization - use one SM for every hero call
2012-02-14 21:04:45 +03:00
2018-04-07 10:44:14 +02:00
const CGTownInstance * findTownWithTavern ( ) const ;
2013-12-19 23:21:21 +03:00
bool canRecruitAnyHero ( const CGTownInstance * t = NULL ) const ;
2012-02-14 21:04:45 +03:00
2018-04-07 10:44:14 +02:00
Goals : : TSubgoal getGoal ( HeroPtr h ) const ;
2013-12-28 15:47:55 +03:00
bool canAct ( HeroPtr h ) const ;
2012-07-01 02:48:40 +03:00
std : : vector < HeroPtr > getUnblockedHeroes ( ) const ;
2019-02-06 23:11:51 +02:00
std : : vector < HeroPtr > getMyHeroes ( ) const ;
2012-07-01 02:48:40 +03:00
HeroPtr primaryHero ( ) const ;
2018-04-07 10:44:14 +02:00
void checkHeroArmy ( HeroPtr h ) ;
2012-03-26 01:46:14 +03:00
2018-04-07 10:44:14 +02:00
void requestSent ( const CPackForServer * pack , int requestID ) override ;
2013-05-27 13:53:28 +03:00
void answerQuery ( QueryID queryID , int selection ) ;
2012-03-26 01:46:14 +03:00
//special function that can be called ONLY from game events handling thread and will send request ASAP
2016-11-26 14:14:43 +02:00
void requestActionASAP ( std : : function < void ( ) > whatToDo ) ;
2013-05-09 14:09:23 +03:00
2018-02-25 09:31:17 +02:00
#if 0
//disabled due to issue 2890
2018-04-07 10:44:14 +02:00
template < typename Handler > void registerGoals ( Handler & h )
2014-02-20 23:18:49 +03:00
{
2014-02-21 15:27:56 +03:00
//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 > ( ) ;
2018-08-10 16:42:55 +02:00
h . template registerType < Goals : : AbstractGoal , Goals : : VisitObj > ( ) ;
2014-02-21 15:27:56 +03:00
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 > ( ) ;
2014-02-20 23:18:49 +03:00
}
2018-02-25 09:31:17 +02:00
# endif
2013-05-09 14:09:23 +03:00
2018-04-07 10:44:14 +02:00
template < typename Handler > void serializeInternal ( Handler & h , const int version )
2013-05-09 14:09:23 +03:00
{
2017-07-31 15:35:42 +02:00
h & knownTeleportChannels ;
h & knownSubterraneanGates ;
h & destinationTeleport ;
h & townVisitsThisWeek ;
2018-02-25 09:31:17 +02:00
#if 0
//disabled due to issue 2890
2017-07-31 15:35:42 +02:00
h & lockedHeroes ;
2018-02-25 09:31:17 +02:00
# else
{
ui32 length = 0 ;
h & length ;
if ( ! h . saving )
{
std : : set < ui32 > loadedPointers ;
lockedHeroes . clear ( ) ;
for ( ui32 index = 0 ; index < length ; index + + )
{
HeroPtr ignored1 ;
h & ignored1 ;
ui8 flag = 0 ;
h & flag ;
if ( flag )
{
ui32 pid = 0xffffffff ;
h & pid ;
if ( ! vstd : : contains ( loadedPointers , pid ) )
{
loadedPointers . insert ( pid ) ;
ui16 typeId = 0 ;
//this is the problem requires such hack
//we have to explicitly ignore invalid goal class type id
h & typeId ;
Goals : : AbstractGoal ignored2 ;
ignored2 . serialize ( h , version ) ;
}
}
}
}
}
# endif
2017-07-31 15:35:42 +02:00
h & reservedHeroesMap ; //FIXME: cannot instantiate abstract class
h & visitableObjs ;
h & alreadyVisited ;
h & reservedObjs ;
h & status ;
h & battlename ;
2014-03-23 19:00:43 +03:00
h & heroesUnableToExplore ;
2013-05-09 14:09:23 +03:00
//myCB is restored after load by init call
}
2012-02-14 21:04:45 +03:00
} ;
2012-10-03 12:29:55 +03:00
class cannotFulfillGoalException : public std : : exception
{
std : : string msg ;
2018-04-07 10:44:14 +02:00
2012-10-03 12:29:55 +03:00
public :
2018-04-07 10:44:14 +02:00
explicit cannotFulfillGoalException ( crstring _Message )
: msg ( _Message )
2012-10-03 12:29:55 +03:00
{
}
virtual ~ cannotFulfillGoalException ( ) throw ( )
{
} ;
2018-04-07 10:44:14 +02:00
const char * what ( ) const throw ( ) override
2012-10-03 12:29:55 +03:00
{
return msg . c_str ( ) ;
}
} ;
2018-04-07 10:44:14 +02:00
2012-10-03 12:29:55 +03:00
class goalFulfilledException : public std : : exception
{
2016-11-26 18:41:34 +02:00
std : : string msg ;
2018-04-07 10:44:14 +02:00
2012-10-03 12:29:55 +03:00
public :
2013-11-23 21:16:25 +03:00
Goals : : TSubgoal goal ;
2012-10-03 12:29:55 +03:00
2018-04-07 10:44:14 +02:00
explicit goalFulfilledException ( Goals : : TSubgoal Goal )
: goal ( Goal )
2012-10-03 12:29:55 +03:00
{
2016-11-26 18:41:34 +02:00
msg = goal - > name ( ) ;
2012-10-03 12:29:55 +03:00
}
virtual ~ goalFulfilledException ( ) throw ( )
{
} ;
2018-04-07 10:44:14 +02:00
const char * what ( ) const throw ( ) override
2012-10-03 12:29:55 +03:00
{
2016-11-26 18:41:34 +02:00
return msg . c_str ( ) ;
2012-10-03 12:29:55 +03:00
}
} ;
2012-02-14 21:04:45 +03:00
2018-04-07 10:44:14 +02:00
void makePossibleUpgrades ( const CArmedInstance * obj ) ;