From 45fccfb1a6f7b4f10447017a7c96e9b22d9c99df Mon Sep 17 00:00:00 2001 From: beegee1 Date: Tue, 16 Apr 2013 13:16:58 +0000 Subject: [PATCH] - Added new trace macro LOG_TRACE which autom. appends leaving func message - Removed old trace macros - Small refactoring in CMapEditManager - Changed documentation comments to /// style for various mapping header files --- AI/VCAI/VCAI.cpp | 171 ++++------ lib/logging/CLogger.cpp | 11 + lib/logging/CLogger.h | 28 +- lib/mapping/CMap.h | 563 +++++--------------------------- lib/mapping/CMapEditManager.cpp | 244 +++++++------- lib/mapping/CMapEditManager.h | 334 ++++++------------- lib/rmg/CMapGenerator.cpp | 3 +- lib/rmg/CMapGenerator.h | 1 - 8 files changed, 397 insertions(+), 958 deletions(-) diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 81ff8e564..53a871df7 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -428,28 +428,25 @@ bool compareDanger(const CGObjectInstance *lhs, const CGObjectInstance *rhs) VCAI::VCAI(void) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); myCb = NULL; makingTurn = NULL; - TRACE_END(logAi); } - VCAI::~VCAI(void) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); } void VCAI::availableCreaturesChanged(const CGDwelling *town) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::heroMoved(const TryMoveHero & details) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; if(details.result == TryMoveHero::TELEPORTATION) { @@ -465,84 +462,73 @@ void VCAI::heroMoved(const TryMoveHero & details) logAi->debugStream() << boost::format("Found a pair of subterranean gates between %s and %s!") % from % to; } } - TRACE_END(logAi); } void VCAI::stackChagedCount(const StackLocation &location, const TQuantity &change, bool isAbsolute) { - TRACE_BEGIN_PARAMS(logAi, "isAbsolute '%i'", isAbsolute); + LOG_TRACE_PARAMS(logAi, "isAbsolute '%i'", isAbsolute); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::heroInGarrisonChange(const CGTownInstance *town) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::centerView(int3 pos, int focusTime) { - TRACE_BEGIN_PARAMS(logAi, "focusTime '%i'", focusTime); + LOG_TRACE_PARAMS(logAi, "focusTime '%i'", focusTime); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::artifactAssembled(const ArtifactLocation &al) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::showTavernWindow(const CGObjectInstance *townOrTavern) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::showThievesGuildWindow (const CGObjectInstance * obj) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::playerBlocked(int reason) { - TRACE_BEGIN_PARAMS(logAi, "reason '%i'", reason); + LOG_TRACE_PARAMS(logAi, "reason '%i'", reason); NET_EVENT_HANDLER; if (reason == PlayerBlocked::UPCOMING_BATTLE) status.setBattle(UPCOMING_BATTLE); - TRACE_END(logAi); } void VCAI::showPuzzleMap() { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::showShipyardDialog(const IShipyard *obj) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::gameOver(PlayerColor player, bool victory) { - TRACE_BEGIN_PARAMS(logAi, "victory '%i'", victory); + LOG_TRACE_PARAMS(logAi, "victory '%i'", victory); NET_EVENT_HANDLER; logAi->debugStream() << boost::format("Player %d: I heard that player %d %s.") % playerID % player.getNum() % (victory ? "won" : "lost"); if(player == playerID) @@ -569,41 +555,36 @@ void VCAI::gameOver(PlayerColor player, bool victory) finish(); } - TRACE_END(logAi); } void VCAI::artifactPut(const ArtifactLocation &al) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::artifactRemoved(const ArtifactLocation &al) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::stacksErased(const StackLocation &location) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::artifactDisassembled(const ArtifactLocation &al) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start) { - TRACE_BEGIN_PARAMS(logAi, "start '%i'", start); + LOG_TRACE_PARAMS(logAi, "start '%i'", start); NET_EVENT_HANDLER; if (start) { @@ -613,49 +594,44 @@ void VCAI::heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visi remove_if_present(reservedHeroesMap[visitor], visitedObj); completeGoal (CGoal(GET_OBJ).sethero(visitor)); //we don't need to visit in anymore } - TRACE_END(logAi); } void VCAI::availableArtifactsChanged(const CGBlackMarket *bm /*= NULL*/) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; //buildArmyIn(town); //moveCreaturesToHero(town); - TRACE_END(logAi); } void VCAI::tileHidden(const boost::unordered_set &pos) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; // BOOST_FOREACH(int3 tile, pos) // BOOST_FOREACH(const CGObjectInstance *obj, cb->getVisitableObjs(tile)) // remove_if_present(visitableObjs, obj); visitableObjs.erase(boost::remove_if(visitableObjs, [&](const CGObjectInstance *obj){return !myCb->getObj(obj->id);}), visitableObjs.end()); - TRACE_END(logAi); } void VCAI::tileRevealed(const boost::unordered_set &pos) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; BOOST_FOREACH(int3 tile, pos) BOOST_FOREACH(const CGObjectInstance *obj, myCb->getVisitableObjs(tile)) addVisitableObj(obj); - TRACE_END(logAi); } void VCAI::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; auto firstHero = cb->getHero(hero1); @@ -672,56 +648,49 @@ void VCAI::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2) completeGoal(CGoal(VISIT_HERO).sethero(secondHero)); //TODO: exchange artifacts }); - TRACE_END(logAi); } void VCAI::heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val) { - TRACE_BEGIN_PARAMS(logAi, "which '%i', val '%i'", which % val); + LOG_TRACE_PARAMS(logAi, "which '%i', val '%i'", which % val); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) { - TRACE_BEGIN_PARAMS(logAi, "level '%i'", level); + LOG_TRACE_PARAMS(logAi, "level '%i'", level); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::heroMovePointsChanged(const CGHeroInstance * hero) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::stackChangedType(const StackLocation &location, const CCreature &newType) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::stacksRebalanced(const StackLocation &src, const StackLocation &dst, TQuantity count) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::newObject(const CGObjectInstance * obj) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; if(obj->isVisitable()) addVisitableObj(obj); - TRACE_END(logAi); } void VCAI::objectRemoved(const CGObjectInstance *obj) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; if(remove_if_present(visitableObjs, obj)) @@ -738,59 +707,52 @@ void VCAI::objectRemoved(const CGObjectInstance *obj) { lostHero(cb->getHero(obj->id)); //we can promote, since objectRemoved is killed just before actual deletion } - TRACE_END(logAi); } void VCAI::showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; requestActionASAP([=]() { makePossibleUpgrades(visitor); }); - TRACE_END(logAi); } void VCAI::playerBonusChanged(const Bonus &bonus, bool gain) { - TRACE_BEGIN_PARAMS(logAi, "gain '%i'", gain); + LOG_TRACE_PARAMS(logAi, "gain '%i'", gain); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::newStackInserted(const StackLocation &location, const CStackInstance &stack) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::heroCreated(const CGHeroInstance*) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::advmapSpellCast(const CGHeroInstance * caster, int spellID) { - TRACE_BEGIN_PARAMS(logAi, "spellID '%i", spellID); + LOG_TRACE_PARAMS(logAi, "spellID '%i", spellID); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::showInfoDialog(const std::string &text, const std::vector &components, int soundID) { - TRACE_BEGIN_PARAMS(logAi, "soundID '%i'", soundID); + LOG_TRACE_PARAMS(logAi, "soundID '%i'", soundID); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::requestRealized(PackageApplied *pa) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; if(status.haveTurn()) { @@ -803,56 +765,49 @@ void VCAI::requestRealized(PackageApplied *pa) { status.receivedAnswerConfirmation(pa->requestID, pa->result); } - TRACE_END(logAi); } void VCAI::receivedResource(int type, int val) { - TRACE_BEGIN_PARAMS(logAi, "type '%i', val '%i'", type % val); + LOG_TRACE_PARAMS(logAi, "type '%i', val '%i'", type % val); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::stacksSwapped(const StackLocation &loc1, const StackLocation &loc2) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::heroManaPointsChanged(const CGHeroInstance * hero) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) { - TRACE_BEGIN_PARAMS(logAi, "which '%', val '%'", which % val); + LOG_TRACE_PARAMS(logAi, "which '%', val '%'", which % val); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::battleResultsApplied() { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; assert(status.getBattle() == ENDING_BATTLE); status.setBattle(NO_BATTLE); - TRACE_END(logAi); } void VCAI::objectPropertyChanged(const SetObjectProperty * sop) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; if(sop->what == ObjProperty::OWNER) { @@ -860,33 +815,29 @@ void VCAI::objectPropertyChanged(const SetObjectProperty * sop) remove_if_present(visitableObjs, myCb->getObj(sop->id)); //TODO restore lost obj } - TRACE_END(logAi); } void VCAI::buildChanged(const CGTownInstance *town, BuildingID buildingID, int what) { - TRACE_BEGIN_PARAMS(logAi, "what '%i'", what); + LOG_TRACE_PARAMS(logAi, "what '%i'", what); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::heroBonusChanged(const CGHeroInstance *hero, const Bonus &bonus, bool gain) { - TRACE_BEGIN_PARAMS(logAi, "gain '%i'", gain); + LOG_TRACE_PARAMS(logAi, "gain '%i'", gain); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::init(CCallback * CB) { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); myCb = CB; cbc = CB; NET_EVENT_HANDLER; @@ -898,39 +849,35 @@ void VCAI::init(CCallback * CB) fh = new FuzzyHelper(); retreiveVisitableObjs(visitableObjs); - TRACE_END(logAi); } void VCAI::yourTurn() { - TRACE_BEGIN(logAi); + LOG_TRACE(logAi); NET_EVENT_HANDLER; status.startedTurn(); makingTurn = new boost::thread(&VCAI::makeTurn, this); - TRACE_END(logAi); } void VCAI::heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector &skills, int queryID) { - TRACE_BEGIN_PARAMS(logAi, "queryID '%i'", queryID); + LOG_TRACE_PARAMS(logAi, "queryID '%i'", queryID); NET_EVENT_HANDLER; status.addQuery(queryID, boost::str(boost::format("Hero %s got level %d") % hero->name % hero->level)); requestActionASAP([=]{ answerQuery(queryID, 0); }); - TRACE_END(logAi); } void VCAI::commanderGotLevel (const CCommanderInstance * commander, std::vector skills, int queryID) { - TRACE_BEGIN_PARAMS(logAi, "queryID '%i'", queryID); + LOG_TRACE_PARAMS(logAi, "queryID '%i'", queryID); NET_EVENT_HANDLER; status.addQuery(queryID, boost::str(boost::format("Commander %s of %s got level %d") % commander->name % commander->armyObj->nodeName() % (int)commander->level)); requestActionASAP([=]{ answerQuery(queryID, 0); }); - TRACE_END(logAi); } void VCAI::showBlockingDialog(const std::string &text, const std::vector &components, ui32 askID, const int soundID, bool selection, bool cancel) { - TRACE_BEGIN_PARAMS(logAi, "text '%s', askID '%i', soundID '%i', selection '%i', cancel '%i'", text % askID % soundID % selection % cancel); + LOG_TRACE_PARAMS(logAi, "text '%s', askID '%i', soundID '%i', selection '%i', cancel '%i'", text % askID % soundID % selection % cancel); NET_EVENT_HANDLER; int sel = 0; status.addQuery(askID, boost::str(boost::format("Blocking dialog query with %d components - %s") @@ -946,12 +893,11 @@ void VCAI::showBlockingDialog(const std::string &text, const std::vectornodeName() : "NONE"; @@ -965,21 +911,18 @@ void VCAI::showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *do pickBestCreatures (down, up); answerQuery(queryID, 0); }); - TRACE_END(logAi); } void VCAI::serialize(COSer &h, const int version) { - TRACE_BEGIN_PARAMS(logAi, "version '%i'", version); + LOG_TRACE_PARAMS(logAi, "version '%i'", version); NET_EVENT_HANDLER; - TRACE_END(logAi); } void VCAI::serialize(CISer &h, const int version) { - TRACE_BEGIN_PARAMS(logAi, "version '%i'", version); + LOG_TRACE_PARAMS(logAi, "version '%i'", version); NET_EVENT_HANDLER; - TRACE_END(logAi); } void makePossibleUpgrades(const CArmedInstance *obj) diff --git a/lib/logging/CLogger.cpp b/lib/logging/CLogger.cpp index c494586b4..760df4e4c 100644 --- a/lib/logging/CLogger.cpp +++ b/lib/logging/CLogger.cpp @@ -219,6 +219,17 @@ bool CLogger::isTraceEnabled() const return getEffectiveLevel() <= ELogLevel::TRACE; } +CTraceLogger::CTraceLogger(const CLogger * logger, const std::string & beginMessage, const std::string & endMessage) + : logger(logger), endMessage(endMessage) +{ + logger->traceStream() << beginMessage; +} + +CTraceLogger::~CTraceLogger() +{ + logger->traceStream() << endMessage; +} + boost::recursive_mutex CLogManager::smx; CLogManager & CLogManager::get() diff --git a/lib/logging/CLogger.h b/lib/logging/CLogger.h index 2f6adc22e..d06a56f0c 100644 --- a/lib/logging/CLogger.h +++ b/lib/logging/CLogger.h @@ -126,15 +126,25 @@ extern DLL_LINKAGE CLogger * logBonus; extern DLL_LINKAGE CLogger * logNetwork; extern DLL_LINKAGE CLogger * logAi; -/// Macros for tracing the control flow of the application conveniently. If the TRACE_BEGIN macro is used it should be -/// the first statement in the function, whereas the TRACE_END should be last one before a return statement. -/// Logging traces via this macro have almost no impact when the trace is disabled. -#define TRACE_BEGIN(logger) logger->traceStream() << boost::format("Entering %s.") % BOOST_CURRENT_FUNCTION; -#define TRACE_BEGIN_PARAMS(logger, formatStr, params) if(logger->isTraceEnabled()) logger->traceStream() << \ - boost::format("Entering %s: " + std::string(formatStr) + ".") % BOOST_CURRENT_FUNCTION % params; -#define TRACE_END(logger) logger->traceStream() << boost::format("Leaving %s.") % BOOST_CURRENT_FUNCTION; -#define TRACE_END_PARAMS(logger, formatStr, params) if(logger->isTraceEnabled()) logger->traceStream() << \ - boost::format("Leaving %s: " + std::string(formatStr) + ".") % BOOST_CURRENT_FUNCTION % params; +/// RAII class for tracing the program execution. +/// It prints "Leaving function XYZ" automatically when the object gets destructed. +class DLL_LINKAGE CTraceLogger +{ +public: + CTraceLogger(const CLogger * logger, const std::string & beginMessage, const std::string & endMessage); + ~CTraceLogger(); + +private: + const CLogger * logger; + std::string endMessage; +}; + +/// Macros for tracing the control flow of the application conveniently. If the LOG_TRACE macro is used it should be +/// the first statement in the function. Logging traces via this macro have almost no impact when the trace is disabled. +#define LOG_TRACE(logger) if(logger->isTraceEnabled()) CTraceLogger ctl00(logger, boost::str(boost::format("Entering %s.") % BOOST_CURRENT_FUNCTION), \ + boost::str(boost::format("Leaving %s.") % BOOST_CURRENT_FUNCTION)) +#define LOG_TRACE_PARAMS(logger, formatStr, params) if(logger->isTraceEnabled()) CTraceLogger ctl00(logger, boost::str(boost::format("Entering %s: " + \ + std::string(formatStr) + ".") % BOOST_CURRENT_FUNCTION % params), boost::str(boost::format("Leaving %s.") % BOOST_CURRENT_FUNCTION)) /* ---------------------------------------------------------------------------- */ /* Implementation/Detail classes, Private API */ diff --git a/lib/mapping/CMap.h b/lib/mapping/CMap.h index 94eaaa7a0..432e8d202 100644 --- a/lib/mapping/CMap.h +++ b/lib/mapping/CMap.h @@ -29,25 +29,14 @@ class IModableArt; class IQuestObject; class CInputStream; -/** - * The hero name struct consists of the hero id and the hero name. - */ +/// The hero name struct consists of the hero id and the hero name. struct DLL_LINKAGE SHeroName { - /** - * Default c-tor. - */ SHeroName(); - /** the id of the hero */ int heroId; - - /** the name of the hero */ std::string heroName; - /** - * Serialize method. - */ template void serialize(Handler & h, const int version) { @@ -67,91 +56,39 @@ enum EAiTactic }; } -/** - * The player info constains data about which factions are allowed, AI tactical settings, - * the main hero name, where to generate the hero, whether the faction should be selected randomly,... - */ +/// The player info constains data about which factions are allowed, AI tactical settings, +/// the main hero name, where to generate the hero, whether the faction should be selected randomly,... struct DLL_LINKAGE PlayerInfo { - /** - * Default constructor. - */ PlayerInfo(); - /** - * Gets the default faction id or -1 for a random faction. - * - * @return the default faction id or -1 for a random faction - */ + /// Gets the default faction id or -1 for a random faction. si8 defaultCastle() const; - - /** - * Gets -1 for random hero. - * - * @return -1 for random hero - */ + /// Gets the default hero id or -1 for a random hero. si8 defaultHero() const; - bool canAnyonePlay() const; - /** True if the player can be played by a human. */ bool canHumanPlay; - - /** True if th player can be played by the computer */ bool canComputerPlay; - - /** Defines the tactical setting of the AI. The default value is EAiTactic::RANDOM. */ - EAiTactic::EAiTactic aiTactic; - - /** A list of unique IDs of allowed factions. */ + EAiTactic::EAiTactic aiTactic; /// The default value is EAiTactic::RANDOM. std::set allowedFactions; - - /** Unused. True if the faction should be chosen randomly. */ bool isFactionRandom; - - /** Specifies the ID of the main hero with chosen portrait. The default value is -1. */ - si32 mainHeroPortrait; - - /** The name of the main hero. */ + si32 mainHeroPortrait; /// The default value is -1. std::string mainHeroName; - - /** The list of renamed heroes. */ - std::vector heroesNames; - - /** True if the player has a main town. The default value is false. */ - bool hasMainTown; - - /** True if the main hero should be generated at the main town. The default value is false. */ - bool generateHeroAtMainTown; - - /** The position of the main town. */ + std::vector heroesNames; /// List of renamed heroes. + bool hasMainTown; /// The default value is false. + bool generateHeroAtMainTown; /// The default value is false. int3 posOfMainTown; + TeamID team; /// The default value is 255 representing that the player belongs to no team. - /** The team id to which the player belongs to. The default value is 255 representing that the player belongs to no team. */ - TeamID team; - - /** Unused. True if a hero should be generated. */ - bool generateHero; - - /** Unknown and unused. */ - si32 p7; - - /** Player has a (custom?) hero */ - bool hasHero; - - /** ID of custom hero, -1 if none */ - si32 customHeroID; - - /** - * Unused. Count of hero placeholders containing hero type. - * WARNING: powerPlaceholders sometimes gives false 0 (eg. even if there is one placeholder), - * maybe different meaning ??? - */ + bool generateHero; /// Unused. + si32 p7; /// Unknown and unused. + bool hasHero; /// Player has a (custom?) hero + si32 customHeroID; /// ID of custom hero, -1 if none + /// Unused. Count of hero placeholders containing hero type. + /// WARNING: powerPlaceholders sometimes gives false 0 (eg. even if there is one placeholder), maybe different meaning ??? ui8 powerPlaceholders; - /** - * Serialize method. - */ template void serialize(Handler & h, const int version) { @@ -161,31 +98,16 @@ struct DLL_LINKAGE PlayerInfo } }; -/** - * The loss condition describes the condition to lose the game. (e.g. lose all own heroes/castles) - */ +/// The loss condition describes the condition to lose the game. (e.g. lose all own heroes/castles) struct DLL_LINKAGE LossCondition { - /** - * Default constructor. - */ LossCondition(); - /** specifies the condition type */ ELossConditionType::ELossConditionType typeOfLossCon; - - /** the position of an object which mustn't be lost */ - int3 pos; - - /** time limit in days, -1 if not used */ - si32 timeLimit; - - /** set during map parsing: hero/town (depending on typeOfLossCon); nullptr if not used */ + int3 pos; /// the position of an object which mustn't be lost + si32 timeLimit; /// time limit in days, -1 if not used const CGObjectInstance * obj; - /** - * Serialize method. - */ template void serialize(Handler & h, const int version) { @@ -193,41 +115,25 @@ struct DLL_LINKAGE LossCondition } }; -/** - * The victory condition describes the condition to win the game. (e.g. defeat all enemy heroes/castles, - * receive a specific artifact, ...) - */ +/// The victory condition describes the condition to win the game. (e.g. defeat all enemy heroes/castles, +/// receive a specific artifact, ...) struct DLL_LINKAGE VictoryCondition { - /** - * Default constructor. - */ VictoryCondition(); - /** specifies the condition type */ EVictoryConditionType::EVictoryConditionType condition; - - /** true if a normal victory is allowed (defeat all enemy towns, heroes) */ - bool allowNormalVictory; - - /** true if this victory condition also applies to the AI */ + bool allowNormalVictory; /// true if a normal victory is allowed (defeat all enemy towns, heroes) bool appliesToAI; - - /** pos of city to upgrade (3); pos of town to build grail, {-1,-1,-1} if not relevant (4); hero pos (5); town pos(6); monster pos (7); destination pos(8) */ + /// pos of city to upgrade (3); pos of town to build grail, {-1,-1,-1} if not relevant (4); hero pos (5); town pos(6); + /// monster pos (7); destination pos(8) int3 pos; - - /** artifact ID (0); monster ID (1); resource ID (2); needed fort level in upgraded town (3); artifact ID (8) */ + /// artifact ID (0); monster ID (1); resource ID (2); needed fort level in upgraded town (3); artifact ID (8) si32 objectId; - - /** needed count for creatures (1) / resource (2); upgraded town hall level (3); */ + /// needed count for creatures (1) / resource (2); upgraded town hall level (3); si32 count; - - /** object of specific monster / city / hero instance (NULL if not used); set during map parsing */ + /// object of specific monster / city / hero instance (NULL if not used); set during map parsing const CGObjectInstance * obj; - /** - * Serialize method. - */ template void serialize(Handler & h, const int version) { @@ -235,20 +141,12 @@ struct DLL_LINKAGE VictoryCondition } }; -/** - * The rumor struct consists of a rumor name and text. - */ +/// The rumor struct consists of a rumor name and text. struct DLL_LINKAGE Rumor { - /** the name of the rumor */ std::string name; - - /** the content of the rumor */ std::string text; - /** - * Serialize method. - */ template void serialize(Handler & h, const int version) { @@ -256,31 +154,16 @@ struct DLL_LINKAGE Rumor } }; -/** - * The disposed hero struct describes which hero can be hired from which player. - */ +/// The disposed hero struct describes which hero can be hired from which player. struct DLL_LINKAGE DisposedHero { - /** - * Default c-tor. - */ DisposedHero(); - /** the id of the hero */ ui32 heroId; - - /** the portrait id of the hero, 0xFF is default */ - ui16 portrait; - - /** the name of the hero */ + ui16 portrait; /// The portrait id of the hero, 0xFF is default. std::string name; + ui8 players; /// Who can hire this hero (bitfield). - /** who can hire this hero (bitfield) */ - ui8 players; - - /** - * Serialize method. - */ template void serialize(Handler & h, const int version) { @@ -288,61 +171,25 @@ struct DLL_LINKAGE DisposedHero } }; -/** - * The map event is an event which e.g. gives or takes resources of a specific - * amount to/from players and can appear regularly or once a time. - */ +/// The map event is an event which e.g. gives or takes resources of a specific +/// amount to/from players and can appear regularly or once a time. class DLL_LINKAGE CMapEvent { public: - /** - * Default c-tor. - */ CMapEvent(); - /** - * Returns true if this map event occurs earlier than the other map event for the first time. - * - * @param other the other map event to compare with - * @return true if this event occurs earlier than the other map event, false if not - */ bool earlierThan(const CMapEvent & other) const; - - /** - * Returns true if this map event occurs earlier than or at the same day than the other map event for the first time. - * - * @param other the other map event to compare with - * @return true if this event occurs earlier than or at the same day than the other map event, false if not - */ bool earlierThanOrEqual(const CMapEvent & other) const; - /** the name of the event */ std::string name; - - /** the message to display */ std::string message; - - /** gained or taken resources */ TResources resources; - - /** affected players */ - ui8 players; - - /** affected humans */ + ui8 players; // affected players, bit field? ui8 humanAffected; - - /** affacted computer players */ ui8 computerAffected; - - /** the day counted continously when the event happens */ ui32 firstOccurence; + ui32 nextOccurence; /// specifies after how many days the event will occur the next time; 0 if event occurs only one time - /** specifies after how many days the event will occur the next time; 0 if event occurs only one time */ - ui32 nextOccurence; - - /** - * Serialize method. - */ template void serialize(Handler & h, const int version) { @@ -351,29 +198,16 @@ public: } }; -/** - * The castle event builds/adds buildings/creatures for a specific town. - */ +/// The castle event builds/adds buildings/creatures for a specific town. class DLL_LINKAGE CCastleEvent: public CMapEvent { public: - /** - * Default c-tor. - */ CCastleEvent(); - /** build specific buildings */ std::set buildings; - - /** additional creatures in i-th level dwelling */ std::vector creatures; - - /** owner of this event */ CGTownInstance * town; - /** - * Serialize method. - */ template void serialize(Handler & h, const int version) { @@ -398,109 +232,38 @@ enum ERoadType }; } -/** - * The terrain tile describes the terrain type and the visual representation of the terrain. - * Furthermore the struct defines whether the tile is visitable or/and blocked and which objects reside in it. - */ +/// The terrain tile describes the terrain type and the visual representation of the terrain. +/// Furthermore the struct defines whether the tile is visitable or/and blocked and which objects reside in it. struct DLL_LINKAGE TerrainTile { - /** - * Default c-tor. - */ TerrainTile(); - /** - * Gets true if the terrain is not a rock. If from is water/land, same type is also required. - * - * @param from - * @return - */ + /// Gets true if the terrain is not a rock. If from is water/land, same type is also required. bool entrableTerrain(const TerrainTile * from = NULL) const; - - /** - * Gets true if the terrain is not a rock. If from is water/land, same type is also required. - * - * @param allowLand - * @param allowSea - * @return - */ bool entrableTerrain(bool allowLand, bool allowSea) const; - - /** - * Checks for blocking objects and terraint type (water / land). - * - * @param from - * @return - */ + /// Checks for blocking objects and terraint type (water / land). bool isClear(const TerrainTile * from = NULL) const; - - /** - * Gets the ID of the top visitable object or -1 if there is none. - * - * @return the ID of the top visitable object or -1 if there is none - */ + /// Gets the ID of the top visitable object or -1 if there is none. int topVisitableId() const; - - /** - * Gets true if the terrain type is water. - * - * @return true if the terrain type is water - */ bool isWater() const; - - /** - * Gets true if the terrain tile is coastal. - * - * @return true if the terrain tile is coastal - */ bool isCoastal() const; - - /** - * Gets true if the terrain tile has favourable winds. - * - * @return true if the terrain tile has favourable winds - */ bool hasFavourableWinds() const; - /** the type of terrain */ ETerrainType terType; - - /** the visual representation of the terrain */ ui8 terView; - - /** the type of the river. 0 if there is no river */ ERiverType::ERiverType riverType; - - /** the direction of the river */ ui8 riverDir; - - /** the type of the road. 0 if there is no river */ ERoadType::ERoadType roadType; - - /** the direction of the road */ ui8 roadDir; - - /** - * first two bits - how to rotate terrain graphic (next two - river graphic, next two - road); - * 7th bit - whether tile is coastal (allows disembarking if land or block movement if water); 8th bit - Favourable Winds effect - */ + /// first two bits - how to rotate terrain graphic (next two - river graphic, next two - road); + /// 7th bit - whether tile is coastal (allows disembarking if land or block movement if water); 8th bit - Favourable Winds effect ui8 extTileFlags; - - /** true if it is visitable, false if not */ bool visitable; - - /** true if it is blocked, false if not */ bool blocked; - /** pointers to objects which the hero can visit while being on this tile */ std::vector visitableObjects; - - /** pointers to objects that are blocking this tile */ std::vector blockingObjects; - /** - * Serialize method. - */ template void serialize(Handler & h, const int version) { @@ -522,80 +285,31 @@ enum EMapFormat }; } -/** - * The map header holds information about loss/victory condition, - * map format, version, players, height, width,... - */ +/// The map header holds information about loss/victory condition,map format, version, players, height, width,... class DLL_LINKAGE CMapHeader { public: - /** - * Default constructor. - */ CMapHeader(); - - /** - * D-tor. - */ virtual ~CMapHeader(); - /** The version of the map. The default value is EMapFormat::SOD. */ - EMapFormat::EMapFormat version; - - /** The height of the map. The default value is 72. */ - si32 height; - - /** The width of the map. The default value is 72. */ - si32 width; - - /** Specifies if the map has two levels. The default value is true. */ - bool twoLevel; - - /** The name of the map. */ + EMapFormat::EMapFormat version; /// The default value is EMapFormat::SOD. + si32 height; /// The default value is 72. + si32 width; /// The default value is 72. + bool twoLevel; /// The default value is true. std::string name; - - /** The description of the map. */ std::string description; - - /** - * Specifies the difficulty of the map ranging from 0 easy to 4 impossible. - * The default value is 1 representing a normal map difficulty. - */ - ui8 difficulty; - - /** - * Specifies the maximum level to reach for a hero. A value of 0 states that there is no - * maximum level for heroes. - */ + ui8 difficulty; /// The default value is 1 representing a normal map difficulty. + /// Specifies the maximum level to reach for a hero. A value of 0 states that there is no + /// maximum level for heroes. This is the default value. ui8 levelLimit; - - /** Specifies the loss condition. The default value is lose all your towns and heroes. */ - LossCondition lossCondition; - - /** Specifies the victory condition. The default value is defeat all enemies. */ - VictoryCondition victoryCondition; - - /** A list containing information about players. The default size of the vector is PlayerColor::PLAYER_LIMIT. */ - std::vector players; - - /** The number of teams. */ + LossCondition lossCondition; /// The default value is lose all your towns and heroes. + VictoryCondition victoryCondition; /// The default value is defeat all enemies. + std::vector players; /// The default size of the vector is PlayerColor::PLAYER_LIMIT. ui8 howManyTeams; - - /** - * A list of allowed heroes. The index is the hero id and the value = hero allowed. - * The default value is a list of default allowed heroes. See CHeroHandler::getDefaultAllowedHeroes for more info. - */ std::vector allowedHeroes; - - /** A list of placeholded heroes. The index is the id of a hero type. */ std::vector placeholdedHeroes; + bool areAnyPlayers; /// Unused. True if there are any playable players on the map. - /** Unused. True if there are any playable players on the map. */ - bool areAnyPlayers; - - /** - * Serialize method. - */ template void serialize(Handler & h, const int Version) { @@ -604,176 +318,55 @@ public: } }; -/** - * The map contains the map header, the tiles of the terrain, objects, - * heroes, towns, rumors... - */ +/// The map contains the map header, the tiles of the terrain, objects, heroes, towns, rumors... class DLL_LINKAGE CMap : public CMapHeader { public: - /** - * Default constructor. - */ CMap(); - - /** - * Destructor. - */ ~CMap(); - - /** - * Erases an artifact instance. - * - * @param art the artifact to erase - */ - void eraseArtifactInstance(CArtifactInstance * art); - - /** - * Gets the topmost object or the lowermost object depending on the flag - * lookForHero from the specified position. - * - * @param pos the position of the tile - * @param lookForHero true if you want to get the lowermost object, false if - * you want to get the topmost object - * @return the object at the given position and level - */ - const CGObjectInstance * getObjectiveObjectFrom(int3 pos, bool lookForHero); - - /** - * Sets the victory/loss condition objectives. - */ - void checkForObjectives(); - - /** - * Adds an visitable/blocking object to a terrain tile. - * - * @param obj the visitable/blocking object to add to a tile - */ - void addBlockVisTiles(CGObjectInstance * obj); - - /** - * Removes an visitable/blocking object from a terrain tile. - * - * @param obj the visitable/blocking object to remove from a tile - * @param total - */ - void removeBlockVisTiles(CGObjectInstance * obj, bool total = false); - - /** - * Gets the terrain tile of the specified position. - * - * @param tile the position of the tile - * @return the terrain tile of the specified position - */ - TerrainTile & getTile(const int3 & tile); - - /** - * Gets the terrain tile as a const of the specified position. - * - * @param tile the position of the tile - * @return the terrain tile as a const of the specified position - */ - const TerrainTile & getTile(const int3 & tile) const; - - /** - * Gets the hero with the given id. - * @param heroId the hero id - * @return the hero with the given id - */ - CGHeroInstance * getHero(int heroId); - - /** - * Validates if the position is in the bounds of the map. - * - * @param pos the position to test - * @return true if the position is in the bounds of the map - */ - bool isInTheMap(const int3 & pos) const; - - /** - * Validates if the tile at the given position is a water terrain type. - * - * @param pos the position to test - * @return true if the tile at the given position is a water terrain type - */ - bool isWaterTile(const int3 & pos) const; - - /** - * Adds the specified artifact instance to the list of artifacts of this map. - * - * @param art the artifact which should be added to the list of artifacts - */ - void addNewArtifactInstance(CArtifactInstance * art); - - /** - * Adds the specified quest instance to the list of quests. - * - * @param quest the quest object which should be added to the list of quests - */ - void addQuest(CGObjectInstance * quest); - - /** - * Initializes the terrain of the map by allocating memory. - */ void initTerrain(); - /** the checksum of the map */ + TerrainTile & getTile(const int3 & tile); + const TerrainTile & getTile(const int3 & tile) const; + bool isInTheMap(const int3 & pos) const; + bool isWaterTile(const int3 & pos) const; + + void addBlockVisTiles(CGObjectInstance * obj); + void removeBlockVisTiles(CGObjectInstance * obj, bool total = false); + + void addNewArtifactInstance(CArtifactInstance * art); + void eraseArtifactInstance(CArtifactInstance * art); + void addQuest(CGObjectInstance * quest); + + /// Gets the topmost object or the lowermost object depending on the flag lookForHero from the specified position. + const CGObjectInstance * getObjectiveObjectFrom(int3 pos, bool lookForHero); + CGHeroInstance * getHero(int heroId); + + /// Sets the victory/loss condition objectives ?? + void checkForObjectives(); + ui32 checksum; - - /** a 3-dimensional array of terrain tiles, access is as follows: x, y, level. where level=1 is underground */ + /// a 3-dimensional array of terrain tiles, access is as follows: x, y, level. where level=1 is underground TerrainTile*** terrain; - - /** list of rumors */ std::vector rumors; - - /** list of disposed heroes */ std::vector disposedHeroes; - - /** list of predefined heroes */ std::vector > predefinedHeroes; - - /** list of .def files with definitions from .h3m (may be custom) */ std::vector > customDefs; - - /** list of allowed spells, index is the spell id */ std::vector allowedSpell; - - /** list of allowed artifacts, index is the artifact id */ std::vector allowedArtifact; - - /** list of allowed abilities, index is the ability id */ std::vector allowedAbilities; - - /** list of map events */ std::list events; - - /** specifies the position of the grail */ int3 grailPos; - - /** specifies the radius of the grail */ int grailRadious; - /** list of objects */ std::vector< ConstTransitivePtr > objects; - - /** list of heroes */ std::vector< ConstTransitivePtr > heroes; - - /** list of towns */ std::vector< ConstTransitivePtr > towns; - - /** list of artifacts */ std::vector< ConstTransitivePtr > artInstances; - - /** list of quests */ std::vector< ConstTransitivePtr > quests; - - /** associative list to identify which hero/creature id belongs to which object id(index for objects) */ + /// associative list to identify which hero/creature id belongs to which object id(index for objects) bmap questIdentifierToId; - /** - * Serialize method. - */ template void serialize(Handler &h, const int formatVersion) { diff --git a/lib/mapping/CMapEditManager.cpp b/lib/mapping/CMapEditManager.cpp index 70864c803..5c6d7ff73 100644 --- a/lib/mapping/CMapEditManager.cpp +++ b/lib/mapping/CMapEditManager.cpp @@ -5,119 +5,8 @@ #include "../filesystem/CResourceLoader.h" #include "../CDefObjInfoHandler.h" -const std::string TerrainViewPattern::FLIP_MODE_SAME_IMAGE = "sameImage"; -const std::string TerrainViewPattern::FLIP_MODE_DIFF_IMAGES = "diffImages"; - -const std::string TerrainViewPattern::RULE_DIRT = "D"; -const std::string TerrainViewPattern::RULE_SAND = "S"; -const std::string TerrainViewPattern::RULE_TRANSITION = "T"; -const std::string TerrainViewPattern::RULE_NATIVE = "N"; -const std::string TerrainViewPattern::RULE_ANY = "?"; - -TerrainViewPattern::TerrainViewPattern() : minPoints(0), flipMode(FLIP_MODE_SAME_IMAGE), - terGroup(ETerrainGroup::NORMAL) -{ - -} - -TerrainViewPattern::WeightedRule::WeightedRule() : points(0) -{ - -} - -bool TerrainViewPattern::WeightedRule::isStandardRule() const -{ - return TerrainViewPattern::RULE_ANY == name || TerrainViewPattern::RULE_DIRT == name - || TerrainViewPattern::RULE_NATIVE == name || TerrainViewPattern::RULE_SAND == name - || TerrainViewPattern::RULE_TRANSITION == name; -} - -CTerrainViewPatternConfig::CTerrainViewPatternConfig() -{ - const JsonNode config(ResourceID("config/terrainViewPatterns.json")); - const std::map terGroups - = boost::assign::map_list_of("normal", ETerrainGroup::NORMAL)("dirt", ETerrainGroup::DIRT) - ("sand", ETerrainGroup::SAND)("water", ETerrainGroup::WATER)("rock", ETerrainGroup::ROCK); - BOOST_FOREACH(auto terMapping, terGroups) - { - BOOST_FOREACH(const JsonNode & ptrnNode, config[terMapping.first].Vector()) - { - TerrainViewPattern pattern; - - // Read pattern data - const JsonVector & data = ptrnNode["data"].Vector(); - if(data.size() != 9) - { - throw std::runtime_error("Size of pattern's data vector has to be 9."); - } - for(int i = 0; i < data.size(); ++i) - { - std::string cell = data[i].String(); - boost::algorithm::erase_all(cell, " "); - std::vector rules; - boost::split(rules, cell, boost::is_any_of(",")); - BOOST_FOREACH(std::string ruleStr, rules) - { - std::vector ruleParts; - boost::split(ruleParts, ruleStr, boost::is_any_of("-")); - TerrainViewPattern::WeightedRule rule; - rule.name = ruleParts[0]; - if(ruleParts.size() > 1) - { - rule.points = boost::lexical_cast(ruleParts[1]); - } - pattern.data[i].push_back(rule); - } - } - - // Read mapping - std::string mappingStr = ptrnNode["mapping"].String(); - boost::algorithm::erase_all(mappingStr, " "); - std::vector mappings; - boost::split(mappings, mappingStr, boost::is_any_of(",")); - BOOST_FOREACH(std::string mapping, mappings) - { - std::vector range; - boost::split(range, mapping, boost::is_any_of("-")); - pattern.mapping.push_back(std::make_pair(boost::lexical_cast(range[0]), - boost::lexical_cast(range.size() > 1 ? range[1] : range[0]))); - } - - // Read optional attributes - pattern.id = ptrnNode["id"].String(); - pattern.minPoints = static_cast(ptrnNode["minPoints"].Float()); - pattern.flipMode = ptrnNode["flipMode"].String(); - if(pattern.flipMode.empty()) - { - pattern.flipMode = TerrainViewPattern::FLIP_MODE_SAME_IMAGE; - } - - pattern.terGroup = terMapping.second; - patterns[terMapping.second].push_back(pattern); - } - } -} - -const std::vector & CTerrainViewPatternConfig::getPatternsForGroup(ETerrainGroup::ETerrainGroup terGroup) const -{ - return patterns.find(terGroup)->second; -} - -const TerrainViewPattern & CTerrainViewPatternConfig::getPatternById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const -{ - const std::vector & groupPatterns = getPatternsForGroup(terGroup); - BOOST_FOREACH(const TerrainViewPattern & pattern, groupPatterns) - { - if(id == pattern.id) - { - return pattern; - } - } - throw std::runtime_error("Pattern with ID not found: " + id); -} - -CMapEditManager::CMapEditManager(const CTerrainViewPatternConfig * terViewPatternConfig, CMap * map, int randomSeed /*= std::time(nullptr)*/) - : map(map), terViewPatternConfig(terViewPatternConfig) +CMapEditManager::CMapEditManager(CMap * map, int randomSeed /*= std::time(nullptr)*/) + : map(map) { gen.seed(randomSeed); } @@ -164,7 +53,7 @@ void CMapEditManager::updateTerrainViews(int posx, int posy, int width, int heig for(int j = posy; j < posy + height; ++j) { const std::vector & patterns = - terViewPatternConfig->getPatternsForGroup(getTerrainGroup(map->terrain[i][j][mapLevel].terType)); + CTerrainViewPatternConfig::get().getPatternsForGroup(getTerrainGroup(map->terrain[i][j][mapLevel].terType)); // Detect a pattern which fits best int bestPattern = -1, bestFlip = -1; @@ -282,7 +171,7 @@ CMapEditManager::ValidationResult CMapEditManager::validateTerrainView(int posx, { if(recDepth == 0) { - const TerrainViewPattern & patternForRule = terViewPatternConfig->getPatternById(pattern.terGroup, rule.name); + const TerrainViewPattern & patternForRule = CTerrainViewPatternConfig::get().getPatternById(pattern.terGroup, rule.name); ValidationResult rslt = validateTerrainView(cx, cy, mapLevel, patternForRule, 1); if(!rslt.result) { @@ -432,3 +321,128 @@ CMapEditManager::ValidationResult::ValidationResult(bool result, const std::stri { } + +const std::string TerrainViewPattern::FLIP_MODE_SAME_IMAGE = "sameImage"; +const std::string TerrainViewPattern::FLIP_MODE_DIFF_IMAGES = "diffImages"; + +const std::string TerrainViewPattern::RULE_DIRT = "D"; +const std::string TerrainViewPattern::RULE_SAND = "S"; +const std::string TerrainViewPattern::RULE_TRANSITION = "T"; +const std::string TerrainViewPattern::RULE_NATIVE = "N"; +const std::string TerrainViewPattern::RULE_ANY = "?"; + +TerrainViewPattern::TerrainViewPattern() : minPoints(0), flipMode(FLIP_MODE_SAME_IMAGE), + terGroup(ETerrainGroup::NORMAL) +{ + +} + +TerrainViewPattern::WeightedRule::WeightedRule() : points(0) +{ + +} + +bool TerrainViewPattern::WeightedRule::isStandardRule() const +{ + return TerrainViewPattern::RULE_ANY == name || TerrainViewPattern::RULE_DIRT == name + || TerrainViewPattern::RULE_NATIVE == name || TerrainViewPattern::RULE_SAND == name + || TerrainViewPattern::RULE_TRANSITION == name; +} + +boost::mutex CTerrainViewPatternConfig::smx; + +CTerrainViewPatternConfig & CTerrainViewPatternConfig::get() +{ + TLockGuard _(smx); + static CTerrainViewPatternConfig instance; + return instance; +} + +CTerrainViewPatternConfig::CTerrainViewPatternConfig() +{ + const JsonNode config(ResourceID("config/terrainViewPatterns.json")); + const std::map terGroups + = boost::assign::map_list_of("normal", ETerrainGroup::NORMAL)("dirt", ETerrainGroup::DIRT) + ("sand", ETerrainGroup::SAND)("water", ETerrainGroup::WATER)("rock", ETerrainGroup::ROCK); + BOOST_FOREACH(auto terMapping, terGroups) + { + BOOST_FOREACH(const JsonNode & ptrnNode, config[terMapping.first].Vector()) + { + TerrainViewPattern pattern; + + // Read pattern data + const JsonVector & data = ptrnNode["data"].Vector(); + if(data.size() != 9) + { + throw std::runtime_error("Size of pattern's data vector has to be 9."); + } + for(int i = 0; i < data.size(); ++i) + { + std::string cell = data[i].String(); + boost::algorithm::erase_all(cell, " "); + std::vector rules; + boost::split(rules, cell, boost::is_any_of(",")); + BOOST_FOREACH(std::string ruleStr, rules) + { + std::vector ruleParts; + boost::split(ruleParts, ruleStr, boost::is_any_of("-")); + TerrainViewPattern::WeightedRule rule; + rule.name = ruleParts[0]; + if(ruleParts.size() > 1) + { + rule.points = boost::lexical_cast(ruleParts[1]); + } + pattern.data[i].push_back(rule); + } + } + + // Read mapping + std::string mappingStr = ptrnNode["mapping"].String(); + boost::algorithm::erase_all(mappingStr, " "); + std::vector mappings; + boost::split(mappings, mappingStr, boost::is_any_of(",")); + BOOST_FOREACH(std::string mapping, mappings) + { + std::vector range; + boost::split(range, mapping, boost::is_any_of("-")); + pattern.mapping.push_back(std::make_pair(boost::lexical_cast(range[0]), + boost::lexical_cast(range.size() > 1 ? range[1] : range[0]))); + } + + // Read optional attributes + pattern.id = ptrnNode["id"].String(); + pattern.minPoints = static_cast(ptrnNode["minPoints"].Float()); + pattern.flipMode = ptrnNode["flipMode"].String(); + if(pattern.flipMode.empty()) + { + pattern.flipMode = TerrainViewPattern::FLIP_MODE_SAME_IMAGE; + } + + pattern.terGroup = terMapping.second; + patterns[terMapping.second].push_back(pattern); + } + } +} + +CTerrainViewPatternConfig::~CTerrainViewPatternConfig() +{ + +} + +const std::vector & CTerrainViewPatternConfig::getPatternsForGroup(ETerrainGroup::ETerrainGroup terGroup) const +{ + return patterns.find(terGroup)->second; +} + +const TerrainViewPattern & CTerrainViewPatternConfig::getPatternById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const +{ + const std::vector & groupPatterns = getPatternsForGroup(terGroup); + BOOST_FOREACH(const TerrainViewPattern & pattern, groupPatterns) + { + if(id == pattern.id) + { + return pattern; + } + } + throw std::runtime_error("Pattern with ID not found: " + id); +} diff --git a/lib/mapping/CMapEditManager.h b/lib/mapping/CMapEditManager.h index 8f7ca9fe0..207b7af1d 100644 --- a/lib/mapping/CMapEditManager.h +++ b/lib/mapping/CMapEditManager.h @@ -15,12 +15,11 @@ #include "CMap.h" class CGObjectInstance; +class CTerrainViewPatternConfig; +class TerrainViewPattern; namespace ETerrainGroup { - /** - * This enumeration lists terrain groups which differ in the terrain view frames alignment. - */ enum ETerrainGroup { NORMAL, @@ -31,263 +30,134 @@ namespace ETerrainGroup }; } -/** - * The terrain view pattern describes a specific composition of terrain tiles - * in a 3x3 matrix and notes which terrain view frame numbers can be used. - */ -struct TerrainViewPattern -{ - /** - * A weighted rule struct is a combination of the rule name and optionally points. - */ - struct WeightedRule - { - /** The name of the rule. Can be any value of the RULE_* constants or a ID of a another pattern. */ - std::string name; - - /** Optional. A rule can have points. Patterns may have a minimum count of points to reach to be successful. */ - int points; - - /** - * Constructor. - */ - WeightedRule(); - - /** - * Gets true if this rule is a standard rule which means that it has a value of one of the RULE_* constants. - * - * @return true for a standard rule - */ - bool isStandardRule() const; - }; - - /** Constant for the flip mode same image. Pattern will be flipped and the same image will be used(which is given in the mapping). */ - static const std::string FLIP_MODE_SAME_IMAGE; - - /** Constant for the flip mode different images. Pattern will be flipped and different images will be used(mapping area is divided into 4 parts) */ - static const std::string FLIP_MODE_DIFF_IMAGES; - - /** Constant for the rule dirt, meaning a dirty border is required. */ - static const std::string RULE_DIRT; - - /** Constant for the rule sand, meaning a sandy border is required. */ - static const std::string RULE_SAND; - - /** Constant for the rule transition, meaning a dirty OR sandy border is required. */ - static const std::string RULE_TRANSITION; - - /** Constant for the rule native, meaning a native type is required. */ - static const std::string RULE_NATIVE; - - /** Constant for the rule any, meaning a native type, dirty OR sandy border is required. */ - static const std::string RULE_ANY; - - /** - * Default constructor. - */ - TerrainViewPattern(); - - /** - * The pattern data. - * - * It can be visualized as a 3x3 matrix: - * [ ][ ][ ] - * [ ][ ][ ] - * [ ][ ][ ] - * - * The box in the center belongs always to the native terrain type and - * is the point of origin. Depending on the terrain type different rules - * can be used. Their meaning differs also from type to type. - * - * std::vector -> several rules can be used in one cell - */ - std::array, 9> data; - - /** The identifier of the pattern, if it's referenced from a another pattern. */ - std::string id; - - /** - * This describes the mapping between this pattern and the corresponding range of frames - * which should be used for the ter view. - * - * std::vector -> size=1: typical, size=2: if this pattern should map to two different types of borders - * std::pair -> 1st value: lower range, 2nd value: upper range - */ - std::vector > mapping; - - /** The minimum points to reach to to validate the pattern successfully. */ - int minPoints; - - /** Describes if flipping is required and which mapping should be used. */ - std::string flipMode; - - /** The terrain group to which the pattern belongs to. */ - ETerrainGroup::ETerrainGroup terGroup; -}; - -/** - * The terrain view pattern config loads pattern data from the filesystem. - */ -class CTerrainViewPatternConfig -{ -public: - /** - * Constructor. Initializes the patterns data. - */ - CTerrainViewPatternConfig(); - - /** - * Gets the patterns for a specific group of terrain. - * - * @param terGroup the terrain group e.g. normal for grass, lava,... OR dirt OR sand,... - * @return a vector containing patterns - */ - const std::vector & getPatternsForGroup(ETerrainGroup::ETerrainGroup terGroup) const; - - /** - * Gets a pattern by ID. Throws if pattern isn't available(config error). - * - * @param terGroup the terrain group e.g. normal for grass, lava,... OR dirt OR sand,... - * @param id the id of the pattern - * @return the pattern which matches the ID - */ - const TerrainViewPattern & getPatternById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const; - -private: - /** The patterns data. */ - std::map > patterns; -}; - -/** - * The map edit manager provides functionality for drawing terrain and placing - * objects on the map. - * - * TODO add undo / selection functionality for the map editor - */ +/// The map edit manager provides functionality for drawing terrain and placing +/// objects on the map. class CMapEditManager { public: - /** - * Constructor. The map object / terrain data has to be initialized. - * - * @param terViewPatternConfig the terrain view pattern config - * @param map the map object which should be edited - * @param randomSeed optional. the seed which is used for generating randomly terrain views - */ - CMapEditManager(const CTerrainViewPatternConfig * terViewPatternConfig, CMap * map, int randomSeed = std::time(nullptr)); + CMapEditManager(CMap * map, int randomSeed = std::time(nullptr)); - /** - * Clears the terrain. The free level is filled with water and the - * underground level with rock. - */ + /// Clears the terrain. The free level is filled with water and the underground level with rock. void clearTerrain(); - /** - * Draws terrain. - * - * @param terType the type of the terrain to draw - * @param posx the x coordinate - * @param posy the y coordinate - * @param width the height of the terrain to draw - * @param height the width of the terrain to draw - * @param underground true if you want to draw at the underground, false if open - */ void drawTerrain(ETerrainType terType, int posx, int posy, int width, int height, bool underground); - - /** - * Inserts an object. - * - * @param obj the object to insert - * @param posx the x coordinate - * @param posy the y coordinate - * @param underground true if you want to draw at the underground, false if open - */ void insertObject(CGObjectInstance * obj, int posx, int posy, bool underground); private: - /** - * The validation result struct represents the result of a pattern validation. - */ struct ValidationResult { - /** - * Constructor. - * - * @param result the result of the validation either true or false - * @param transitionReplacement optional. the replacement of a T rule, either D or S - */ ValidationResult(bool result, const std::string & transitionReplacement = ""); - /** The result of the validation. */ bool result; - - /** The replacement of a T rule, either D or S. */ + /// The replacement of a T rule, either D or S. std::string transitionReplacement; }; - /** - * Updates the terrain view ids in the specified area. - * - * @param posx the x coordinate - * @param posy the y coordinate - * @param width the height of the terrain to update - * @param height the width of the terrain to update - * @param mapLevel the map level, 0 for open and 1 for underground - */ void updateTerrainViews(int posx, int posy, int width, int height, int mapLevel); - - /** - * Gets the terrain group by the terrain type number. - * - * @param terType the terrain type - * @return the terrain group - */ ETerrainGroup::ETerrainGroup getTerrainGroup(ETerrainType terType) const; - - /** - * Validates the terrain view of the given position and with the given pattern. - * - * @param posx the x position - * @param posy the y position - * @param mapLevel the map level, 0 for open and 1 for underground - * @param pattern the pattern to validate the terrain view with - * @param recDepth the depth of the recursion, 0 for no recursion - 1 for recursion - * @return a validation result struct - */ + /// Validates the terrain view of the given position and with the given pattern. ValidationResult validateTerrainView(int posx, int posy, int mapLevel, const TerrainViewPattern & pattern, int recDepth = 0) const; - - /** - * Tests whether the given terrain type is a sand type. Sand types are: Water, Sand and Rock - * - * @param terType the terrain type to test - * @return true if the terrain type is a sand type, otherwise false - */ + /// Tests whether the given terrain type is a sand type. Sand types are: Water, Sand and Rock bool isSandType(ETerrainType terType) const; - - /** - * Gets a flipped pattern. - * - * @param pattern the original pattern to flip - * @param flip the flip mode value, see FLIP_PATTERN_* constants for details - * @return the flipped pattern - */ TerrainViewPattern getFlippedPattern(const TerrainViewPattern & pattern, int flip) const; - /** Constant for flipping a pattern horizontally. */ static const int FLIP_PATTERN_HORIZONTAL = 1; - - /** Constant for flipping a pattern vertically. */ static const int FLIP_PATTERN_VERTICAL = 2; - - /** Constant for flipping a pattern horizontally and vertically. */ static const int FLIP_PATTERN_BOTH = 3; - /** The map object to edit. */ CMap * map; - - /** The random number generator. */ CRandomGenerator gen; - - /** The terrain view pattern config. */ - const CTerrainViewPatternConfig * terViewPatternConfig; +}; + +/* ---------------------------------------------------------------------------- */ +/* Implementation/Detail classes, Private API */ +/* ---------------------------------------------------------------------------- */ + +/// The terrain view pattern describes a specific composition of terrain tiles +/// in a 3x3 matrix and notes which terrain view frame numbers can be used. +struct TerrainViewPattern +{ + struct WeightedRule + { + WeightedRule(); + + /// Gets true if this rule is a standard rule which means that it has a value of one of the RULE_* constants. + bool isStandardRule() const; + + /// The name of the rule. Can be any value of the RULE_* constants or a ID of a another pattern. + std::string name; + + /// Optional. A rule can have points. Patterns may have a minimum count of points to reach to be successful. + int points; + }; + + /// Constant for the flip mode same image. Pattern will be flipped and the same image will be used(which is given in the mapping). + static const std::string FLIP_MODE_SAME_IMAGE; + + /// Constant for the flip mode different images. Pattern will be flipped and different images will be used(mapping area is divided into 4 parts) + static const std::string FLIP_MODE_DIFF_IMAGES; + + /// Constant for the rule dirt, meaning a dirty border is required. + static const std::string RULE_DIRT; + + /// Constant for the rule sand, meaning a sandy border is required. + static const std::string RULE_SAND; + + /// Constant for the rule transition, meaning a dirty OR sandy border is required. + static const std::string RULE_TRANSITION; + + /// Constant for the rule native, meaning a native type is required. + static const std::string RULE_NATIVE; + + /// Constant for the rule any, meaning a native type, dirty OR sandy border is required. + static const std::string RULE_ANY; + + TerrainViewPattern(); + + /// The pattern data can be visualized as a 3x3 matrix: + /// [ ][ ][ ] + /// [ ][ ][ ] + /// [ ][ ][ ] + /// + /// The box in the center belongs always to the native terrain type and + /// is the point of origin. Depending on the terrain type different rules + /// can be used. Their meaning differs also from type to type. + /// + /// std::vector -> several rules can be used in one cell + std::array, 9> data; + + /// The identifier of the pattern, if it's referenced from a another pattern. + std::string id; + + /// This describes the mapping between this pattern and the corresponding range of frames + /// which should be used for the ter view. + /// + /// std::vector -> size=1: typical, size=2: if this pattern should map to two different types of borders + /// std::pair -> 1st value: lower range, 2nd value: upper range + std::vector > mapping; + + /// The minimum points to reach to to validate the pattern successfully. + int minPoints; + + /// Describes if flipping is required and which mapping should be used. + std::string flipMode; + + ETerrainGroup::ETerrainGroup terGroup; +}; + +/// The terrain view pattern config loads pattern data from the filesystem. +class CTerrainViewPatternConfig +{ +public: + static CTerrainViewPatternConfig & get(); + + const std::vector & getPatternsForGroup(ETerrainGroup::ETerrainGroup terGroup) const; + const TerrainViewPattern & getPatternById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const; + +private: + CTerrainViewPatternConfig(); + ~CTerrainViewPatternConfig(); + + std::map > patterns; + static boost::mutex smx; }; diff --git a/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index bf071d8f7..44ce1861b 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -377,8 +377,7 @@ std::unique_ptr CMapGenerator::generate() map = make_unique(); addHeaderInfo(); - terViewPatternConfig = make_unique(); - mapMgr = make_unique(terViewPatternConfig.get(), map.get(), randomSeed); + mapMgr = make_unique(map.get(), randomSeed); genTerrain(); genTowns(); diff --git a/lib/rmg/CMapGenerator.h b/lib/rmg/CMapGenerator.h index 1515155ee..84be545a4 100644 --- a/lib/rmg/CMapGenerator.h +++ b/lib/rmg/CMapGenerator.h @@ -186,6 +186,5 @@ private: std::unique_ptr map; CRandomGenerator gen; int randomSeed; - std::unique_ptr terViewPatternConfig; std::unique_ptr mapMgr; };