From 99ed83c5e818ae02bf8bf469a49800b8008e4ff1 Mon Sep 17 00:00:00 2001 From: "wrenczes@gmail.com" Date: Sun, 10 Apr 2011 00:07:34 +0000 Subject: [PATCH] Performance improvements/cleanup: card->hasType("foo") performs a string lookup for an integer id. Now that our primitives have over 1000 types (1018, I believe is the number I saw while debugging), this is not the cheapest lookup. Over the course of time, a lot of new rules have crept in the code - support for 'aura', 'equipment', and recently 'planeswalker'. While profiling, I saw an inordinate amount of time being used doing map lookups for these strings. Since they're used so frequently, I've added them to the SubTypes enumeration, and swapped out doing the string lookup in favour of using the int ID directly. I also found a few places where we were using hasType("Creature") or hasType("land") when we already had helper functions to do the int lookup, so I swapped these in as appropriate, as well as a couple of places where we had hasType("instant") instead of hasType(Subtypes::TYPE_INSTANT), etc. --- projects/mtg/include/AllAbilities.h | 7 ++++--- projects/mtg/include/Subtypes.h | 6 ++++-- projects/mtg/src/AIPlayer.cpp | 2 +- projects/mtg/src/ActionStack.cpp | 3 ++- projects/mtg/src/AllAbilities.cpp | 10 +++++----- projects/mtg/src/GameObserver.cpp | 14 +++++++------- projects/mtg/src/GuiPlay.cpp | 14 ++++++++------ projects/mtg/src/MTGAbility.cpp | 24 ++++++++++++------------ projects/mtg/src/MTGGameZones.cpp | 21 ++++++++++++--------- projects/mtg/src/MTGRules.cpp | 16 ++++++++-------- projects/mtg/src/Subtypes.cpp | 9 +++------ projects/mtg/src/TargetChooser.cpp | 2 +- 12 files changed, 67 insertions(+), 61 deletions(-) diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index ef7c147c6..e6f846942 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -15,6 +15,7 @@ #include "WEvent.h" #include "GuiStatic.h" #include "GameObserver.h" +#include "Subtypes.h" #include "ThisDescriptor.h" #include #include @@ -130,7 +131,7 @@ public: intValue = 0; intValue = target->thatmuch; int checkagain = 0; - if(target->hasSubtype("aura") || target->hasSubtype("equipment")) + if(target->hasSubtype(Subtypes::TYPE_AURA) || target->hasSubtype(Subtypes::TYPE_EQUIPMENT)) { if(target->target) { @@ -2727,7 +2728,7 @@ public: { if(card->isPhased || source->isPhased) return 0; - if ((tc->source->hasSubtype("aura") || tc->source->hasSubtype("equipment") || tc->source->hasSubtype("instant") + if ((tc->source->hasSubtype(Subtypes::TYPE_AURA) || tc->source->hasSubtype(Subtypes::TYPE_EQUIPMENT) || tc->source->hasSubtype("instant") || tc->source->hasSubtype("sorcery")) && tc->canTarget(card) && card == tc->source->target && card != tc->source) return 1; return 0; } @@ -2759,7 +2760,7 @@ public: { MTGAbility * a = ability->clone(); - if (a->source->hasSubtype("aura") || a->source->hasSubtype("equipment") || a->source->hasSubtype("instant") + if (a->source->hasSubtype(Subtypes::TYPE_AURA) || a->source->hasSubtype(Subtypes::TYPE_EQUIPMENT) || a->source->hasSubtype("instant") || a->source->hasSubtype("sorcery")) { a->target = a->source->target; diff --git a/projects/mtg/include/Subtypes.h b/projects/mtg/include/Subtypes.h index 904f12290..d4ebe4da6 100644 --- a/projects/mtg/include/Subtypes.h +++ b/projects/mtg/include/Subtypes.h @@ -19,7 +19,10 @@ public: TYPE_LAND = 5, TYPE_ARTIFACT = 6, TYPE_LEGENDARY = 7, - LAST_TYPE = TYPE_LEGENDARY, + TYPE_EQUIPMENT = 8, + TYPE_AURA = 9, + TYPE_PLANESWALKER = 10, + LAST_TYPE = TYPE_PLANESWALKER, }; protected: @@ -28,7 +31,6 @@ protected: public: static Subtypes * subtypesList; Subtypes(); - int find(const char * subtype, bool forceAdd = true); int find(string subtype, bool forceAdd = true); string find(unsigned int id); }; diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index 9524cedb5..7182c69f4 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -427,7 +427,7 @@ int AIAction::getEfficiency() { MTGCardInstance * _target = (MTGCardInstance *) (a->target); //nothing huge here, just ensuring that Ai makes his noncreature becomers into creatures during first main, so it can actually use them in combat. - if (_target && !_target->hasType("Creature") && g->getCurrentGamePhase() == Constants::MTG_PHASE_FIRSTMAIN) + if (_target && !_target->isCreature() && g->getCurrentGamePhase() == Constants::MTG_PHASE_FIRSTMAIN) { efficiency = 100; } diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index f41d1665d..c9a0611f8 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -11,6 +11,7 @@ The Action Stack contains all information for Game Events that can be interrupte #include "GameOptions.h" #include "ManaCost.h" #include "MTGAbility.h" +#include "Subtypes.h" #include "TargetChooser.h" #include "Translate.h" #include "WResourceManager.h" @@ -289,7 +290,7 @@ Spell::~Spell() int Spell::resolve() { GameObserver * game = GameObserver::GetInstance(); - if (!source->hasType("instant") && !source->hasType("sorcery")) + if (!source->hasType(Subtypes::TYPE_INSTANT) && !source->hasType(Subtypes::TYPE_SORCERY)) { Player * p = source->controller(); int castMethod = source->castMethod; diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 9bb5e4aa6..ea019a53e 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -767,12 +767,12 @@ int AANewTarget::resolve() MTGCardInstance * refreshed = source->controller()->game->putInZone(_target,_target->currentZone,source->controller()->game->battlefield); Spell * reUp = NEW Spell(refreshed); - if(reUp->source->hasSubtype("aura")) + if(reUp->source->hasSubtype(Subtypes::TYPE_AURA)) { reUp->source->target = source; reUp->resolve(); } - if(_target->hasSubtype("equipment")) + if(_target->hasSubtype(Subtypes::TYPE_EQUIPMENT)) { reUp->resolve(); GameObserver * g = g->GetInstance(); @@ -3189,7 +3189,7 @@ void ABlink::Update(float dt) } Spell * spell = NEW Spell(Blinker); spell->source->counters->init(); - if(spell->source->hasSubtype("aura") && !blinkhand) + if(spell->source->hasSubtype(Subtypes::TYPE_AURA) && !blinkhand) { TargetChooserFactory tcf; TargetChooser * tc = tcf.createTargetChooser(spell->source->spellTargetType,spell->source); @@ -3223,7 +3223,7 @@ void ABlink::Update(float dt) } spell->source->power = spell->source->origpower; spell->source->toughness = spell->source->origtoughness; - if(!spell->source->hasSubtype("aura")) + if(!spell->source->hasSubtype(Subtypes::TYPE_AURA)) { spell->resolve(); if(stored) @@ -3288,7 +3288,7 @@ void ABlink::resolveBlink() } Spell * spell = NEW Spell(Blinker); spell->source->counters->init(); - if(spell->source->hasSubtype("aura") && !blinkhand) + if(spell->source->hasSubtype(Subtypes::TYPE_AURA) && !blinkhand) { TargetChooserFactory tcf; TargetChooser * tc = tcf.createTargetChooser(spell->source->spellTargetType,spell->source); diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index c95ebef89..64ee5f018 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -6,6 +6,7 @@ #include "Damage.h" #include "Rules.h" #include "ExtraCost.h" +#include "Subtypes.h" #include #include @@ -13,7 +14,6 @@ GameObserver * GameObserver::mInstance = NULL; GameObserver* GameObserver::GetInstance() { - return mInstance; } @@ -296,7 +296,7 @@ void GameObserver::startGame(Rules * rules) for (int j = 0; j < z->nb_cards; j++) { MTGCardInstance * _card = z->cards[j]; - if (_card->hasType("land")) + if (_card->isLand()) { card = _card; j = z->nb_cards; @@ -403,12 +403,12 @@ void GameObserver::gameStateBasedEffects() /////////////////////////////////////////////////////// //Remove auras that don't have a valid target anymore// /////////////////////////////////////////////////////// - if (card->target && !isInPlay(card->target) && !card->hasType("equipment")) + if (card->target && !isInPlay(card->target) && !card->hasType(Subtypes::TYPE_EQUIPMENT)) { players[i]->game->putInGraveyard(card); } card->enchanted = false; - if (card->target && isInPlay(card->target) && !card->hasType("equipment") && card->hasSubtype("aura")) + if (card->target && isInPlay(card->target) && !card->hasType(Subtypes::TYPE_EQUIPMENT) && card->hasSubtype(Subtypes::TYPE_AURA)) { card->target->enchanted = true; } @@ -455,7 +455,7 @@ void GameObserver::gameStateBasedEffects() if(card->view) card->view->alpha = 255; } - if (card->target && isInPlay(card->target) && (card->hasSubtype("equipment") || card->hasSubtype("aura"))) + if (card->target && isInPlay(card->target) && (card->hasSubtype(Subtypes::TYPE_EQUIPMENT) || card->hasSubtype(Subtypes::TYPE_AURA))) { card->isPhased = card->target->isPhased; card->phasedTurn = card->target->phasedTurn; @@ -681,7 +681,7 @@ void GameObserver::enchantmentStatus() for (int k = zone->nb_cards - 1; k >= 0; k--) { MTGCardInstance * card = zone->cards[k]; - if (card && !card->hasType("equipment") && !card->hasSubtype("aura")) + if (card && !card->hasType(Subtypes::TYPE_EQUIPMENT) && !card->hasSubtype(Subtypes::TYPE_AURA)) { card->enchanted = false; card->auras = 0; @@ -690,7 +690,7 @@ void GameObserver::enchantmentStatus() for (int j = zone->nb_cards - 1; j >= 0; j--) { MTGCardInstance * card = zone->cards[j]; - if (card->target && isInPlay(card->target) && !card->hasType("equipment") && card->hasSubtype("aura")) + if (card->target && isInPlay(card->target) && !card->hasType(Subtypes::TYPE_EQUIPMENT) && card->hasSubtype(Subtypes::TYPE_AURA)) { card->target->enchanted = true; card->target->auras += 1; diff --git a/projects/mtg/src/GuiPlay.cpp b/projects/mtg/src/GuiPlay.cpp index 928c69469..fec6b0d60 100644 --- a/projects/mtg/src/GuiPlay.cpp +++ b/projects/mtg/src/GuiPlay.cpp @@ -3,6 +3,7 @@ #include "CardSelectorSingleton.h" #include "GameApp.h" #include "GuiPlay.h" +#include "Subtypes.h" #include "Trash.h" #define CARD_WIDTH (31) @@ -10,6 +11,7 @@ const float GuiPlay::HORZWIDTH = 300.0f; const float GuiPlay::VERTHEIGHT = 80.0f; + void GuiPlay::CardStack::reset(unsigned total, float x, float y) { this->total = total; @@ -177,7 +179,7 @@ GuiPlay::~GuiPlay() bool isSpell(CardView* c) { - return c->card->isSpell() && !c->card->isCreature() && !c->card->hasType("Planeswalker"); + return c->card->isSpell() && !c->card->isCreature() && !c->card->hasType(Subtypes::TYPE_PLANESWALKER); } void GuiPlay::Replace() { @@ -189,7 +191,7 @@ void GuiPlay::Replace() for (iterator it = cards.begin(); it != end_spells; ++it) if (!(*it)->card->target) { - if(!(*it)->card->hasSubtype("aura") && !(*it)->card->hasType("Planeswalker")) + if(!(*it)->card->hasSubtype(Subtypes::TYPE_AURA) && !(*it)->card->hasType(Subtypes::TYPE_PLANESWALKER)) { if (game->players[0] == (*it)->card->controller()) ++selfSpellsN; @@ -210,7 +212,7 @@ void GuiPlay::Replace() else ++opponentCreaturesN; } - else if ((*it)->card->isLand() || (*it)->card->hasType("Planeswalker")) + else if ((*it)->card->isLand() || (*it)->card->hasType(Subtypes::TYPE_PLANESWALKER)) { if (game->players[0] == (*it)->card->controller()) ++selfLandsN; @@ -225,7 +227,7 @@ void GuiPlay::Replace() for (iterator it = cards.begin(); it != end_spells; ++it) if (!(*it)->card->target) { - if(!(*it)->card->hasSubtype("aura") && !(*it)->card->hasType("Planeswalker")) + if(!(*it)->card->hasSubtype(Subtypes::TYPE_AURA) && !(*it)->card->hasType(Subtypes::TYPE_PLANESWALKER)) { if (game->players[0] == (*it)->card->controller()) selfSpells.Enstack(*it); @@ -268,7 +270,7 @@ void GuiPlay::Replace() //rerun the iter reattaching planes walkers to the back of the lands. for (iterator it = end_spells; it != cards.end(); ++it) { - if ((*it)->card->hasType("Planeswalker")) + if ((*it)->card->hasType(Subtypes::TYPE_PLANESWALKER)) { if (game->players[0] == (*it)->card->controller()) selfLands.Enstack(*it); @@ -297,7 +299,7 @@ void GuiPlay::Render() else opponentCreatures.Render(*it, cards.begin(), end_spells); } - else if(!(*it)->card->hasType("Planeswalker")) + else if(!(*it)->card->hasType(Subtypes::TYPE_PLANESWALKER)) { if (!(*it)->card->target) { diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index b011d4ea8..97a264021 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -1214,7 +1214,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG oneShot = 1; if (activated) oneShot = 1; - if (card->hasType("sorcery") || card->hasType("instant")) + if (card->hasType(Subtypes::TYPE_SORCERY) || card->hasType(Subtypes::TYPE_INSTANT)) oneShot = 1; if (a->oneShot) oneShot = 1; @@ -1304,7 +1304,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG oneShot = 1; if (a->oneShot) oneShot = 1; - if (card->hasType("sorcery") || card->hasType("instant")) + if (card->hasType(Subtypes::TYPE_SORCERY) || card->hasType(Subtypes::TYPE_INSTANT)) oneShot = 1; found = s.find("while "); if (found != string::npos) @@ -1868,7 +1868,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG //hack for http://code.google.com/p/wagic/issues/detail?id=120 //We assume that auras don't move their own target... - if (card->hasType("aura")) + if (card->hasType(Subtypes::TYPE_AURA)) target = card; MTGAbility * a = NEW AAMover(id, card, target, szone); @@ -2300,7 +2300,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG t = spell->getNextTarget(); if (!activated) { - if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT) + if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY) || forceUEOT) { return NEW AInstantCastRestrictionUEOT(id, card, t, castTargets, value, modifyExisting, kMaxCastZones[i], who); } @@ -2608,7 +2608,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG { if (!activated) { - if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT) + if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY) || forceUEOT) { return NEW AInstantPowerToughnessModifierUntilEOT(id, card, target, wppt); } @@ -2647,7 +2647,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG fromTc->setAllZones(); if (!activated) { - if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT) + if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY) || forceUEOT) { return NULL; //TODO } @@ -2668,7 +2668,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG fromTc->setAllZones(); if (!activated) { - if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT) + if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY) || forceUEOT) { return NULL; //TODO } @@ -2690,7 +2690,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG //default target zone to opponentbattlefield here? if (!activated) { - if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT) + if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY) || forceUEOT) { return NULL; //TODO } @@ -2797,7 +2797,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG } if (!activated) { - if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT) + if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY) || forceUEOT) { return NEW AInstantBasicAbilityModifierUntilEOT(id, card, target, j, modifier); } @@ -3073,7 +3073,7 @@ int AbilityFactory::getAbilities(vector * v, Spell * spell, MTGCar magicText.append(faceupC); } - else if(card && card->hasType("equipment") && card->target) + else if(card && card->hasType(Subtypes::TYPE_EQUIPMENT) && card->target) { magicText = card->model->data->magicText; string equipText = card->magicTexts["skill"]; @@ -3451,7 +3451,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell) for (int j = inplay->nb_cards - 1; j >= 0; j--) { MTGCardInstance * card = inplay->cards[j]; - if (card->owner == player && card->hasType("artifact")) + if (card->owner == player && card->hasType(Subtypes::TYPE_ARTIFACT)) { player->game->putInZone(card, inplay, player->game->hand); } @@ -3780,7 +3780,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell) if(card->previous && card->previous->previous && card->previous->previous->suspended) card->basicAbilities[Constants::HASTE] = 1; - if (card->hasType("instant") || card->hasType("sorcery")) + if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY)) { MTGPlayerCards * zones = card->controller()->game; if (card->alternateCostPaid[ManaCost::MANA_PAID_WITH_BUYBACK] > 0) diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 17ee9b0dd..e97d6b2a9 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -5,6 +5,7 @@ #include "GameOptions.h" #include "WEvent.h" #include "MTGDeck.h" +#include "Subtypes.h" #if defined (WIN32) || defined (LINUX) #include @@ -133,7 +134,7 @@ void MTGPlayerCards::OptimizedHand(Player * who,int amount, int lands, int creat { MTGCardInstance * _card = z->cards[j]; //------------- - if (_card->hasType("Land") && optimizedland < lands) + if (_card->isLand() && optimizedland < lands) { card = _card; if (card) @@ -143,8 +144,8 @@ void MTGPlayerCards::OptimizedHand(Player * who,int amount, int lands, int creat } } //----------------first try to optimize a few cards that cost 2 or less. - if (_card->getManaCost()->getConvertedCost() <= 2 && optimizedothercards < othercards && !_card->hasType("Land") - && !_card->hasType("Creature")) + if (_card->getManaCost()->getConvertedCost() <= 2 && optimizedothercards < othercards && !_card->isLand() + && !_card->isCreature()) { card = _card; if (card) @@ -153,7 +154,7 @@ void MTGPlayerCards::OptimizedHand(Player * who,int amount, int lands, int creat optimizedothercards += 1; } } - if (_card->getManaCost()->getConvertedCost() <= 2 && optimizedcreatures < creatures && _card->hasType("Creature")) + if (_card->getManaCost()->getConvertedCost() <= 2 && optimizedcreatures < creatures && _card->isCreature()) { card = _card; if (card) @@ -168,8 +169,8 @@ void MTGPlayerCards::OptimizedHand(Player * who,int amount, int lands, int creat { MTGCardInstance * _card = z->cards[k]; - if (_card->getManaCost()->getConvertedCost() <= 3 && optimizedothercards < othercards && (!_card->hasType("Land") - || _card->hasType("Creature"))) + if (_card->getManaCost()->getConvertedCost() <= 3 && optimizedothercards < othercards && (!_card->isLand() + || _card->isCreature())) { card = _card; if (card) @@ -178,8 +179,8 @@ void MTGPlayerCards::OptimizedHand(Player * who,int amount, int lands, int creat optimizedothercards += 1; } } - if (_card->getManaCost()->getConvertedCost() <= 3 && optimizedcreatures < creatures && (_card->hasType("Creature") - || !_card->hasType("Land"))) + if (_card->getManaCost()->getConvertedCost() <= 3 && optimizedcreatures < creatures && (_card->isCreature() + || !_card->isLand())) { card = _card; if (card) @@ -478,15 +479,17 @@ MTGCardInstance * MTGGameZone::hasCard(MTGCardInstance * card) int MTGGameZone::countByType(const char * value) { int result = 0; + int subTypeId = Subtypes::subtypesList->find(value); for (int i = 0; i < (nb_cards); i++) { - if (cards[i]->hasType(value)) + if (cards[i]->hasType(subTypeId)) { result++; } } return result; } + int MTGGameZone::countByCanTarget(TargetChooser * tc) { if(!tc) diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 399e18f4a..6ed8bde1f 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -38,7 +38,7 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) if(!allowedToCast(card,player)) return 0; - if (card->hasType("land")) + if (card->isLand()) { if (currentPlayer->game->playRestrictions->canPutIntoZone(card, currentPlayer->game->inPlay) == PlayRestriction::CANT_PLAY) return 0; @@ -49,7 +49,7 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) return 1; } } - else if ((card->hasType("instant")) || card->has(Constants::FLASH) + else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)) @@ -127,7 +127,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card) ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); delete previousManaPool; - if (card->hasType("land")) + if (card->isLand()) { MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp); Spell * spell = NEW Spell(0,copy,NULL,NULL, payResult); @@ -224,7 +224,7 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * if(!allowedToAltCast(card,player)) return 0; - if (card->hasType("land")) + if (card->isLand()) { if (currentPlayer->game->playRestrictions->canPutIntoZone(card, currentPlayer->game->inPlay) == PlayRestriction::CANT_PLAY) return 0; @@ -234,7 +234,7 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * ) return 1; } - else if ((card->hasType("instant")) || card->has(Constants::FLASH) + else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)) @@ -295,7 +295,7 @@ int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card, ManaCost *alter card->alternateCostPaid[alternateCostType] = 1; - if (card->hasType("land")) + if (card->isLand()) { MTGCardInstance * copy = player->game->putInZone(card, card->currentZone, player->game->temp); Spell * spell = NEW Spell(0,copy,NULL,NULL, alternateCostType); @@ -642,7 +642,7 @@ int MTGMorphCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) if(!allowedToAltCast(card,player)) return 0; //note lands can morph too, this is different from other cost types. - if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer + if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)) @@ -1571,7 +1571,7 @@ int MTGPlaneWalkerRule::canBeInList(MTGCardInstance * card) { if(card->isPhased) return 0; - if (card->hasType("Planeswalker") && game->isInPlay(card)) + if (card->hasType(Subtypes::TYPE_PLANESWALKER) && game->isInPlay(card)) { return 1; } diff --git a/projects/mtg/src/Subtypes.cpp b/projects/mtg/src/Subtypes.cpp index 4111c553f..cf3666dfb 100644 --- a/projects/mtg/src/Subtypes.cpp +++ b/projects/mtg/src/Subtypes.cpp @@ -15,6 +15,9 @@ Subtypes::Subtypes() find("Land"); find("Artifact"); find("Legendary"); + find("Equipment"); + find("Aura"); + find("Planeswalker"); } int Subtypes::find(string value, bool forceAdd) @@ -29,12 +32,6 @@ int Subtypes::find(string value, bool forceAdd) return id; } -int Subtypes::find(const char * subtype, bool forceAdd) -{ - string value = subtype; - return find(value, forceAdd); -} - string Subtypes::find(unsigned int id) { if (valuesById.size() < id || !id) return ""; diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 67c8b7eee..e27c8fb18 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -754,7 +754,7 @@ bool TargetChooser::canTarget(Targetable * target,bool withoutProtections) tempcard = tempcard->previous; } } - if(source && ((source->hasSubtype("aura") || source->hasSubtype("equipment")) && source->target && source->target == card && source->target->isPhased && targetter->target == card)) + if(source && ((source->hasSubtype(Subtypes::TYPE_AURA) || source->hasSubtype(Subtypes::TYPE_EQUIPMENT)) && source->target && source->target == card && source->target->isPhased && targetter->target == card)) return true; //this is kinda cheating but by default we let auras and equipments always continue to target a phased creature. else if(card->isPhased)