diff --git a/projects/mtg/include/CardDescriptor.h b/projects/mtg/include/CardDescriptor.h index 648647a3f..058e9091a 100644 --- a/projects/mtg/include/CardDescriptor.h +++ b/projects/mtg/include/CardDescriptor.h @@ -11,6 +11,7 @@ #define CD_OR 1 #define CD_AND 2 +#define CD_NOT 3 enum ENUM_COMPARISON_MODES { @@ -23,10 +24,12 @@ enum ENUM_COMPARISON_MODES COMPARISON_UNEQUAL }; -class CardDescriptor: public MTGCardInstance{ +class CardDescriptor: public MTGCardInstance +{ protected: - MTGCardInstance * match_or(MTGCardInstance * card); - MTGCardInstance * match_and(MTGCardInstance * card); + MTGCardInstance * match_or(MTGCardInstance * card); + MTGCardInstance * match_and(MTGCardInstance * card); + MTGCardInstance * match_not(MTGCardInstance * card); bool valueInRange(int comparisonMode, int value, int criterion); public: int mode; diff --git a/projects/mtg/include/CardPrimitive.h b/projects/mtg/include/CardPrimitive.h index 1057cf7f4..f1d418c1b 100644 --- a/projects/mtg/include/CardPrimitive.h +++ b/projects/mtg/include/CardPrimitive.h @@ -11,6 +11,15 @@ using namespace std; +const uint8_t kColorBitMask_Artifact = 0x01; +const uint8_t kColorBitMask_Green = 0x02; +const uint8_t kColorBitMask_Blue = 0x04; +const uint8_t kColorBitMask_Red = 0x08; +const uint8_t kColorBitMask_Black = 0x10; +const uint8_t kColorBitMask_White = 0x20; +const uint8_t kColorBitMask_Land = 0x40; + + class CardPrimitive #ifdef TRACK_OBJECT_USAGE : public InstanceCounter @@ -25,7 +34,7 @@ public: string name; int init(); - int colors[Constants::MTG_NB_COLORS]; + uint8_t colors; map basicAbilities; map magicTexts; string magicText; @@ -44,10 +53,10 @@ public: virtual ~CardPrimitive(); void setColor(int _color, int removeAllOthers = 0); - void setColor(string _color, int removeAllOthers = 0); + void setColor(const string& _color, int removeAllOthers = 0); void removeColor(int color); int getColor(); - int hasColor(int _color); + bool hasColor(int inColor); int countColors(); int has(int ability); @@ -70,11 +79,11 @@ public: int removeType(int value, int removeAll = 0); bool hasSubtype(int _subtype); bool hasSubtype(const char * _subtype); - bool hasSubtype(string _subtype); + bool hasSubtype(const string& _subtype); bool hasType(int _type); bool hasType(const char * type); - void setManaCost(string value); + void setManaCost(const string& value); ManaCost * getManaCost(); bool isCreature(); bool isLand(); diff --git a/projects/mtg/src/CardDescriptor.cpp b/projects/mtg/src/CardDescriptor.cpp index 46d243ffc..9f7917896 100644 --- a/projects/mtg/src/CardDescriptor.cpp +++ b/projects/mtg/src/CardDescriptor.cpp @@ -101,6 +101,13 @@ bool CardDescriptor::valueInRange(int comparisonMode, int value, int criterion) return false; } +MTGCardInstance* CardDescriptor::match_not(MTGCardInstance * card) +{ + // if we have a color match, return null + bool colorFound = (colors & card->colors) > 0; + return colorFound ? NULL : card; +} + MTGCardInstance * CardDescriptor::match_or(MTGCardInstance * card) { int found = 1; @@ -128,27 +135,11 @@ MTGCardInstance * CardDescriptor::match_or(MTGCardInstance * card) if (!found) return NULL; - for (int i = 0; i < Constants::MTG_NB_COLORS; i++) + if (colors) { - if (colors[i] == 1) - { - found = 0; - if (card->hasColor(i)) - { - found = 1; - break; - } - } - else if (colors[i] == -1) - { - found = 0; - if (!card->hasColor(i)) - { - found = 1; - break; - } - } + found = (colors & card->colors); } + if (!found) return NULL; @@ -184,13 +175,8 @@ MTGCardInstance * CardDescriptor::match_and(MTGCardInstance * card) } } } - for (int i = 0; i < Constants::MTG_NB_COLORS; i++) - { - if ((colors[i] == 1 && !card->hasColor(i)) || (colors[i] == -1 && card->hasColor(i))) - { - match = NULL; - } - } + if ((colors & card->colors) != colors) + match = NULL; if (powerComparisonMode && !valueInRange(powerComparisonMode, card->getPower(), power)) match = NULL; @@ -200,21 +186,7 @@ MTGCardInstance * CardDescriptor::match_and(MTGCardInstance * card) match = NULL; if(nameComparisonMode && compareName != card->name) match = NULL; - if(colorComparisonMode) - { - bool hasMatch = false; - for (int i=0;i< Constants::MTG_NB_COLORS;i++) - { - if (card->hasColor(i) && colors[i] > 0) - { - hasMatch = true; - } - } - if( !hasMatch ) - { - match = NULL; - } - } + return match; } @@ -226,10 +198,14 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card) { match = match_and(card); } - else + else if (mode == CD_OR) { match = match_or(card); } + else + { + match = match_not(card); + } //Abilities for (map::const_iterator it = basicAbilities.begin(); it != basicAbilities.end(); ++it) diff --git a/projects/mtg/src/CardPrimitive.cpp b/projects/mtg/src/CardPrimitive.cpp index 24d1762fa..e16d67307 100644 --- a/projects/mtg/src/CardPrimitive.cpp +++ b/projects/mtg/src/CardPrimitive.cpp @@ -1,5 +1,6 @@ #include "PrecompiledHeader.h" +#include "MTGDefinitions.h" #include "CardPrimitive.h" #include "MTGDeck.h" @@ -8,9 +9,68 @@ using std::string; +namespace +{ + uint8_t ConvertColorToBitMask(int inColor) + { + uint8_t value = 0; + switch (inColor) + { + case Constants::MTG_COLOR_ARTIFACT: + value = kColorBitMask_Artifact; + break; + + case Constants::MTG_COLOR_GREEN: + value = kColorBitMask_Green; + break; + + case Constants::MTG_COLOR_BLUE: + value = kColorBitMask_Blue; + break; + + case Constants::MTG_COLOR_RED: + value = kColorBitMask_Red; + break; + + case Constants::MTG_COLOR_BLACK: + value = kColorBitMask_Black; + break; + + case Constants::MTG_COLOR_WHITE: + value = kColorBitMask_White; + break; + + case Constants::MTG_COLOR_LAND: + value = kColorBitMask_Land; + break; + + default: + break; + } + + return value; + } + + /** + ** Count the number of set bits in a given integer + */ + int CountSetBits(int n) + { + int count = 0; + while (n) + { + n &= (n-1); + count++; + } + return count; + } +} + + SUPPORT_OBJECT_ANALYTICS(CardPrimitive) CardPrimitive::CardPrimitive() + : colors(0) { init(); } @@ -22,8 +82,7 @@ CardPrimitive::CardPrimitive(CardPrimitive * source) for (size_t i = 0; i < source->types.size(); ++i) types.push_back(source->types[i]); - for (int i = 0; i < Constants::MTG_NB_COLORS; ++i) - colors[i] = source->colors[i]; + colors = source->colors; manaCost.copy(source->getManaCost()); //reducedCost.copy(source->getReducedManaCost()); //increasedCost.copy(source->getIncreasedManaCost()); @@ -56,9 +115,6 @@ int CardPrimitive::init() types.clear(); - for (int i = 0; i < Constants::MTG_NB_COLORS; ++i) - colors[i] = 0; - magicText = ""; magicTexts.clear(); spellTargetType = ""; @@ -102,17 +158,17 @@ void CardPrimitive::getOtherRestrictions() otherrestriction; } -void CardPrimitive::setColor(string _color, int removeAllOthers) +void CardPrimitive::setColor(const string& _color, int removeAllOthers) { - if (_color.compare("blue") == 0) + if (_color.compare(Constants::kManaBlue) == 0) return setColor(Constants::MTG_COLOR_BLUE, removeAllOthers); - if (_color.compare("red") == 0) + if (_color.compare(Constants::kManaRed) == 0) return setColor(Constants::MTG_COLOR_RED, removeAllOthers); - if (_color.compare("green") == 0) + if (_color.compare(Constants::kManaGreen) == 0) return setColor(Constants::MTG_COLOR_GREEN, removeAllOthers); - if (_color.compare("black") == 0) + if (_color.compare(Constants::kManaBlack) == 0) return setColor(Constants::MTG_COLOR_BLACK, removeAllOthers); - if (_color.compare("white") == 0) + if (_color.compare(Constants::kManaWhite) == 0) return setColor(Constants::MTG_COLOR_WHITE, removeAllOthers); if (_color.compare("artifact") == 0) return setColor(Constants::MTG_COLOR_ARTIFACT, removeAllOthers); @@ -121,39 +177,43 @@ void CardPrimitive::setColor(string _color, int removeAllOthers) void CardPrimitive::setColor(int _color, int removeAllOthers) { if (removeAllOthers) - for (int i = 0; i < Constants::MTG_NB_COLORS; i++) - colors[i] = 0; - colors[_color] = 1; + colors = 0; + + colors |= ConvertColorToBitMask(_color); } void CardPrimitive::removeColor(int _color) { - colors[_color] = 0; + uint8_t mask = ~ConvertColorToBitMask(_color); + colors &= mask; } int CardPrimitive::getColor() { - for (int i = 1; i < Constants::MTG_NB_COLORS; i++) - if (colors[i]) - return i; + if (colors) + { + for (int i = 1; i < Constants::MTG_NB_COLORS; i++) + if (hasColor(i)) + return i; + } + return 0; } -int CardPrimitive::hasColor(int color) +bool CardPrimitive::hasColor(int inColor) { - return (colors[color]); + return (colors & ConvertColorToBitMask(inColor)) > 0; } int CardPrimitive::countColors() { - int result = 0; - for (int i = Constants::MTG_COLOR_GREEN; i <= Constants::MTG_COLOR_WHITE; ++i) - if (hasColor(i)) - ++result; - return result; + uint8_t mask = kColorBitMask_Green | kColorBitMask_Blue | kColorBitMask_Red | kColorBitMask_Black | kColorBitMask_White; + mask &= colors; + + return CountSetBits(mask); } -void CardPrimitive::setManaCost(string s) +void CardPrimitive::setManaCost(const string& s) { ManaCost::parseManaCost(s, &manaCost); for (int i = Constants::MTG_COLOR_GREEN; i <= Constants::MTG_COLOR_WHITE; i++) @@ -163,7 +223,6 @@ void CardPrimitive::setManaCost(string s) setColor(i); } } - } void CardPrimitive::setType(const string& _type_text) @@ -290,7 +349,7 @@ bool CardPrimitive::hasSubtype(const char * _subtype) return hasType(id); } -bool CardPrimitive::hasSubtype(string _subtype) +bool CardPrimitive::hasSubtype(const string& _subtype) { int id = Subtypes::subtypesList->find(_subtype); return hasType(id); diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 9871ff2f2..58a700aa0 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -3113,8 +3113,7 @@ int AbilityFactory::getAbilities(vector * v, Spell * spell, MTGCar card->setColor(0,1); card->name = card->model->data->name; card->types = card->model->data->types; - for (int i = 0; i < Constants::MTG_NB_COLORS; ++i) - card->colors[i] = card->model->data->colors[i]; + card->colors = card->model->data->colors; for (map::const_iterator it = card->model->data->basicAbilities.begin(); it != card->model->data->basicAbilities.end(); ++it) { int i = it->first; diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 7d63333c5..236f53544 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -62,10 +62,9 @@ void MTGCardInstance::copy(MTGCardInstance * card) { types.push_back(data->types[i]); } - for (int i = 0; i < Constants::MTG_NB_COLORS; i++) - { - colors[i] = data->colors[i]; - } + + colors = data->colors; + manaCost.copy(data->getManaCost()); text = data->text; @@ -197,32 +196,33 @@ void MTGCardInstance::initMTGCI() } } int colored = 0; - + for (int i = Constants::MTG_COLOR_GREEN; i <= Constants::MTG_COLOR_WHITE; ++i) { if (this->hasColor(i)) ++colored; } - if(colored > 1) + if (colored > 1) { isMultiColored = 1; + + if(this->hasColor(Constants::MTG_COLOR_WHITE) && this->hasColor(Constants::MTG_COLOR_BLACK)) + isBlackAndWhite = 1; + if(this->hasColor(Constants::MTG_COLOR_RED) && this->hasColor(Constants::MTG_COLOR_BLUE)) + isRedAndBlue = 1; + if(this->hasColor(Constants::MTG_COLOR_GREEN) && this->hasColor(Constants::MTG_COLOR_BLACK)) + isBlackAndGreen = 1; + if(this->hasColor(Constants::MTG_COLOR_BLUE) && this->hasColor(Constants::MTG_COLOR_GREEN)) + isBlueAndGreen = 1; + if(this->hasColor(Constants::MTG_COLOR_RED) && this->hasColor(Constants::MTG_COLOR_WHITE)) + isRedAndWhite = 1; + } + + if(previous && previous->morphed && !turningOver) + { + morphed = true; + isMorphed = true; } - - if(this->hasColor(Constants::MTG_COLOR_WHITE) && this->hasColor(Constants::MTG_COLOR_BLACK)) - isBlackAndWhite = 1; - if(this->hasColor(Constants::MTG_COLOR_RED) && this->hasColor(Constants::MTG_COLOR_BLUE)) - isRedAndBlue = 1; - if(this->hasColor(Constants::MTG_COLOR_GREEN) && this->hasColor(Constants::MTG_COLOR_BLACK)) - isBlackAndGreen = 1; - if(this->hasColor(Constants::MTG_COLOR_BLUE) && this->hasColor(Constants::MTG_COLOR_GREEN)) - isBlueAndGreen = 1; - if(this->hasColor(Constants::MTG_COLOR_RED) && this->hasColor(Constants::MTG_COLOR_WHITE)) - isRedAndWhite = 1; - if(previous && previous->morphed && !turningOver) - { - morphed = true; - isMorphed = true; - } } const string MTGCardInstance::getDisplayName() const diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 286fd22df..00f9fc959 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -507,13 +507,11 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta } else if( CDtype.find("color") != string::npos ) { - for(int i = 0; i < Constants::MTG_NB_COLORS; i++) - { - if(card->target) - cd->colors[i] = card->target->colors[i]; - else - cd->colors[i] = card->colors[i]; - } + if(card->target) + cd->colors = card->target->colors; + else + cd->colors = card->colors; + cd->mode = CD_OR; } else if( CDtype.find("types") != string::npos ) @@ -571,20 +569,17 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta else { int attributefound = 0; - //Colors + //Colors - remove Artifact and Land from the loop for (int cid = 1; cid < Constants::MTG_NB_COLORS - 1; cid++) - { //remove Artifact and Land from the loop + { if (attribute.find(Constants::MTGColorStrings[cid]) != string::npos) { attributefound = 1; if (minus) { - cd->colors[cid] = -1; - } - else - { - cd->colors[cid] = 1; + cd->mode = CD_NOT; } + cd->setColor(cid); } } if (!attributefound) @@ -621,7 +616,8 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta } } } - if (nbminuses) cd->mode = CD_AND; + if (nbminuses && cd->mode != CD_NOT) + cd->mode = CD_AND; typeName = typeName.substr(0, found); } //X targets allowed ? diff --git a/projects/mtg/src/WFilter.cpp b/projects/mtg/src/WFilter.cpp index 4bd15e8dd..dbb4188f1 100644 --- a/projects/mtg/src/WFilter.cpp +++ b/projects/mtg/src/WFilter.cpp @@ -211,7 +211,7 @@ string WCFilterSet::getCode() bool WCFilterColor::isMatch(MTGCard * c) { if (!c || !c->data) return false; - return (c->data->hasColor(color) > 0); + return (c->data->hasColor(color)); } string WCFilterColor::getCode() { @@ -242,9 +242,9 @@ bool WCFilterOnlyColor::isMatch(MTGCard * c) for (int i = 0; i < Constants::MTG_NB_COLORS; i++) { if (i == color) continue; - if (c->data->hasColor(i) > 0) return false; + if (c->data->hasColor(i)) return false; } - return (c->data->hasColor(color) > 0); + return (c->data->hasColor(color)); } string WCFilterOnlyColor::getCode() {