- Add a simple macro system for auto lines (the goal is to help mostly with repetitive card auto lines such as the ones we have in MotD mod) Check the MotD mod for examples.

-- I added an AbilityParser.cpp file, mid term goal is to move AbilityFactory there, so that MTGAbility.cpp becomes a bit less big.
-- I tried to add the file reference in Makefiles, but only tested windows compilation so far
- Fixed bugs related to "castRestriction" variables in MTGAbility. these variables were declared in both the parent and children classes, leading to bugs and duplicate code/content

The test suite passes
This commit is contained in:
wagic.the.homebrew
2011-10-15 16:19:29 +00:00
parent 28069e980b
commit 6825082d6d
16 changed files with 201 additions and 24 deletions
+126
View File
@@ -0,0 +1,126 @@
#include "PrecompiledHeader.h"
#include "AbilityParser.h"
#include "utils.h"
#include <boost/algorithm/string.hpp>
using std::string;
using std::vector;
vector<AutoLineMacro *> AutoLineMacro::gAutoLineMacros;
map<string, bool> AutoLineMacro::gAutoLineMacrosIndex;
AutoLineMacro::AutoLineMacro(string& s)
{
parse(s);
}
void AutoLineMacro::parse(string& s)
{
//we convert to lower, because the counterpart (auto strings) is converted to lower at parse time
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
size_t firstSpace = s.find(" ");
if (firstSpace == string::npos)
{
DebugTrace("FATAL:error parsing macro : " << s);
return;
}
size_t firstParenthesis = s.find("(");
if (firstParenthesis != string::npos && firstParenthesis < firstSpace)
{
//The string has params
mName = s.substr(0, firstParenthesis);
size_t firstClosingParenthesis = s.find(")");
string params = s.substr(firstParenthesis + 1,firstClosingParenthesis - (firstParenthesis + 1));
mParams = split(params, ',');
mResult = s.substr(firstClosingParenthesis + 2);
}
else
{
//no params
mName = s.substr(0, firstSpace);
mResult = s.substr(firstSpace + 1);
}
boost::replace_all(mResult, "\\n", "\n");
}
string AutoLineMacro::process(string& s)
{
string temp = s;
if (!mParams.size())
{
//no params, simple macro
boost::replace_all(temp, mName, mResult);
return temp;
}
//params, complex macro
string toFind = mName + "(";
string result;
size_t occurence = temp.find(toFind);
if (occurence == string::npos)
return s;
while (occurence != string::npos)
{
result.append(temp.substr(0, occurence));
size_t closingParenthesis = temp.find(")");
size_t paramsStart = occurence + toFind.length();
string params = temp.substr(paramsStart, closingParenthesis - paramsStart);
vector<string> vParams = split(params, ',');
if (vParams.size() != mParams.size())
{
return s;
}
string tempResult = mResult;
for (size_t i = 0; i < vParams.size(); ++i)
{
boost::replace_all(tempResult, mParams[i], vParams[i]);
}
result.append(tempResult);
temp = temp.substr(closingParenthesis + 1);
occurence = temp.find(toFind);
}
result.append(temp);
return result;
}
bool AutoLineMacro::AddMacro(string& s)
{
AutoLineMacro * alm = NEW AutoLineMacro(s);
if (gAutoLineMacrosIndex[alm->mName])
{
DebugTrace("WARNING, Macro already exists: " << alm->mName);
delete alm;
return false;
}
gAutoLineMacrosIndex[alm->mName] = true;
gAutoLineMacros.push_back(alm);
return true;
}
void AutoLineMacro::Destroy()
{
for (size_t i = 0; i < gAutoLineMacros.size(); ++i)
{
SAFE_DELETE(gAutoLineMacros[i]);
}
}
string AutoLineMacro::Process(string& s)
{
string result = s;
for (size_t i = 0; i < gAutoLineMacros.size(); ++i)
{
result = gAutoLineMacros[i]->process(result);
}
return result;
}
+3 -3
View File
@@ -8,7 +8,7 @@
//Generic Activated Abilities
GenericActivatedAbility::GenericActivatedAbility(GameObserver* observer, string newName, string castRestriction, int _id, MTGCardInstance * card, MTGAbility * a, ManaCost * _cost,
string limit,MTGAbility * sideEffects,string usesBeforeSideEffects, int restrictions, MTGGameZone * dest) :
ActivatedAbility(observer, _id, card, _cost, restrictions,limit,sideEffects,usesBeforeSideEffects,castRestriction), NestedAbility(a), activeZone(dest),newName(newName),castRestriction(castRestriction)
ActivatedAbility(observer, _id, card, _cost, restrictions,limit,sideEffects,usesBeforeSideEffects,castRestriction), NestedAbility(a), activeZone(dest),newName(newName)
{
counters = 0;
target = ability->target;
@@ -2486,9 +2486,9 @@ MultiAbility::~MultiAbility()
}
//Generic Target Ability
GenericTargetAbility::GenericTargetAbility(GameObserver* observer, string newName, string castRestriction,int _id, MTGCardInstance * _source, TargetChooser * _tc, MTGAbility * a,
GenericTargetAbility::GenericTargetAbility(GameObserver* observer, string newName, string castRestriction, int _id, MTGCardInstance * _source, TargetChooser * _tc, MTGAbility * a,
ManaCost * _cost, string limit,MTGAbility * sideEffects,string usesBeforeSideEffects, int restrictions, MTGGameZone * dest) :
TargetAbility(observer, _id, _source, _tc, _cost, restrictions,castRestriction), limit(limit), activeZone(dest),newName(newName),castRestriction(castRestriction)
TargetAbility(observer, _id, _source, _tc, _cost, restrictions, castRestriction), limit(limit), activeZone(dest),newName(newName)
{
ability = a;
MTGAbility * core = AbilityFactory::getCoreAbility(a);
+3
View File
@@ -30,6 +30,7 @@
#include "ModRules.h"
#include "JFileSystem.h"
#include "Credits.h"
#include "AbilityParser.h"
#define DEFAULT_DURATION .25
@@ -328,6 +329,8 @@ void GameApp::Destroy()
options.theGame = NULL;
Unlockable::Destroy();
AutoLineMacro::Destroy();
Rules::unloadAllRules();
LOG("==Destroying GameApp Successful==");
+6 -2
View File
@@ -12,6 +12,7 @@
#include "ThisDescriptor.h"
#include "ExtraCost.h"
#include "MTGRules.h"
#include "AbilityParser.h"
//Used for Lord/This parsing
@@ -2777,6 +2778,9 @@ int AbilityFactory::getAbilities(vector<MTGAbility *> * v, Spell * spell, MTGCar
size_t found;
int result = id;
magicText = AutoLineMacro::Process(magicText);
while (magicText.size())
{
found = magicText.find("\n");
@@ -3891,13 +3895,13 @@ ostream& ActivatedAbility::toString(ostream& out) const
}
TargetAbility::TargetAbility(GameObserver* observer, int id, MTGCardInstance * card, TargetChooser * _tc, ManaCost * _cost, int _playerturnonly, string castRestriction) :
ActivatedAbility(observer, id, card, _cost, _playerturnonly, castRestriction), NestedAbility(NULL)
ActivatedAbility(observer, id, card, _cost, _playerturnonly, "", NULL, "", castRestriction), NestedAbility(NULL) //Todo fix this mess, why do we have to pass "", NULL, "" here before cast restrictions?
{
tc = _tc;
}
TargetAbility::TargetAbility(GameObserver* observer, int id, MTGCardInstance * card, ManaCost * _cost, int _playerturnonly, string castRestriction) :
ActivatedAbility(observer, id, card, _cost, _playerturnonly, castRestriction), NestedAbility(NULL)
ActivatedAbility(observer, id, card, _cost, _playerturnonly, "", NULL, "", castRestriction), NestedAbility(NULL) //Todo fix this mess, why do we have to pass "", NULL, "" here before cast restrictions?
{
tc = NULL;
}
+7
View File
@@ -11,6 +11,7 @@
#include "utils.h"
#include "DeckManager.h"
#include <iomanip>
#include "AbilityParser.h"
#if defined (WIN32) || defined (LINUX)
#include <time.h>
@@ -341,6 +342,12 @@ int MTGAllCards::load(const char * config_file, const char * set_name, int autol
if (!s.size()) continue;
if (s[s.size() - 1] == '\r') s.erase(s.size() - 1); // Handle DOS files
if (!s.size()) continue;
if (s.find("#AUTO_DEFINE ") == 0)
{
AutoLineMacro::AddMacro(s.substr(13));
continue;
}
switch (conf_read_mode)
{
case MTGAllCards::READ_ANYTHING:
+1 -1
View File
@@ -26,7 +26,7 @@ const string Constants::kRetraceKeyword = "retrace";
const string Constants::kKickerKeyword = "kicker";
const string Constants::kMorphKeyword = "facedown";
int Constants::NB_Colors; //Store de Max number of colors
int Constants::NB_Colors = 0; //Store the Max number of colors.
const char* Constants::MTGBasicAbilities[] = {
"trample",
+1
View File
@@ -828,6 +828,7 @@ int TargetChooser::countValidTargets()
int result = 0;
for (int i = 0; i < 2; ++i)
{
assert(observer);
Player *p = observer->players[i];
if(canTarget(p))
result++;