From e7678522ee79f14462c8294697ee36144d7dd433 Mon Sep 17 00:00:00 2001 From: "wagic.the.homebrew@gmail.com" Date: Sun, 12 Apr 2009 12:39:44 +0000 Subject: [PATCH] Erwan - fixed a few memory leaks (but Wagic still crashes on the PSP after a few games :( ) --- JGE/Makefile.hge | 20 ++ projects/mtg/include/AllAbilities.h | 10 +- projects/mtg/include/MTGAbility.h | 1 - projects/mtg/include/TargetChooser.h | 2 + projects/mtg/src/AIPlayer.cpp | 1 + projects/mtg/src/ActionLayer.cpp | 4 +- projects/mtg/src/GameApp.cpp | 2 +- projects/mtg/src/GameStateDuel.cpp | 2 +- projects/mtg/src/MTGAbility.cpp | 194 +++++++++---- projects/mtg/src/MTGCardInstance.cpp | 3 +- projects/mtg/src/TargetChooser.cpp | 394 +++++++++++++-------------- 11 files changed, 361 insertions(+), 272 deletions(-) create mode 100644 JGE/Makefile.hge diff --git a/JGE/Makefile.hge b/JGE/Makefile.hge new file mode 100644 index 000000000..a14ef12f9 --- /dev/null +++ b/JGE/Makefile.hge @@ -0,0 +1,20 @@ +PSPSDK=$(shell psp-config --pspsdk-path) +PSPDIR=$(shell psp-config --psp-prefix) +TARGET_LIB = libhgetools.a +OBJS = src/hge/hgecolor.o src/hge/hgeparticle.o \ + src/hge/hgerect.o src/hge/hgevector.o \ + src/hge/hgedistort.o src/hge/hgefont.o + + +INCDIR = include/psp include/psp/freetype2 +LIBDIR = lib/psp + +CFLAGS = -O2 -G0 -Wall + +LIBS = -lgif -lfreetype -ljpeg -lpng -lz -lmikmod -lpsppower -lpspmpeg -lpspaudiocodec -lpspaudiolib -lpspaudio -lpspgum -lpspgu -lpsprtc -lm -lstdc++ -ljge300 + +include $(PSPSDK)/lib/build.mak + +install: $(TARGET_LIB) + @cp libhgetools.a lib/psp + @echo "Done" diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index e9a755319..94e03e33b 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -843,6 +843,10 @@ class AProtectionFrom:public MTGAbility{ return 1; } + ~AProtectionFrom(){ + delete(cd); + } + }; //Aura Enchantments that provide controller of target life or damages at a given phase of their turn @@ -979,7 +983,6 @@ class AConvertLandToCreatures:public ListMaintainerAbility{ //Lords (Merfolk lord...) give power and toughness to OTHER creatures of their type, they can give them special abilities, regeneration class ALord:public ListMaintainerAbility{ public: - TargetChooser * tc; int power, toughness; int ability; int modifier; @@ -1035,7 +1038,6 @@ class ALord:public ListMaintainerAbility{ //Foreach (plague rats...) class AForeach:public ListMaintainerAbility{ public: - TargetChooser * tc; int power, toughness; int includeSelf; AForeach(int _id, MTGCardInstance * card,MTGCardInstance * _target, TargetChooser * _tc, int _includeSelf, int _power = 0 , int _toughness = 0):ListMaintainerAbility(_id,card,_target){ @@ -2780,7 +2782,6 @@ class AMinionofLeshrac: public TargetAbility{ //Generic Kird Ape class AKirdApe:public ListMaintainerAbility{ public: - TargetChooser * tc; int power; int toughness; int ability; @@ -2822,9 +2823,6 @@ class AKirdApe:public ListMaintainerAbility{ return 0; } - ~AKirdApe(){ - delete tc; - } }; diff --git a/projects/mtg/include/MTGAbility.h b/projects/mtg/include/MTGAbility.h index fc9f1ced6..2fbaa6277 100644 --- a/projects/mtg/include/MTGAbility.h +++ b/projects/mtg/include/MTGAbility.h @@ -95,7 +95,6 @@ class ActivatedAbility:public MTGAbility{ virtual int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL); virtual int reactToTargetClick(Targetable * object); virtual int resolve() = 0; - virtual ~ActivatedAbility(); }; class TargetAbility:public ActivatedAbility{ diff --git a/projects/mtg/include/TargetChooser.h b/projects/mtg/include/TargetChooser.h index 0136893a1..e0ac5e12c 100644 --- a/projects/mtg/include/TargetChooser.h +++ b/projects/mtg/include/TargetChooser.h @@ -38,6 +38,7 @@ class TargetChooser: public TargetsList { virtual int canTarget(Targetable * _target); virtual int full(){if (maxtargets != -1 && cursor>=maxtargets) {return 1;} else{return 0;}}; virtual int ready(){return cursor;}; + virtual ~TargetChooser(){}; int targetListSet(); @@ -103,6 +104,7 @@ class DescriptorTargetChooser:public TargetZoneChooser{ DescriptorTargetChooser(CardDescriptor * _cd, MTGCardInstance * card = NULL, int _maxtargets = 1); DescriptorTargetChooser(CardDescriptor * _cd, MTGGameZone ** _zones, int nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1); virtual int canTarget(Targetable * target); + ~DescriptorTargetChooser(); }; diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index 8e3c9d472..347b4a704 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -39,6 +39,7 @@ AIPlayer::~AIPlayer(){ stats->save(); SAFE_DELETE(stats); } + //TODO delete clickstream! } MTGCardInstance * AIPlayer::chooseCard(TargetChooser * tc, MTGCardInstance * source, int random){ for (int i = 0; i < game->hand->nb_cards; i++){ diff --git a/projects/mtg/src/ActionLayer.cpp b/projects/mtg/src/ActionLayer.cpp index e9d9fa1bd..51b7971d5 100644 --- a/projects/mtg/src/ActionLayer.cpp +++ b/projects/mtg/src/ActionLayer.cpp @@ -66,8 +66,8 @@ void ActionLayer::Update(float dt){ if (mObjects[i]!= NULL){ ActionElement * currentAction = (ActionElement *)mObjects[i]; if (currentAction->testDestroy()){ - currentAction->destroy(); - Remove(currentAction); + currentAction->destroy(); + Remove(currentAction); } } } diff --git a/projects/mtg/src/GameApp.cpp b/projects/mtg/src/GameApp.cpp index fc5005846..f39535b47 100644 --- a/projects/mtg/src/GameApp.cpp +++ b/projects/mtg/src/GameApp.cpp @@ -221,7 +221,7 @@ void GameApp::Update() if (mNextState != NULL) { if (mCurrentState != NULL) - mCurrentState->End(); + mCurrentState->End(); mCurrentState = mNextState; mCurrentState->Start(); diff --git a/projects/mtg/src/GameStateDuel.cpp b/projects/mtg/src/GameStateDuel.cpp index 61fd505f1..d3c1f6ea5 100644 --- a/projects/mtg/src/GameStateDuel.cpp +++ b/projects/mtg/src/GameStateDuel.cpp @@ -66,7 +66,7 @@ void GameStateDuel::Start() #ifdef TESTSUITE - if (testSuite) delete testSuite; + SAFE_DELETE(testSuite); testSuite = NEW TestSuite(RESPATH"/test/_tests.txt",mParent->collection); #endif diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 1844a0519..14a906a46 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -94,7 +94,7 @@ Trigger * AbilityFactory::parseTrigger(string magicText){ for (int i = 0; i < Constants::NB_MTG_PHASES; i++){ found = magicText.find(Constants::MTGPhaseCodeNames[i]); if (found != string::npos){ - return NEW TriggerNextPhase(i); + return NEW TriggerNextPhase(i); } } } @@ -102,6 +102,9 @@ Trigger * AbilityFactory::parseTrigger(string magicText){ return NULL; } + + + //Some basic functionalities that can be added automatically in the text file /* * Several objects are computed from the text string, and have a direct influence on what action we should take @@ -114,6 +117,9 @@ Trigger * AbilityFactory::parseTrigger(string magicText){ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ int dryMode = 0; if (!spell) dryMode = 1; + int dryModeResultSet = 0; + int dryModeResult = 0; + GameObserver * game = GameObserver::GetInstance(); if (!card) card = spell->source; MTGCardInstance * target = card->target; @@ -165,6 +171,9 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ //Tap in the cost ? if (line.find("{t}") != string::npos) doTap = 1; + TargetChooser * tc; + TargetChooser * lordTargets; + Trigger * trigger; while (line.size()){ string s; found = line.find("&&"); @@ -173,8 +182,10 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ line = line.substr(found+2); if (!multi){ OutputDebugString("Multi initializing\n"); - multi = NEW MultiAbility(id, card, cost,doTap); - game->addObserver(multi); + if (!dryMode) { + multi = NEW MultiAbility(id, card, cost,doTap); + game->addObserver(multi); + } OutputDebugString("Multi initialized\n"); } }else{ @@ -182,14 +193,13 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ line = ""; } - TargetChooser * tc = NULL; - - TargetChooser * lordTargets = NULL; + tc = NULL; + lordTargets = NULL; int lordIncludeSelf = 1; int lordType = 0; string lordTargetsString; - Trigger * trigger = parseTrigger(s); + trigger = parseTrigger(s); //Dirty way to remove the trigger text (could get in the way) if (trigger){ found = s.find(":"); @@ -210,7 +220,11 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ //Lord found = s.find("lord("); if (found != string::npos){ - if (dryMode) return BAKA_EFFECT_GOOD; + if (dryMode) { + dryModeResult = BAKA_EFFECT_GOOD; + dryModeResultSet = 1; + break; + } unsigned int end = s.find(")", found+5); if (end != string::npos){ lordTargetsString = s.substr(found+5,end-found-5).c_str(); @@ -219,7 +233,11 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ } found = s.find("foreach("); if (found != string::npos){ - if (dryMode) return BAKA_EFFECT_GOOD; + if (dryMode) { + dryModeResult = BAKA_EFFECT_GOOD; + dryModeResultSet = 1; + break; + } unsigned int end = s.find(")", found+8); if (end != string::npos){ lordTargetsString = s.substr(found+8,end-found-8).c_str(); @@ -228,7 +246,11 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ } found = s.find("aslongas("); if (found != string::npos){ - if (dryMode) return BAKA_EFFECT_GOOD; + if (dryMode) { + dryModeResult = BAKA_EFFECT_GOOD; + dryModeResultSet = 1; + break; + } unsigned int end = s.find(")", found+9); if (end != string::npos){ lordTargetsString = s.substr(found+9,end-found-9).c_str(); @@ -245,7 +267,11 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ //Untapper (Ley Druid...) found = s.find("untap"); if (found != string::npos){ - if (dryMode) return BAKA_EFFECT_GOOD; + if (dryMode) { + dryModeResult = BAKA_EFFECT_GOOD; + dryModeResultSet = 1; + break; + } if (tc){ game->addObserver(NEW AUntaper(id, card, cost, tc)); }else{ @@ -259,7 +285,11 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ //Regeneration found = s.find("}:regenerate"); if (found != string::npos){ - if (dryMode) return BAKA_EFFECT_GOOD; + if (dryMode) { + dryModeResult = BAKA_EFFECT_GOOD; + dryModeResultSet = 1; + break; + } if (lordTargets){ game->addObserver(NEW ALord(id,card,lordTargets,lordIncludeSelf,0,0,-1,cost)); @@ -279,7 +309,11 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ //Token creator. Name, type, p/t, abilities found = s.find("token("); if (found != string::npos){ - if (dryMode) return BAKA_EFFECT_GOOD; + if (dryMode) { + dryModeResult = BAKA_EFFECT_GOOD; + dryModeResultSet = 1; + break; + } int end = s.find(",", found); string sname = s.substr(found + 6,end - found - 6); int previous = end+1; @@ -310,7 +344,11 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ //MoveTo Move a card from a zone to another found = s.find("moveto("); if (found != string::npos){ - if (dryMode) return BAKA_EFFECT_BAD; //TODO : depends on where from, where to... + if (dryMode) { + dryModeResult = BAKA_EFFECT_BAD; + dryModeResultSet = 1; + break; + } //TODO : depends on where from, where to... int end = s.find(")",found+1); string szone = s.substr(found + 7,end - found - 7); if (tc){ @@ -343,7 +381,11 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ //Copy a target found = s.find("copy "); if (found != string::npos){ - if (dryMode) return BAKA_EFFECT_GOOD; //TODO : + if (dryMode) { + dryModeResult = BAKA_EFFECT_GOOD; + dryModeResultSet = 1; + break; + } //TODO : if (tc){ ACopier * a = NEW ACopier(id,card,tc,cost); if (may){ @@ -363,7 +405,11 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ found = s.find("bury"); if (found != string::npos){ if (trigger){ - if (dryMode) return BAKA_EFFECT_BAD; + if (dryMode) { + dryModeResult = BAKA_EFFECT_BAD; + dryModeResultSet = 1; + break; + } BuryEvent * action = NEW BuryEvent(); game->addObserver(NEW GenericTriggeredAbility(id, card,trigger,action)); }else{ @@ -379,8 +425,9 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ int myCardsPower = countCards(targetAll,card->controller(),COUNT_POWER); int opponentCardsPower = countCards(targetAll, card->controller()->opponent(),COUNT_POWER); delete targetAll; - if (myNbCards < opponentNbCards || myCardsPower < opponentCardsPower) return BAKA_EFFECT_GOOD; - return BAKA_EFFECT_BAD; + if (myNbCards < opponentNbCards || myCardsPower < opponentCardsPower) dryModeResult = BAKA_EFFECT_GOOD; + else dryModeResult = BAKA_EFFECT_BAD; + break; }else{ if (cost){ game->addObserver(NEW AAllDestroyer(id, card,targetAll,1,cost,doTap)); @@ -390,7 +437,10 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ } } }else{ - if (dryMode) return BAKA_EFFECT_BAD; + if (dryMode){ + dryModeResult = BAKA_EFFECT_BAD; + break; + } if (tc){ game->addObserver(NEW ABurier(id, card,tc)); }else{ @@ -418,8 +468,9 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ int myCardsPower = countCards(targetAll,card->controller(),COUNT_POWER); int opponentCardsPower = countCards(targetAll, card->controller()->opponent(),COUNT_POWER); delete targetAll; - if (myNbCards < opponentNbCards || myCardsPower < opponentCardsPower) return BAKA_EFFECT_GOOD; - return BAKA_EFFECT_BAD; + if (myNbCards < opponentNbCards || myCardsPower < opponentCardsPower) dryModeResult = BAKA_EFFECT_GOOD; + else dryModeResult = BAKA_EFFECT_BAD; + break; }else{ if (cost){ game->addObserver(NEW AAllDestroyer(id, card,targetAll,0,cost,doTap)); @@ -429,7 +480,10 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ } } }else{ - if (dryMode) return BAKA_EFFECT_BAD; + if (dryMode){ + dryModeResult = BAKA_EFFECT_BAD; + break; + } if (tc){ game->addObserver(NEW ADestroyer(id, card,tc,0,cost)); }else{ @@ -452,7 +506,10 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ }else{ damage = atoi(s.substr(start+1).c_str()); } - if (dryMode) return BAKA_EFFECT_BAD; + if (dryMode){ + dryModeResult = BAKA_EFFECT_BAD; + break; + } if (tc){ MTGAbility * a = NEW ADamager(id, card, cost, damage, tc,doTap); if (multi){ @@ -485,7 +542,10 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ }else{ life = atoi(s.substr(start+1).c_str()); } - if (dryMode) return BAKA_EFFECT_GOOD; + if (dryMode){ + dryModeResult = BAKA_EFFECT_GOOD; + break; + } if (tc){ //TODO ? }else{ @@ -510,7 +570,10 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ }else{ nbcards = atoi(s.substr(start+1).c_str()); } - if (dryMode) return BAKA_EFFECT_GOOD; + if (dryMode){ + dryModeResult = BAKA_EFFECT_GOOD; + break; + } if (trigger){ DrawEvent * action = NEW DrawEvent(card->controller(),nbcards); game->addObserver(NEW GenericTriggeredAbility(id, card,trigger,action)); @@ -533,8 +596,12 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ int power, toughness; if ( parsePowerToughness(s,&power, &toughness)){ if (dryMode){ - if (power >=0 && toughness >= 0 ) return BAKA_EFFECT_GOOD; - return BAKA_EFFECT_BAD; + if (power >=0 && toughness >= 0 ) { + dryModeResult = BAKA_EFFECT_GOOD; + }else{ + dryModeResult = BAKA_EFFECT_BAD; + } + break; } int limit = 0; unsigned int limit_str = s.find("limit:"); @@ -573,7 +640,10 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ //Mana Producer found = s.find("add"); if (found != string::npos){ - if (dryMode) return BAKA_EFFECT_GOOD; + if (dryMode){ + dryModeResult = BAKA_EFFECT_GOOD; + break; + } ManaCost * input = ManaCost::parseManaCost(s.substr(0,found)); ManaCost * output = ManaCost::parseManaCost(s.substr(found)); if (!input->isNull() || doTap){ @@ -604,42 +674,48 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ if (found > 0 && s[found-1] == '-') modifier = 0; if (dryMode){ if (j == Constants::DEFENDER){ - if (modifier == 1) return BAKA_EFFECT_BAD; - return BAKA_EFFECT_GOOD; + if (modifier == 1) dryModeResult = BAKA_EFFECT_BAD; + else dryModeResult = BAKA_EFFECT_GOOD; }else{ - if (modifier == 1) return BAKA_EFFECT_GOOD; - return BAKA_EFFECT_BAD; + if (modifier == 1) dryModeResult = BAKA_EFFECT_GOOD; + else dryModeResult = BAKA_EFFECT_BAD; } - } - - if (lordType == PARSER_LORD){ - game->addObserver(NEW ALord(id,card,lordTargets,lordIncludeSelf,0,0,j,0,modifier)); - }else if (lordType == PARSER_ASLONGAS){ - game->addObserver(NEW AKirdApe(id,card,lordTargets,lordIncludeSelf,0,0,j,modifier)); + dryModeResultSet = 1; + break; }else{ - if (tc){ - game->addObserver(NEW ABasicAbilityModifierUntilEOT(id, card, j, cost,tc, modifier)); - }else{ - if (!cost){ - if(card->hasType("enchantment")){ - game->addObserver(NEW ABasicAbilityModifier(id, card,target, j,modifier)); - }else{ - game->addObserver(NEW AInstantBasicAbilityModifierUntilEOT(id, card,target, j,modifier)); - } + if (lordType == PARSER_LORD){ + game->addObserver(NEW ALord(id,card,lordTargets,lordIncludeSelf,0,0,j,0,modifier)); + }else if (lordType == PARSER_ASLONGAS){ + game->addObserver(NEW AKirdApe(id,card,lordTargets,lordIncludeSelf,0,0,j,modifier)); + }else{ + if (tc){ + game->addObserver(NEW ABasicAbilityModifierUntilEOT(id, card, j, cost,tc, modifier)); }else{ - game->addObserver(NEW ABasicAbilityAuraModifierUntilEOT(id, card,target, cost,j,modifier)); + if (!cost){ + if(card->hasType("enchantment")){ + game->addObserver(NEW ABasicAbilityModifier(id, card,target, j,modifier)); + }else{ + game->addObserver(NEW AInstantBasicAbilityModifierUntilEOT(id, card,target, j,modifier)); + } + }else{ + game->addObserver(NEW ABasicAbilityAuraModifierUntilEOT(id, card,target, cost,j,modifier)); + } } } - } - result++; - continue; + result++; + continue; + } } } + if (dryModeResultSet) break; //Tapper (icy manipulator) found = s.find("tap"); if (found != string::npos){ - if (dryMode) return BAKA_EFFECT_GOOD; + if (dryMode){ + dryModeResult = BAKA_EFFECT_GOOD; + break; + } if (tc){ game->addObserver(NEW ATapper(id, card, cost, tc)); }else{ @@ -653,8 +729,17 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ sprintf(buf, "AUTO ACTION PARSED: %s\n", line.c_str()); OutputDebugString(buf); #endif + } + if (dryMode){ + SAFE_DELETE(tc); + SAFE_DELETE(lordTargets); + SAFE_DELETE(multi); + SAFE_DELETE(cost); + SAFE_DELETE(trigger); + return dryModeResult; } } + return result; } @@ -1597,7 +1682,7 @@ MTGAbility::MTGAbility(int id, MTGCardInstance * _source,Damageable * _target ): } MTGAbility::~MTGAbility(){ - + SAFE_DELETE(cost); } //returns 1 if this ability needs to be removed from the list of active abilities @@ -1687,9 +1772,6 @@ int ActivatedAbility::reactToTargetClick(Targetable * object){ } -ActivatedAbility::~ActivatedAbility(){ - if (cost) delete cost; -} //The whole targetAbility mechanism is messed up, mainly because of its interactions with // the ActionLayer, GameObserver, and parent class ActivatedAbility. diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index dbc04ac64..c39eb2c6e 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -87,7 +87,7 @@ void MTGCardInstance::initMTGCI(){ doDamageTest = 1; belongs_to=NULL; tapped = 0; - blockers = NEW Blockers(); + blockers = NULL; untapping = 0; summoningSickness = 0; target = NULL; @@ -110,6 +110,7 @@ void MTGCardInstance::addType(int type){ } Blockers * MTGCardInstance::getBlockers(){ + if (!blockers) blockers = NEW Blockers(); return blockers; } diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 54b9149f4..0fba37199 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -8,220 +8,204 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInstance * card){ + if (!s.size()) return NULL; + GameObserver * game = GameObserver::GetInstance(); MTGGameZone * zones[10]; int nbzones = 0; - int size = s.size(); - if (size != 0){ - unsigned int found; - found = s.find("player"); - if (found != string::npos){ - int maxtargets = 1; - unsigned int several = s.find_first_of('s',5); - if (several != string::npos) maxtargets = -1; - found = s.find("creature"); + unsigned int found; + + found = s.find("player"); + if (found != string::npos){ + int maxtargets = 1; + unsigned int several = s.find_first_of('s',5); + if (several != string::npos) maxtargets = -1; + found = s.find("creature"); + if (found != string::npos) return NEW DamageableTargetChooser(card,maxtargets); //Any Damageable target (player, creature) + return NEW PlayerTargetChooser(card,maxtargets); //Any player + } + + string s1; + found = s.find("|"); + if (found != string::npos){ + string s2; + s1 = s.substr(0,found); + s2 = s.substr(found+1); + while(s2.size()){ + found = s2.find(","); + string zoneName; if (found != string::npos){ - return NEW DamageableTargetChooser(card,maxtargets); //Any Damageable target (player, creature) + zoneName = s2.substr(0,found); + s2 = s2.substr(found+1); }else{ - return NEW PlayerTargetChooser(card,maxtargets); //Any player + zoneName = s2; + s2 = ""; + } + zones[nbzones] = game->currentlyActing()->game->inPlay; + + //Graveyards + if(zoneName.compare("graveyard") == 0){ + zones[nbzones] = game->players[0]->game->graveyard; + nbzones++; + zones[nbzones] = game->players[1]->game->graveyard; + }else if(zoneName.compare("inplay") == 0){ + zones[nbzones] = game->players[0]->game->inPlay; + nbzones++; + zones[nbzones] = game->players[1]->game->inPlay; + }else{ + MTGGameZone * zone = MTGGameZone::stringToZone(zoneName, card,card); + if (zone) zones[nbzones] = zone; + } + nbzones++; + } + }else{ + s1 = s; + nbzones = 2; + zones[0]= game->players[0]->game->inPlay; + zones[1]= game->players[1]->game->inPlay; + } + + TargetChooser * tc = NULL; + int maxtargets = 1; + CardDescriptor * cd = NULL; + + while(s1.size()){ + found = s1.find(","); + string typeName; + if (found != string::npos){ + typeName = s1.substr(0,found); + s1 = s1.substr(found+1); + }else{ + typeName = s1; + s1 = ""; + } + + //Advanced cards caracteristics ? + found = typeName.find("["); + if (found != string::npos){ + int nbminuses = 0; + int end = typeName.find("]"); +#ifdef WIN32 + OutputDebugString("Advanced Attributes 1 \n"); +#endif + string attributes = typeName.substr(found+1,end-found-1); +#ifdef WIN32 + OutputDebugString(attributes.c_str()); + OutputDebugString("\n"); +#endif + cd = NEW CardDescriptor(); + while(attributes.size()){ + unsigned int found2 = attributes.find(";"); + string attribute; + if (found2 != string::npos){ + attribute = attributes.substr(0,found2); + attributes = attributes.substr(found2+1); + }else{ + attribute = attributes; + attributes = ""; + } + int minus = 0; + if (attribute[0] == '-'){ +#ifdef WIN32 + OutputDebugString("MINUS\n"); +#endif + minus = 1; + nbminuses++; + attribute=attribute.substr(1); + } +#ifdef WIN32 + OutputDebugString(attribute.c_str()); + OutputDebugString("\n"); +#endif + //Attacker + if (attribute.find("attacking") != string::npos){ + if (minus){ + cd->attacker = -1; + }else{ + cd->attacker = 1; + } + //Blocker + }else if (attribute.find("blocking") != string::npos){ + if (minus){ + cd->defenser = (MTGCardInstance *)-1; //Oh yeah, that's ugly.... + }else{ + cd->defenser = (MTGCardInstance *)1; + } + //Tapped, untapped + }else if (attribute.find("tapped") != string::npos){ + if (minus){ + cd->tapped = -1; + }else{ + cd->tapped = 1; + } + }else{ + int attributefound = 0; + //Colors + for (int cid = 0; cid < Constants::MTG_NB_COLORS; cid++){ + if (attribute.find(Constants::MTGColorStrings[cid]) != string::npos){ + attributefound = 1; + if (minus){ + cd->colors[cid] = -1; + }else{ + cd->colors[cid] = 1; + } + } + } + if (!attributefound){ + //Abilities + for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){ + if (attribute.find(Constants::MTGBasicAbilities[j]) != string::npos){ + attributefound = 1; + if (minus){ + cd->basicAbilities[j] = -1; + }else{ + cd->basicAbilities[j] = 1; + } + } + } + } + + if (!attributefound){ + //Subtypes + if (minus){ + cd->setNegativeSubtype(attribute); + }else{ + cd->setSubtype(attribute); + } + } + } + } + if (nbminuses == 0) cd->mode = CD_OR; + typeName = typeName.substr(0,found); + } + //X targets allowed ? + if (typeName.at(typeName.length()-1) == 's' && !Subtypes::subtypesList->find(typeName)){ + typeName = typeName.substr(0,typeName.length()-1); + maxtargets = -1; + } + if (cd){ + if (!tc){ + if (typeName.compare("*")!=0) cd->setSubtype(typeName); + + tc = NEW DescriptorTargetChooser(cd,zones,nbzones,card,maxtargets); + }else{ + delete(cd); + return NULL; } }else{ - string s1; - found = s.find("|"); - if (found != string::npos){ - string s2; - s1 = s.substr(0,found); - s2 = s.substr(found+1); - while(s2.size()){ - found = s2.find(","); - string zoneName; - if (found != string::npos){ - zoneName = s2.substr(0,found); - s2 = s2.substr(found+1); - }else{ - zoneName = s2; - s2 = ""; - } - zones[nbzones] = game->currentlyActing()->game->inPlay; - - //Graveyards - if(zoneName.compare("graveyard") == 0){ - zones[nbzones] = game->players[0]->game->graveyard; - nbzones++; - zones[nbzones] = game->players[1]->game->graveyard; - }else if(zoneName.compare("inplay") == 0){ - zones[nbzones] = game->players[0]->game->inPlay; - nbzones++; - zones[nbzones] = game->players[1]->game->inPlay; - }else{ - MTGGameZone * zone = MTGGameZone::stringToZone(zoneName, card,card); - if (zone) zones[nbzones] = zone; - } - nbzones++; - } + if (!tc){ + if (typeName.compare("*")==0){ + return NEW TargetZoneChooser(zones, nbzones,card, maxtargets); + }else{ + tc = NEW TypeTargetChooser(typeName.c_str(), zones, nbzones, card,maxtargets); + } }else{ - s1 = s; - nbzones = 2; - zones[0]= game->players[0]->game->inPlay; - zones[1]= game->players[1]->game->inPlay; + ((TypeTargetChooser *)tc)->addType(typeName.c_str()); + tc->maxtargets = maxtargets; } - - TargetChooser * tc = NULL; - int maxtargets = 1; - CardDescriptor * cd = NULL; - - while(s1.size()){ - found = s1.find(","); - string typeName; - if (found != string::npos){ - typeName = s1.substr(0,found); - s1 = s1.substr(found+1); - }else{ - typeName = s1; - s1 = ""; - } - - //Advanced cards caracteristics ? - found = typeName.find("["); - if (found != string::npos){ - int nbminuses = 0; - int end = typeName.find("]"); -#ifdef WIN32 - OutputDebugString("Advanced Attributes 1 \n"); -#endif - string attributes = typeName.substr(found+1,end-found-1); -#ifdef WIN32 - OutputDebugString(attributes.c_str()); - OutputDebugString("\n"); -#endif - cd = NEW CardDescriptor(); - while(attributes.size()){ - unsigned int found2 = attributes.find(";"); - string attribute; - if (found2 != string::npos){ - attribute = attributes.substr(0,found2); - attributes = attributes.substr(found2+1); - }else{ - attribute = attributes; - attributes = ""; - } - int minus = 0; - if (attribute[0] == '-'){ -#ifdef WIN32 - OutputDebugString("MINUS\n"); -#endif - minus = 1; - nbminuses++; - attribute=attribute.substr(1); - } -#ifdef WIN32 - OutputDebugString(attribute.c_str()); - OutputDebugString("\n"); -#endif - //Attacker - if (attribute.find("attacking") != string::npos){ - if (minus){ - cd->attacker = -1; - }else{ - cd->attacker = 1; - } - - //Blocker - }else if (attribute.find("blocking") != string::npos){ - if (minus){ - cd->defenser = (MTGCardInstance *)-1; //Oh yeah, that's ugly.... - }else{ - cd->defenser = (MTGCardInstance *)1; - } - - //Tapped, untapped - }else if (attribute.find("tapped") != string::npos){ - if (minus){ - cd->tapped = -1; - }else{ - cd->tapped = 1; - } - }else{ - int attributefound = 0; - //Colors - for (int cid = 0; cid < Constants::MTG_NB_COLORS; cid++){ - if (attribute.find(Constants::MTGColorStrings[cid]) != string::npos){ - attributefound = 1; - if (minus){ - cd->colors[cid] = -1; - }else{ - cd->colors[cid] = 1; -#ifdef WIN32 -OutputDebugString("COLOR FOUND !!!"); -#endif - } - } - } - if (!attributefound){ - //Abilities - for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){ - if (attribute.find(Constants::MTGBasicAbilities[j]) != string::npos){ - attributefound = 1; - if (minus){ - cd->basicAbilities[j] = -1; - }else{ - cd->basicAbilities[j] = 1; - } - } - } - } - - if (!attributefound){ - //Subtypes - if (minus){ - cd->setNegativeSubtype(attribute); - }else{ - cd->setSubtype(attribute); - } - } - } - } - if (nbminuses == 0){ -#ifdef WIN32 - OutputDebugString("Switching to OR\n"); -#endif - cd->mode = CD_OR; - } - typeName = typeName.substr(0,found); - } - //X targets allowed ? - if (typeName.at(typeName.length()-1) == 's' && !Subtypes::subtypesList->find(typeName)){ - typeName = typeName.substr(0,typeName.length()-1); - maxtargets = -1; - } - if (cd){ - if (!tc){ - if (typeName.compare("*")!=0) cd->setSubtype(typeName); - - tc = NEW DescriptorTargetChooser(cd,zones,nbzones,card,maxtargets); -#ifdef WIN32 - OutputDebugString("Advanced Attributes 2 \n"); -#endif - }else{ - return NULL; - } - }else{ - if (!tc){ - if (typeName.compare("*")==0){ - return NEW TargetZoneChooser(zones, nbzones,card, maxtargets); - }else{ - tc = NEW TypeTargetChooser(typeName.c_str(), zones, nbzones, card,maxtargets); - } - }else{ - ((TypeTargetChooser *)tc)->addType(typeName.c_str()); - tc->maxtargets = maxtargets; - } - } - } - return tc; } } - return NULL; + return tc; } TargetChooser * TargetChooserFactory::createTargetChooser(MTGCardInstance * card){ @@ -421,7 +405,9 @@ int DescriptorTargetChooser::canTarget(Targetable * target){ return 0; } - +DescriptorTargetChooser::~DescriptorTargetChooser(){ + SAFE_DELETE(cd); +} /** Choose a creature