diff --git a/projects/mtg/bin/Res/rules/mtg.txt b/projects/mtg/bin/Res/rules/mtg.txt index 211a462ef..572a22a73 100644 --- a/projects/mtg/bin/Res/rules/mtg.txt +++ b/projects/mtg/bin/Res/rules/mtg.txt @@ -4,4 +4,5 @@ mode=mtg life:20 auto=shuffle auto=draw:7 -auto=@each my draw:draw:1 \ No newline at end of file +auto=@each my draw:draw:1 +auto=maxPlay(land)1 \ No newline at end of file diff --git a/projects/mtg/bin/Res/rules/testsuite.txt b/projects/mtg/bin/Res/rules/testsuite.txt index f0643f6c3..da38c9016 100644 --- a/projects/mtg/bin/Res/rules/testsuite.txt +++ b/projects/mtg/bin/Res/rules/testsuite.txt @@ -3,4 +3,5 @@ mode=mtg [PLAYERS] life:20 -auto=@each my draw:draw:1 \ No newline at end of file +auto=@each my draw:draw:1 +auto=maxPlay(land)1 \ No newline at end of file diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index 0651c7caa..d89d65310 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -414,6 +414,7 @@ ondu_cleric.txt OneDozenEyes.txt orcish_artillery.txt orcish_lumberjack.txt +orims_chant_i595.txt overrun.txt paradise_mantle.txt paralysis.txt diff --git a/projects/mtg/bin/Res/test/orims_chant_i595.txt b/projects/mtg/bin/Res/test/orims_chant_i595.txt new file mode 100644 index 000000000..5c1b35eb9 --- /dev/null +++ b/projects/mtg/bin/Res/test/orims_chant_i595.txt @@ -0,0 +1,23 @@ +#Bug with maxCast, see http://code.google.com/p/wagic/issues/detail?id=595 +#1. Have at least two or more spells in your hand, include Orim's Chant; and have enough mana in your mana pool for these spells +#2. Cast Orim's Chant on yourself +#3. Cast other spells in your hand +[init] +firstmain +[player1] +manapool:{W}{R}{1}{G} +hand:Orim's chant,raging goblin, grizzly bears +[player2] +[do] +Orim's chant +p1 +raging goblin +grizzly bears +[assert] +firstmain +[player1] +graveyard:Orim's chant +hand:raging goblin, grizzly bears +manapool:{R}{1}{G} +[player2] +[end] \ No newline at end of file diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 953cbc68a..d99bcf8c1 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -1469,7 +1469,7 @@ public: abilitygranted = ability; nbTargets = 0; tc = _tc; - if (!tc) tc = NEW CreatureTargetChooser(_source); + if (!tc) tc = NEW TypeTargetChooser("creature",_source); } void Update(float dt) @@ -4738,7 +4738,7 @@ public: counter = NEW TypeTargetChooser("land"); landsPlayedThisTurn = source->controller()->game->inPlay->seenThisTurn(counter); PlayRestrictions * restrictions = source->controller()->game->playRestrictions; - landsRestriction = (MaxPerTurnRestriction *) (restrictions->getRestrictionById(PlayRestriction::LANDS_RULE_ID)); + landsRestriction = restrictions->getMaxPerTurnRestrictionByTargetChooser(counter); restrictions->removeRestriction(landsRestriction); } @@ -4773,7 +4773,7 @@ public: int destroy() { PlayRestrictions * restrictions = source->controller()->game->playRestrictions; - if(restrictions->getRestrictionById(PlayRestriction::LANDS_RULE_ID)) + if(restrictions->getMaxPerTurnRestrictionByTargetChooser(counter)) return 1; restrictions->addRestriction(landsRestriction); @@ -5590,7 +5590,7 @@ class AMinionofLeshrac: public TargetAbility public: int paidThisTurn; AMinionofLeshrac(int _id, MTGCardInstance * source) : - TargetAbility(_id, source, NEW CreatureTargetChooser(), 0, 1, 0) + TargetAbility(_id, source, NEW TypeTargetChooser("creature"), 0, 1, 0) { paidThisTurn = 1; } diff --git a/projects/mtg/include/PlayRestrictions.h b/projects/mtg/include/PlayRestrictions.h index 9770edba6..91320b737 100644 --- a/projects/mtg/include/PlayRestrictions.h +++ b/projects/mtg/include/PlayRestrictions.h @@ -10,11 +10,6 @@ class PlayRestriction { public: - enum - { - LANDS_RULE_ID, - UNDEF_ID - }; enum { @@ -23,12 +18,11 @@ public: NO_OPINION }; - unsigned int id; TargetChooser * tc; virtual int canPutIntoZone(MTGCardInstance * card, MTGGameZone * destZone) = 0; - PlayRestriction(unsigned int id, TargetChooser * tc); + PlayRestriction(TargetChooser * tc); ~PlayRestriction(); }; @@ -41,7 +35,7 @@ public: }; int maxPerTurn; MTGGameZone * zone; - MaxPerTurnRestriction(unsigned int id, TargetChooser * tc, int maxPerTurn, MTGGameZone * zone); + MaxPerTurnRestriction(TargetChooser * tc, int maxPerTurn, MTGGameZone * zone); int canPutIntoZone(MTGCardInstance * card, MTGGameZone * destZone); }; @@ -51,7 +45,8 @@ class PlayRestrictions protected: vectorrestrictions; public: - PlayRestriction * getRestrictionById(unsigned int id); + MaxPerTurnRestriction * getMaxPerTurnRestrictionByTargetChooser(TargetChooser * tc); + void addRestriction(PlayRestriction * restriction); void removeRestriction(PlayRestriction * restriction); int canPutIntoZone(MTGCardInstance * card, MTGGameZone * destZone); diff --git a/projects/mtg/include/TargetChooser.h b/projects/mtg/include/TargetChooser.h index fcb6622d1..08c5b02ff 100644 --- a/projects/mtg/include/TargetChooser.h +++ b/projects/mtg/include/TargetChooser.h @@ -56,6 +56,11 @@ public: int targetsReadyCheck(); virtual int addTarget(Targetable * target); virtual bool canTarget(Targetable * _target); + + //returns true if tc is equivalent to this TargetChooser + //Two targetchoosers are equivalent if they target exactly the same cards + virtual bool equals(TargetChooser * tc); + virtual int full() { if (maxtargets != -1 && cursor >= maxtargets) @@ -100,6 +105,7 @@ public: virtual bool canTarget(Targetable * _card); int setAllZones(); virtual TargetZoneChooser * clone() const; + virtual bool equals(TargetChooser * tc); }; class CardTargetChooser: public TargetZoneChooser @@ -110,43 +116,7 @@ public: CardTargetChooser(MTGCardInstance * card, MTGCardInstance * source, int * zones = NULL, int nbzones = 0); virtual bool canTarget(Targetable * target); virtual CardTargetChooser * clone() const; -}; - -class CreatureTargetChooser: public TargetZoneChooser -{ -public: - CreatureTargetChooser(int * _zones, int _nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false); - CreatureTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false); - virtual bool canTarget(Targetable * _card); - virtual CreatureTargetChooser * clone() const; - -}; - -class DamageableTargetChooser: public CreatureTargetChooser -{ -public: - DamageableTargetChooser(int * _zones, int _nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false) : - CreatureTargetChooser(_zones, _nbzones, card, _maxtargets, other) - { - } - ; - DamageableTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false) : - CreatureTargetChooser(card, _maxtargets, other) - { - } - ; - virtual bool canTarget(Targetable * target); - virtual DamageableTargetChooser * clone() const; -}; - -class PlayerTargetChooser: public TargetChooser -{ -protected: - Player * p; //In Case we can only target a specific player -public: - PlayerTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1, Player *_p = NULL); - virtual bool canTarget(Targetable * target); - virtual PlayerTargetChooser * clone() const; + virtual bool equals(TargetChooser * tc); }; class TypeTargetChooser: public TargetZoneChooser @@ -160,6 +130,36 @@ public: void addType(const char * type); virtual bool canTarget(Targetable * target); virtual TypeTargetChooser * clone() const; + virtual bool equals(TargetChooser * tc); +}; + +class DamageableTargetChooser: public TypeTargetChooser +{ +public: + DamageableTargetChooser(int * _zones, int _nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false) : + TypeTargetChooser("creature",_zones, _nbzones, card, _maxtargets, other) + { + } + ; + DamageableTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false) : + TypeTargetChooser("creature", card, _maxtargets, other) + { + } + ; + virtual bool canTarget(Targetable * target); + virtual DamageableTargetChooser * clone() const; + virtual bool equals(TargetChooser * tc); +}; + +class PlayerTargetChooser: public TargetChooser +{ +protected: + Player * p; //In Case we can only target a specific player +public: + PlayerTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1, Player *_p = NULL); + virtual bool canTarget(Targetable * target); + virtual PlayerTargetChooser * clone() const; + virtual bool equals(TargetChooser * tc); }; class DescriptorTargetChooser: public TargetZoneChooser @@ -171,6 +171,7 @@ public: virtual bool canTarget(Targetable * target); ~DescriptorTargetChooser(); virtual DescriptorTargetChooser * clone() const; + virtual bool equals(TargetChooser * tc); }; class SpellTargetChooser: public TargetChooser @@ -180,6 +181,7 @@ public: SpellTargetChooser(MTGCardInstance * card = NULL, int _color = -1, int _maxtargets = 1, bool other = false); virtual bool canTarget(Targetable * target); virtual SpellTargetChooser * clone() const; + virtual bool equals(TargetChooser * tc); }; class SpellOrPermanentTargetChooser: public TargetZoneChooser @@ -189,6 +191,7 @@ public: SpellOrPermanentTargetChooser(MTGCardInstance * card = NULL, int _color = -1, int _maxtargets = 1, bool other = false); virtual bool canTarget(Targetable * target); virtual SpellOrPermanentTargetChooser * clone() const; + virtual bool equals(TargetChooser * tc); }; class DamageTargetChooser: public TargetChooser @@ -199,6 +202,7 @@ public: DamageTargetChooser(MTGCardInstance * card = NULL, int _color = -1, int _maxtargets = 1, int state = NOT_RESOLVED); virtual bool canTarget(Targetable * target); virtual DamageTargetChooser * clone() const; + virtual bool equals(TargetChooser * tc); }; //Should only be used for triggered abilities. @@ -211,6 +215,7 @@ public: virtual bool targetsZone(MTGGameZone * z); virtual bool canTarget(Targetable * _target); virtual TriggerTargetChooser * clone() const; + virtual bool equals(TargetChooser * tc); }; #endif diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index f1886a039..ad6d65d7b 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -1484,14 +1484,14 @@ int ACastRestriction::addToGame() //For now the only modifying rule is the one for lands, so this is hardcoded here. //This means that a modifying rule for anything lands will actually modify the lands rule. //In the future, we need a way to "identify" rules that modify an existing restriction, probably by doing a comparison of the TargetChoosers - existingRestriction = (MaxPerTurnRestriction *) (targetPlayer->game->playRestrictions->getRestrictionById(PlayRestriction::LANDS_RULE_ID)); + existingRestriction = targetPlayer->game->playRestrictions->getMaxPerTurnRestrictionByTargetChooser(restrictionsScope); if(existingRestriction && existingRestriction->maxPerTurn != MaxPerTurnRestriction::NO_MAX) existingRestriction->maxPerTurn += value->getValue(); } else { TargetChooser * _tc = restrictionsScope->clone(); - existingRestriction = NEW MaxPerTurnRestriction(PlayRestriction::UNDEF_ID, _tc, value->getValue(), MTGGameZone::intToZone(zoneId, source->controller(), targetPlayer)); + existingRestriction = NEW MaxPerTurnRestriction(_tc, value->getValue(), MTGGameZone::intToZone(zoneId, source->controller(), targetPlayer)); targetPlayer->game->playRestrictions->addRestriction(existingRestriction); } diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 1a2ce7dd1..6aec543c7 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -18,7 +18,7 @@ const size_t kLordKeywordsCount = 5; const string kThisKeywords[] = { "this(", "thisforeach(" }; const size_t kThisKeywordsCount = 2; -const string kMaxCastKeywords[] = { "maxplay(", "maxcost("}; +const string kMaxCastKeywords[] = { "maxplay(", "maxcast("}; const int kMaxCastZones[] = { MTGGameZone::BATTLEFIELD, MTGGameZone::STACK}; const size_t kMaxCastKeywordsCount = 2; diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 65c1628db..f0a631ad4 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -260,10 +260,7 @@ void MTGPlayerCards::init() garbage = NEW MTGGameZone(); temp = NEW MTGGameZone(); - //This is a Rule that should ideally be moved as an ability in the game... playRestrictions = NEW PlayRestrictions(); - TargetChooser * tc = NEW TypeTargetChooser("land"); - playRestrictions->addRestriction(NEW MaxPerTurnRestriction(PlayRestriction::LANDS_RULE_ID, tc, 1, inPlay)); } void MTGPlayerCards::showHand() diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 31f60af72..433edf087 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -149,7 +149,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card) if (card->has(Constants::STORM)) { - int storm = player->game->stack->seenThisTurn("*"); + int storm = player->game->stack->seenThisTurn("*") + player->opponent()->game->stack->seenThisTurn("*"); ManaCost * spellCost = player->getManaPool(); for (int i = storm; i > 1; i--) { @@ -314,8 +314,8 @@ int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card, ManaCost *alter if (card->has(Constants::STORM)) { - int storm = player->game->stack->seenThisTurn("*"); - for (int i = storm; i > 1; i--) + int storm = player->game->stack->seenThisTurn("*") + player->opponent()->game->stack->seenThisTurn("*"); + for (int i = storm; i > 1; i--) { game->mLayers->stackLayer()->addSpell(copy, NULL, playerMana, alternateCostType, 1); } diff --git a/projects/mtg/src/PlayRestrictions.cpp b/projects/mtg/src/PlayRestrictions.cpp index 57123410d..4bc0a90f1 100644 --- a/projects/mtg/src/PlayRestrictions.cpp +++ b/projects/mtg/src/PlayRestrictions.cpp @@ -5,7 +5,7 @@ #include "MTGCardInstance.h" -PlayRestriction::PlayRestriction(unsigned int id, TargetChooser * tc): id(id), tc(tc) +PlayRestriction::PlayRestriction(TargetChooser * tc): tc(tc) { tc->setAllZones(); // This is to allow targetting cards without caring about the actual zone tc->targetter = NULL; @@ -17,8 +17,8 @@ PlayRestriction::~PlayRestriction() }; -MaxPerTurnRestriction::MaxPerTurnRestriction(unsigned int id, TargetChooser * tc, int maxPerTurn, MTGGameZone * zone): - PlayRestriction(id, tc), maxPerTurn(maxPerTurn), zone(zone) +MaxPerTurnRestriction::MaxPerTurnRestriction(TargetChooser * tc, int maxPerTurn, MTGGameZone * zone): + PlayRestriction(tc), maxPerTurn(maxPerTurn), zone(zone) {} int MaxPerTurnRestriction::canPutIntoZone(MTGCardInstance * card, MTGGameZone * destZone) @@ -38,17 +38,22 @@ int MaxPerTurnRestriction::canPutIntoZone(MTGCardInstance * card, MTGGameZone * }; -PlayRestriction * PlayRestrictions::getRestrictionById(unsigned int id) +MaxPerTurnRestriction * PlayRestrictions::getMaxPerTurnRestrictionByTargetChooser(TargetChooser * tc) { - if (id == PlayRestriction::UNDEF_ID) - return NULL; // do not request Restrictions that don't have an id, there are several of them + TargetChooser * _tc = tc->clone(); + _tc->setAllZones(); // we don't care about the actual zone for the "equals" check for (vector::iterator iter = restrictions.begin(); iter != restrictions.end(); ++iter) { - if ((*iter)->id == id) - return *iter; + MaxPerTurnRestriction * mptr = dynamic_cast (*iter); + if (mptr && mptr->tc->equals(_tc)) + { + delete _tc; + return mptr; + } } + delete _tc; return NULL; } diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 3734019d2..2f02f407f 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -745,7 +745,7 @@ bool TargetChooser::canTarget(Targetable * target) } if(source && ((source->hasSubtype("aura") || source->hasSubtype("equipment")) && source->target && source->target == card && source->target->isPhased && targetter->target == card)) return true; - //this is kinda cheating but by defualt we let auras and equipments always contenue to target a phased creature. + //this is kinda cheating but by default we let auras and equipments always continue to target a phased creature. else if(card->isPhased) return false; if (source && targetter && card->isInPlay()) @@ -830,6 +830,14 @@ bool TargetChooser::validTargetsExist() return false; } +bool TargetChooser::equals(TargetChooser * tc) +{ + + //This function always return 1 for now, since the default TargetChooser targets everything + //In the future we might need to check some of "targetter" settings to take protection into account... + return true; +} + /** a specific Card **/ @@ -860,6 +868,20 @@ CardTargetChooser * CardTargetChooser::clone() const return a; } +bool CardTargetChooser::equals(TargetChooser * tc) +{ + + CardTargetChooser * ctc = dynamic_cast (tc); + if (!ctc) + return false; + + if (validTarget != ctc->validTarget) //todo, check also previous cards, see "cantarget"... + return false; + + return TargetZoneChooser::equals(tc); +} + + /** Choose anything that has a given list of types **/ @@ -940,6 +962,34 @@ TypeTargetChooser * TypeTargetChooser::clone() const return a; } +bool TypeTargetChooser ::equals(TargetChooser * tc) +{ + + TypeTargetChooser * ttc = dynamic_cast (tc); + if (!ttc) + return false; + + if (nbtypes != ttc->nbtypes) + return false; + + map counts; + + for (int i = 0; i < nbtypes; ++i) + { + counts[types[i]] +=1; + counts[ttc->types[i]] -=1; + } + + for (int i = 0; i < nbtypes; ++i) + { + if (counts[types[i]] || counts[ttc->types[i]]) + return false; + } + + return TargetZoneChooser::equals(tc); +} + + /** A Target Chooser associated to a Card Descriptor object, for fine tuning of targets description **/ @@ -1001,46 +1051,16 @@ DescriptorTargetChooser * DescriptorTargetChooser::clone() const return a; } -/** - Choose a creature - **/ - -CreatureTargetChooser::CreatureTargetChooser(MTGCardInstance * card, int _maxtargets, bool other) : - TargetZoneChooser(card, _maxtargets, other) +bool DescriptorTargetChooser::equals(TargetChooser * tc) { - int default_zones[] = { MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD }; - init(default_zones, 2); -} -CreatureTargetChooser::CreatureTargetChooser(int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets, bool other) : - TargetZoneChooser(card, _maxtargets, other) -{ - if (nbzones == 0) - { - int default_zones[] = { MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD }; - init(default_zones, 2); - } - else - { - init(_zones, nbzones); - } -} + DescriptorTargetChooser * dtc = dynamic_cast (tc); + if (!dtc) + return false; + + //TODO Descriptors need to have an "equals" method too -_- -bool CreatureTargetChooser::canTarget(Targetable * target) -{ - if (!TargetZoneChooser::canTarget(target)) return false; - if (target->typeAsTarget() == TARGET_CARD) - { - MTGCardInstance * card = (MTGCardInstance *) target; - return card->isCreature(); - } - return false; -} - -CreatureTargetChooser * CreatureTargetChooser::clone() const -{ - CreatureTargetChooser * a = NEW CreatureTargetChooser(*this); - return a; + return TargetZoneChooser::equals(tc); } /* TargetzoneChooser targets everything in a given zone */ @@ -1114,6 +1134,35 @@ TargetZoneChooser * TargetZoneChooser::clone() const return a; } +bool TargetZoneChooser::equals(TargetChooser * tc) +{ + + TargetZoneChooser * tzc = dynamic_cast (tc); + if (!tzc) + return false; + + if (nbzones!= tzc->nbzones) + return false; + + map counts; + + for (int i = 0; i < nbzones; ++i) + { + counts[zones[i]] +=1; + counts[tzc->zones[i]] -=1; + } + + for (int i = 0; i < nbzones; ++i) + { + if (counts[zones[i]] || counts[tzc->zones[i]]) + return false; + } + + //TODO: ALL_ZONES should be equivalent to something actually targetting all zones... + + return TargetChooser::equals(tc); +} + /* Player Target */ PlayerTargetChooser::PlayerTargetChooser(MTGCardInstance * card, int _maxtargets, Player *p) : TargetChooser(card, _maxtargets), p(p) @@ -1140,6 +1189,19 @@ PlayerTargetChooser* PlayerTargetChooser::clone() const return a; } +bool PlayerTargetChooser::equals(TargetChooser * tc) +{ + + PlayerTargetChooser * ptc = dynamic_cast (tc); + if (!ptc) + return false; + + if (p != ptc->p) + return false; + + return TargetChooser::equals(tc); +} + /*Damageable Target */ bool DamageableTargetChooser::canTarget(Targetable * target) { @@ -1156,7 +1218,7 @@ bool DamageableTargetChooser::canTarget(Targetable * target) { return true; } - return CreatureTargetChooser::canTarget(target); + return TypeTargetChooser::canTarget(target); } DamageableTargetChooser* DamageableTargetChooser::clone() const @@ -1165,6 +1227,16 @@ DamageableTargetChooser* DamageableTargetChooser::clone() const return a; } +bool DamageableTargetChooser::equals(TargetChooser * tc) +{ + + DamageableTargetChooser * dtc = dynamic_cast (tc); + if (!dtc) + return false; + + return TypeTargetChooser::equals(tc); +} + /*Spell */ SpellTargetChooser::SpellTargetChooser(MTGCardInstance * card, int _color, int _maxtargets, bool other) : @@ -1196,6 +1268,19 @@ SpellTargetChooser* SpellTargetChooser::clone() const return a; } +bool SpellTargetChooser::equals(TargetChooser * tc) +{ + + SpellTargetChooser * stc = dynamic_cast (tc); + if (!stc) + return false; + + if (color != stc->color) + return false; + + return TargetChooser::equals(tc); +} + /*Spell or Permanent */ SpellOrPermanentTargetChooser::SpellOrPermanentTargetChooser(MTGCardInstance * card, int _color, int _maxtargets, bool other) : TargetZoneChooser(card, _maxtargets, other) @@ -1232,6 +1317,19 @@ SpellOrPermanentTargetChooser* SpellOrPermanentTargetChooser::clone() const return a; } +bool SpellOrPermanentTargetChooser::equals(TargetChooser * tc) +{ + + SpellOrPermanentTargetChooser * sptc = dynamic_cast (tc); + if (!sptc) + return false; + + if (color != sptc->color) + return false; + + return TargetZoneChooser::equals(tc); +} + /*Damage */ DamageTargetChooser::DamageTargetChooser(MTGCardInstance * card, int _color, int _maxtargets, int _state) : TargetChooser(card, _maxtargets) @@ -1262,6 +1360,19 @@ DamageTargetChooser* DamageTargetChooser::clone() const return a; } +bool DamageTargetChooser::equals(TargetChooser * tc) +{ + + DamageTargetChooser * dtc = dynamic_cast (tc); + if (!dtc) + return false; + + if (color != dtc->color || state != dtc->state) + return false; + + return TargetChooser::equals(tc); +} + TriggerTargetChooser::TriggerTargetChooser(int _triggerTarget) { triggerTarget = _triggerTarget; @@ -1284,3 +1395,16 @@ TriggerTargetChooser * TriggerTargetChooser::clone() const TriggerTargetChooser * a = NEW TriggerTargetChooser(*this); return a; } + +bool TriggerTargetChooser::equals(TargetChooser * tc) +{ + + TriggerTargetChooser * ttc = dynamic_cast (tc); + if (!ttc) + return false; + + if (triggerTarget != ttc->triggerTarget) + return false; + + return TargetChooser::equals(tc); +} \ No newline at end of file