From 7b0fdcd7219842d912373a92b99d9310c5104a00 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Wed, 1 Feb 2017 09:49:36 +0800 Subject: [PATCH] refactor Legendary Rule --- .../mtg/bin/Res/test/generic/legendary.txt | 1 + projects/mtg/include/MTGCardInstance.h | 1 + projects/mtg/include/MTGRules.h | 18 ++-- projects/mtg/include/WEvent.h | 5 + projects/mtg/src/MTGCardInstance.cpp | 16 +++ projects/mtg/src/MTGRules.cpp | 101 +++++++----------- 6 files changed, 72 insertions(+), 70 deletions(-) diff --git a/projects/mtg/bin/Res/test/generic/legendary.txt b/projects/mtg/bin/Res/test/generic/legendary.txt index 44a74aa94..46f5a1ed6 100644 --- a/projects/mtg/bin/Res/test/generic/legendary.txt +++ b/projects/mtg/bin/Res/test/generic/legendary.txt @@ -10,6 +10,7 @@ inplay:22897 [DO] 106525 choice 0 +106525 [ASSERT] FIRSTMAIN [PLAYER1] diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index 6242cfcfe..8c64487de 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -250,6 +250,7 @@ public: int getCurrentToughness(); int LKIpower; int LKItoughness; + int countDuplicateCardNames(); void cdaPT(int p = 0, int t = 0); bool isCDA; void switchPT(bool apply = false); diff --git a/projects/mtg/include/MTGRules.h b/projects/mtg/include/MTGRules.h index bc4e44d98..ecb6fde33 100644 --- a/projects/mtg/include/MTGRules.h +++ b/projects/mtg/include/MTGRules.h @@ -423,19 +423,19 @@ public: }; /* - * Rule 420.5e (Legend Rule) - * If two or more legendary permanents with the same name are in play, all are put into their - * owners' graveyards. This is called the "legend rule." If only one of those permanents is - * legendary, this rule doesn't apply. + * 704.5k If a player controls two or more legendary permanents with the same name, + * that player chooses one of them, and the rest are put into their owners’ graveyards. + * This is called the “legend rule.” */ -class MTGLegendRule: public ListMaintainerAbility +class MTGLegendRule: public PermanentAbility { public: + TargetChooser * tcL; + MTGAbility * Legendrule; + MTGAbility * LegendruleAbility; + MTGAbility * LegendruleGeneric; MTGLegendRule(GameObserver* observer, int _id); - int canBeInList(MTGCardInstance * card); - int added(MTGCardInstance * card); - int removed(MTGCardInstance * card); - int testDestroy(); + int receiveEvent(WEvent * event); virtual ostream& toString(ostream& out) const; virtual MTGLegendRule * clone() const; }; diff --git a/projects/mtg/include/WEvent.h b/projects/mtg/include/WEvent.h index 1358bf57d..29dee342a 100644 --- a/projects/mtg/include/WEvent.h +++ b/projects/mtg/include/WEvent.h @@ -79,6 +79,11 @@ struct WEventDamageStackResolved : public WEvent { WEventDamageStackResolved(); }; + +struct WEventGameStateBasedChecked : public WEvent { + WEventGameStateBasedChecked(); +}; + struct WEventPhasePreChange : public WEvent { Phase * from; Phase * to; diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index c73d0797c..ed7f7e932 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -828,6 +828,22 @@ int MTGCardInstance::getCurrentToughness() return toughness; } +int MTGCardInstance::countDuplicateCardNames() +{ + int count = 0; + + if(observer) + { + int nb_cards = controller()->game->battlefield->nb_cards; + for(int x = 0; x < nb_cards; x++) + { + if(controller()->game->battlefield->cards[x]->name == this->name) + count+=1; + } + } + return count; +} + //check stack bool MTGCardInstance::StackIsEmptyandSorcerySpeed() { diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index bbd92a56f..259c285da 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -3205,76 +3205,55 @@ MTGTokensCleanup * MTGTokensCleanup::clone() const /* Legend Rule */ MTGLegendRule::MTGLegendRule(GameObserver* observer, int _id) : -ListMaintainerAbility(observer, _id) +PermanentAbility(observer, _id) { + tcL = NULL; + Legendrule = NULL; + LegendruleAbility = NULL; + LegendruleGeneric = NULL; } ; -int MTGLegendRule::canBeInList(MTGCardInstance * card) +int MTGLegendRule::receiveEvent(WEvent * event) { - if(card->isPhased) - return 0; - if (card->hasType(Subtypes::TYPE_LEGENDARY) && card->controller()->game->inPlay->hasCard(card)) + WEventGameStateBasedChecked * e = dynamic_cast (event); + if (e) { - if(card->has(Constants::NOLEGEND)||card->controller()->opponent()->inPlay()->hasAbility(Constants::NOLEGENDRULE)||card->controller()->inPlay()->hasAbility(Constants::NOLEGENDRULE)) - return 0; - else - return 1; - } - return 0; -} - -int MTGLegendRule::added(MTGCardInstance * card) -{ - map::iterator it; - int destroy = 0; - - vectoroldCards; - for (it = cards.begin(); it != cards.end(); it++) - { - MTGCardInstance * comparison = (*it).first; - if (comparison != card && comparison->controller() == card->controller() && !(comparison->getName().compare(card->getName()))) + for (int i = 0; i < 2; i++) { - oldCards.push_back(comparison); - destroy = 1; + MTGGameZone * zone = game->players[i]->game->inPlay; + for (int k = zone->nb_cards - 1; k >= 0; k--) + { + MTGCardInstance * card = zone->cards[k]; + if (card && card->hasType(Subtypes::TYPE_LEGENDARY) && !card->isPhased) + { + if(card->has(Constants::NOLEGEND)||card->controller()->opponent()->inPlay()->hasAbility(Constants::NOLEGENDRULE)||card->controller()->inPlay()->hasAbility(Constants::NOLEGENDRULE)) + ; + else + if(card->countDuplicateCardNames() > 1) + { + vectorselection; + TargetChooserFactory tfL(game); + tcL = tfL.createTargetChooser("*[share!name!]|mybattlefield",card->clone()); + tcL->targetter = NULL; + tcL->maxtargets = card->countDuplicateCardNames()-1; + Legendrule = NEW AAMover(game, game->mLayers->actionLayer()->getMaxId(), card, NULL,"ownergraveyard","Put in Graveyard"); + Legendrule->oneShot = true; + Legendrule->canBeInterrupted = false; + LegendruleAbility = NEW GenericTargetAbility(game, "","",game->mLayers->actionLayer()->getMaxId(), card,tcL, Legendrule->clone()); + LegendruleAbility->oneShot = true; + LegendruleAbility->canBeInterrupted = false; + LegendruleGeneric = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), card,NULL,LegendruleAbility->clone()); + LegendruleGeneric->oneShot = true; + selection.push_back(LegendruleGeneric->clone()); + MTGAbility * menuChoice = NEW MenuAbility(game, game->mLayers->actionLayer()->getMaxId(), card, card,true,selection,card->controller(),"Legendary Rule"); + menuChoice->addToGame(); + return 1; + } + } + } } } - if (game->mLayers->stackLayer()->count(0, NOT_RESOLVED) != 0) - destroy = 0; - if (game->mLayers->actionLayer()->menuObject) - destroy = 0; - if (game->getCurrentTargetChooser() || game->mLayers->actionLayer()->isWaitingForAnswer()) - destroy = 0; - if(destroy) - { - vectorselection; - MultiAbility * multi = NEW MultiAbility(game, game->mLayers->actionLayer()->getMaxId(), card, card, NULL); - for(unsigned int i = 0;i < oldCards.size();i++) - { - AAMover *a = NEW AAMover(game, game->mLayers->actionLayer()->getMaxId(), card, oldCards[i],"ownergraveyard","Keep New"); - a->oneShot = true; - multi->Add(a); - } - multi->oneShot = 1; - MTGAbility * a1 = multi; - selection.push_back(a1); - AAMover *b = NEW AAMover(game, game->mLayers->actionLayer()->getMaxId(), card, card,"ownergraveyard","Keep Old"); - b->oneShot = true; - MTGAbility * b1 = b; - selection.push_back(b1); - MTGAbility * menuChoice = NEW MenuAbility(game, game->mLayers->actionLayer()->getMaxId(), card, card,true,selection,card->controller(),"Legendary Rule"); - menuChoice->addToGame(); - } - return 1; -} - -int MTGLegendRule::removed(MTGCardInstance *) -{ - return 0; -} - -int MTGLegendRule::testDestroy() -{ return 0; }