1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

- 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

This commit is contained in:
beegee1 2013-04-16 13:16:58 +00:00
parent feea589648
commit 45fccfb1a6
8 changed files with 397 additions and 958 deletions

View File

@ -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<int3, ShashInt3> &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<int3, ShashInt3> &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<Component*> &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<SecondarySkill> &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<ui32> 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<Component> &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::vector<Compone
{
answerQuery(askID, sel);
});
TRACE_END(logAi);
}
void VCAI::showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, int queryID)
{
TRACE_BEGIN_PARAMS(logAi, "removableUnits '%i', queryID '%i'", removableUnits % queryID);
LOG_TRACE_PARAMS(logAi, "removableUnits '%i', queryID '%i'", removableUnits % queryID);
NET_EVENT_HANDLER;
std::string s1 = up ? up->nodeName() : "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<CSaveFile> &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<CLoadFile> &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)

View File

@ -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()

View File

@ -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 */

View File

@ -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 <typename Handler>
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<TFaction> 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<SHeroName> 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<SHeroName> 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 <typename Handler>
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 <typename Handler>
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 <typename Handler>
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 <typename Handler>
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 <typename Handler>
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 <typename Handler>
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<BuildingID> buildings;
/** additional creatures in i-th level dwelling */
std::vector<si32> creatures;
/** owner of this event */
CGTownInstance * town;
/**
* Serialize method.
*/
template <typename Handler>
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<CGObjectInstance *> visitableObjects;
/** pointers to objects that are blocking this tile */
std::vector<CGObjectInstance *> blockingObjects;
/**
* Serialize method.
*/
template <typename Handler>
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<PlayerInfo> 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<PlayerInfo> 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<bool> allowedHeroes;
/** A list of placeholded heroes. The index is the id of a hero type. */
std::vector<ui16> 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 <typename Handler>
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<Rumor> rumors;
/** list of disposed heroes */
std::vector<DisposedHero> disposedHeroes;
/** list of predefined heroes */
std::vector<ConstTransitivePtr<CGHeroInstance> > predefinedHeroes;
/** list of .def files with definitions from .h3m (may be custom) */
std::vector<ConstTransitivePtr<CGDefInfo> > customDefs;
/** list of allowed spells, index is the spell id */
std::vector<bool> allowedSpell;
/** list of allowed artifacts, index is the artifact id */
std::vector<bool> allowedArtifact;
/** list of allowed abilities, index is the ability id */
std::vector<bool> allowedAbilities;
/** list of map events */
std::list<CMapEvent> events;
/** specifies the position of the grail */
int3 grailPos;
/** specifies the radius of the grail */
int grailRadious;
/** list of objects */
std::vector< ConstTransitivePtr<CGObjectInstance> > objects;
/** list of heroes */
std::vector< ConstTransitivePtr<CGHeroInstance> > heroes;
/** list of towns */
std::vector< ConstTransitivePtr<CGTownInstance> > towns;
/** list of artifacts */
std::vector< ConstTransitivePtr<CArtifactInstance> > artInstances;
/** list of quests */
std::vector< ConstTransitivePtr<CQuest> > 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<si32, ObjectInstanceID> questIdentifierToId;
/**
* Serialize method.
*/
template <typename Handler>
void serialize(Handler &h, const int formatVersion)
{

View File

@ -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<std::string, ETerrainGroup::ETerrainGroup> 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<std::string> rules;
boost::split(rules, cell, boost::is_any_of(","));
BOOST_FOREACH(std::string ruleStr, rules)
{
std::vector<std::string> 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<int>(ruleParts[1]);
}
pattern.data[i].push_back(rule);
}
}
// Read mapping
std::string mappingStr = ptrnNode["mapping"].String();
boost::algorithm::erase_all(mappingStr, " ");
std::vector<std::string> mappings;
boost::split(mappings, mappingStr, boost::is_any_of(","));
BOOST_FOREACH(std::string mapping, mappings)
{
std::vector<std::string> range;
boost::split(range, mapping, boost::is_any_of("-"));
pattern.mapping.push_back(std::make_pair(boost::lexical_cast<int>(range[0]),
boost::lexical_cast<int>(range.size() > 1 ? range[1] : range[0])));
}
// Read optional attributes
pattern.id = ptrnNode["id"].String();
pattern.minPoints = static_cast<int>(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<TerrainViewPattern> & 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<TerrainViewPattern> & 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<TerrainViewPattern> & 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<std::string, ETerrainGroup::ETerrainGroup> 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<std::string> rules;
boost::split(rules, cell, boost::is_any_of(","));
BOOST_FOREACH(std::string ruleStr, rules)
{
std::vector<std::string> 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<int>(ruleParts[1]);
}
pattern.data[i].push_back(rule);
}
}
// Read mapping
std::string mappingStr = ptrnNode["mapping"].String();
boost::algorithm::erase_all(mappingStr, " ");
std::vector<std::string> mappings;
boost::split(mappings, mappingStr, boost::is_any_of(","));
BOOST_FOREACH(std::string mapping, mappings)
{
std::vector<std::string> range;
boost::split(range, mapping, boost::is_any_of("-"));
pattern.mapping.push_back(std::make_pair(boost::lexical_cast<int>(range[0]),
boost::lexical_cast<int>(range.size() > 1 ? range[1] : range[0])));
}
// Read optional attributes
pattern.id = ptrnNode["id"].String();
pattern.minPoints = static_cast<int>(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<TerrainViewPattern> & 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<TerrainViewPattern> & 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);
}

View File

@ -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<std::vector<WeightedRule>, 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<std::pair<int, int> > 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<TerrainViewPattern> & 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<ETerrainGroup::ETerrainGroup, std::vector<TerrainViewPattern> > 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<std::vector<WeightedRule>, 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<std::pair<int, int> > 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<TerrainViewPattern> & getPatternsForGroup(ETerrainGroup::ETerrainGroup terGroup) const;
const TerrainViewPattern & getPatternById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const;
private:
CTerrainViewPatternConfig();
~CTerrainViewPatternConfig();
std::map<ETerrainGroup::ETerrainGroup, std::vector<TerrainViewPattern> > patterns;
static boost::mutex smx;
};

View File

@ -377,8 +377,7 @@ std::unique_ptr<CMap> CMapGenerator::generate()
map = make_unique<CMap>();
addHeaderInfo();
terViewPatternConfig = make_unique<CTerrainViewPatternConfig>();
mapMgr = make_unique<CMapEditManager>(terViewPatternConfig.get(), map.get(), randomSeed);
mapMgr = make_unique<CMapEditManager>(map.get(), randomSeed);
genTerrain();
genTowns();

View File

@ -186,6 +186,5 @@ private:
std::unique_ptr<CMap> map;
CRandomGenerator gen;
int randomSeed;
std::unique_ptr<CTerrainViewPatternConfig> terViewPatternConfig;
std::unique_ptr<CMapEditManager> mapMgr;
};