From f9821242099d9ca93ff80c94203681e50eaf26d4 Mon Sep 17 00:00:00 2001 From: Vittorio Alfieri Date: Mon, 18 Jan 2021 17:11:09 +0100 Subject: [PATCH] Added boast ability, refactored WParsedInt class (this class has been removed from AllAbilities.h file and it has been included into two dedicated .h and .cpp files), refactored all makefiles (Windows, Linux, PSP and Android) in order to to include the new .h and .cpp files added for WParsedInt class. --- projects/mtg/Android/jni/Android.mk | 1 + projects/mtg/Makefile | 2 +- projects/mtg/iOS/Makefile | 1 + projects/mtg/include/AllAbilities.h | 1123 +------------------------ projects/mtg/include/MTGDefinitions.h | 3 +- projects/mtg/include/WParsedInt.h | 35 + projects/mtg/src/MTGDefinitions.cpp | 3 +- projects/mtg/src/WParsedInt.cpp | 1086 ++++++++++++++++++++++++ projects/mtg/template.vcxproj | 2 + projects/mtg/template.vcxproj.filters | 6 + projects/mtg/wagic.pri | 2 + 11 files changed, 1139 insertions(+), 1125 deletions(-) create mode 100644 projects/mtg/include/WParsedInt.h create mode 100644 projects/mtg/src/WParsedInt.cpp diff --git a/projects/mtg/Android/jni/Android.mk b/projects/mtg/Android/jni/Android.mk index c4095ff56..4ddc142d8 100644 --- a/projects/mtg/Android/jni/Android.mk +++ b/projects/mtg/Android/jni/Android.mk @@ -133,6 +133,7 @@ LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.cpp \ $(MTG_PATH)/src/WFilter.cpp \ $(MTG_PATH)/src/WFont.cpp \ $(MTG_PATH)/src/WGui.cpp \ + $(MTG_PATH)/src/WParsedInt.cpp \ $(MTG_PATH)/src/WResourceManager.cpp \ $(MTG_PATH)/src/DeckView.cpp \ $(MTG_PATH)/src/CarouselDeckView.cpp \ diff --git a/projects/mtg/Makefile b/projects/mtg/Makefile index d64eb2eef..085dedbd5 100644 --- a/projects/mtg/Makefile +++ b/projects/mtg/Makefile @@ -27,7 +27,7 @@ OBJS = objs/InteractiveButton.o objs/AbilityParser.o objs/ActionElement.o\ objs/ThisDescriptor.o objs/Token.o objs/Translate.o objs/TranslateKeys.o\ objs/Trash.o objs/utils.o objs/WEvent.o objs/WResourceManager.o\ objs/WCachedResource.o objs/WDataSrc.o objs/WGui.o objs/WFilter.o objs/Tasks.o\ - objs/WFont.o objs/CarouselDeckView.o objs/GridDeckView.o objs/DeckView.o + objs/WFont.o objs/WParsedInt.o objs/CarouselDeckView.o objs/GridDeckView.o objs/DeckView.o DEPS = $(patsubst objs/%.o, deps/%.d, $(OBJS)) RESULT = $(shell psp-config --psp-prefix 2> Makefile.cache) diff --git a/projects/mtg/iOS/Makefile b/projects/mtg/iOS/Makefile index 753632933..aa252564f 100644 --- a/projects/mtg/iOS/Makefile +++ b/projects/mtg/iOS/Makefile @@ -135,6 +135,7 @@ wagic_FILES = ../../../JGE/src/iOS/main.m\ ../src/WFilter.cpp\ ../src/WFont.cpp\ ../src/WGui.cpp\ + ../src/WParsedInt.cpp\ ../src/WResourceManager.cpp \ ../src/AIPlayerBakaB.cpp \ ../src/TestSuiteAI.cpp\ diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index e8e5b97cb..e9d537ebe 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -20,6 +20,7 @@ #include #include "IconButton.h" #include "ExtraCost.h" +#include "WParsedInt.h" #include using std::map; @@ -150,1132 +151,10 @@ public: }; -class WParsedInt -{ -public: - int intValue; - - int computeX(Spell * spell, MTGCardInstance * card) - { - if (spell) return spell->computeX(card); - if (card) return card->X; - return 1; //this should only hapen when the ai calls the ability. This is to give it an idea of the "direction" of X (positive/negative) - } - -private: - void init(string s, Spell * spell, MTGCardInstance * card) - { - if(!s.size()) - return; - if (!card) - { - intValue = atoi(s.c_str());//if there is no card, try parsing a number. - return; - } - MTGCardInstance * target = card->target; - if(!card->storedCard) - card->storedCard = card->storedSourceCard; - intValue = 0; - bool halfup = false; - bool halfdown = false; - bool thirdup = false; - bool thirddown = false; - bool twice = false; - bool thrice = false; - bool other = false;//othertype:[subtype] - - if (!target) target = card; - int multiplier = 1; - if (s[0] == '-') - { - s = s.substr(1); - multiplier = -1; - if(s.find("stored") != string::npos) - { - string altered ="-"; - altered.append(s.substr(+6)); - return init(altered,spell,card->storedCard); - } - } - if(s[0] == '+') - { - //ignore "+" signs.... - s = s.substr(1); - } - if(s.find("stored") != string::npos) - { - return init(s.substr(+6),spell,card->storedCard); - } - //rounding values, the words can be written anywhere in the line, - //they are erased after parsing. - if(s.find("halfup") != string::npos) - { - halfup = true; - size_t hU = s.find("halfup"); - s.erase(hU,hU + 6); - } - if(s.find("halfdown") != string::npos) - { - halfdown = true; - size_t hD = s.find("halfdown"); - s.erase(hD,hD + 8); - } - if(s.find("thirdup") != string::npos) - { - thirdup = true; - size_t tU = s.find("thirdup"); - s.erase(tU,tU + 7); - } - if(s.find("thirddown") != string::npos) - { - thirddown = true; - size_t tD = s.find("thirddown"); - s.erase(tD,tD + 9); - } - if(s.find("twice") != string::npos) - { - twice = true; - size_t tXX = s.find("twice"); - s.erase(tXX,tXX + 5); - } - if(s.find("thrice") != string::npos) - { - thrice = true; - size_t tXXX = s.find("thrice"); - s.erase(tXXX,tXXX + 6); - } - - if(s.find("othertype") != string::npos) - { - other = true; - size_t oth = s.find("othertype"); - s.erase(oth,oth + 5); - } - if(s.find("otherpower") != string::npos) - { - other = true; - size_t otp = s.find("otherpower"); - s.erase(otp,otp + 5); - } - if(s.find("othertoughness") != string::npos) - { - other = true; - size_t ott = s.find("othertoughness"); - s.erase(ott,ott + 5); - } - if(s.find("otherconvertedcost") != string::npos) - { - other = true; - size_t otc = s.find("otherconvertedcost"); - s.erase(otc,otc + 5); - } - - if (s.find("plusend") != string::npos || s.find("minusend") != string::npos || s.find("math") != string::npos) - { - //plus#plusend and minus#minusend splits the first part and second parts and parses the - //ints for each part, then either adds or subtracts those 2 variables as specified. - vectormathFound = parseBetween(s, "math", "mathend", true); - if (mathFound.size())//maths allows us to get the value before applying multipliers - { - WParsedInt numPar(mathFound[1], NULL, card); - intValue = numPar.getValue(); - - } - else - { - vectorplusSplit = parseBetween(s, "", "plus", true); - if (plusSplit.size()) - { - WParsedInt numPar(plusSplit[1], NULL, card); - intValue = numPar.getValue(); - } - vectorplusFound = parseBetween(s, "plus", "plusend", true); - if (plusFound.size()) - { - WParsedInt numPar(plusFound[1], NULL, card); - intValue += numPar.getValue(); - } - vectorminusSplit = parseBetween(s, "", "minus", true); - if (minusSplit.size()) - { - WParsedInt numPar(minusSplit[1], NULL, card); - intValue = numPar.getValue(); - } - vectorminusFound = parseBetween(s, "minus", "minusend", true); - if (minusFound.size()) - { - WParsedInt numPar(minusFound[1], NULL, card); - intValue -= numPar.getValue(); - } - } - } - else if(s == "prex") - { - if (card->setX > -1) - { - intValue = card->setX; - } - else - { - ManaCost * cX = card->controller()->getManaPool()->Diff(card->getManaCost()); - intValue = cX->getCost(Constants::NB_Colors); - delete cX; - } - } - else if (s == "x" || s == "X" || s == "fullpaid") - { - intValue = computeX(spell, card); - if(intValue < 0) - intValue = 0; - } - else if (s == "xx" || s == "XX" || s == "halfpaid") - { - intValue = computeX(spell, card) / 2; - if(intValue < 0) - intValue = 0; - } - else if (s == "castx" || s == "Iroas")//calculate castx - devotion to red white - { - intValue = (s == "castx")?card->castX:countDevotionTo(card, card->controller()->inPlay(), Constants::MTG_COLOR_RED, Constants::MTG_COLOR_WHITE); - } - else if (s == "azorius" || s == "boros")//devotion blue white - devotion red white - { - intValue = (s == "azorius")?countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_WHITE):countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_WHITE,Constants::MTG_COLOR_RED); - } - else if (s == "dimir" || s == "golgari")//devotion blue black - devotion to green black - { - intValue = (s == "dimir")?countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_BLUE):countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_GREEN); - } - else if (s == "gruul" || s == "izzet")//devotion to green red - devotion to red blue - { - intValue = (s == "gruul")?countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_GREEN,Constants::MTG_COLOR_RED):countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_RED); - } - else if (s == "orzhov" || s == "rakdos")//devotion to white black - devotion to red black - { - intValue = (s == "orzhov")?countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_WHITE):countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_RED); - } - else if (s == "selesnya" || s == "simic")//devotion to green white - devotion to green blue - { - intValue = (s == "selesnya")?countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_GREEN,Constants::MTG_COLOR_WHITE):countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_GREEN); - } - else if (s == "gear" || s == "auras") - { - intValue = (s == "gear")?target->equipment:target->auras; - } - else if (s == "mutations" || s == "colors") - { - intValue = (s == "mutations")?target->mutation:target->countColors(); - } - else if (s == "manacost") - { - if (target->currentZone == target->controller()->game->stack)//X is 0 except if it's on the stack - intValue = target->myconvertedcost + target->castX; - else - intValue = target->myconvertedcost; - } - else if (s.find("type:") != string::npos) - { - size_t begins = s.find("type:"); - string theType = s.substr(begins + 5); - size_t typepos = theType.find("chosentype"); - if(typepos != string::npos && card->chooseasubtype != "") - theType.replace(typepos, 10, card->chooseasubtype); - size_t colpos = theType.find("chosencolor"); - if(colpos != string::npos && card->chooseacolor >= 0){ - if(card->chooseacolor == Constants::MTG_COLOR_ARTIFACT) - theType.replace(colpos, 11, "artifact"); - else if(card->chooseacolor == Constants::MTG_COLOR_GREEN) - theType.replace(colpos, 11, "green"); - else if(card->chooseacolor == Constants::MTG_COLOR_BLUE) - theType.replace(colpos, 11, "blue"); - else if(card->chooseacolor == Constants::MTG_COLOR_RED) - theType.replace(colpos, 11, "red"); - else if(card->chooseacolor == Constants::MTG_COLOR_BLACK) - theType.replace(colpos, 11, "black"); - else if(card->chooseacolor == Constants::MTG_COLOR_WHITE) - theType.replace(colpos, 11, "white"); - else if(card->chooseacolor == Constants::MTG_COLOR_WASTE) - theType.replace(colpos, 11, "waste"); - else if(card->chooseacolor == Constants::MTG_COLOR_LAND) - theType.replace(colpos, 11, "land"); - } - size_t zoned = theType.find(":"); - if(zoned == string::npos) - { - theType.append("|mybattlefield"); - } - else - { - replace(theType.begin(), theType.end(), ':', '|'); - } - int color = 0; - if (theType.find("mana") != string::npos) { - color = ManaCost::parseManaSymbol(theType[4]); - theType.replace(0, 5, "*"); - } - TargetChooserFactory tf(card->getObserver()); - TargetChooser * tc = tf.createTargetChooser(theType.c_str(),NULL); - tc->other = other; - for (int i = 0; i < 2; i++) - { - Player * p = card->getObserver()->players[i]; - MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->commandzone, p->game->sideboard };//wish cards use sideboard - for (int k = 0; k < 7; k++) - { - MTGGameZone * zone = zones[k]; - if (tc->targetsZone(zone, card)) - { - if (color) - { - intValue += card->controller()->devotionOffset + zone->countTotalManaSymbols(tc, color); // Increase total devotion with an offset (e.g. Altar of the Pantheon) - } - else - { - intValue += zone->countByCanTarget(tc); - } - } - } - } - SAFE_DELETE(tc); - } - else if (s.find("restriction{") != string::npos) - { - vector splitRest = parseBetween(s,"restriction{","}"); - if (splitRest.size()) - { - AbilityFactory abf(target->getObserver()); - int checkCond = abf.parseCastRestrictions(target,target->controller(),splitRest[1].c_str()); - if(checkCond) - intValue = 1; - } - } - else if (s.find("counter{") != string::npos) - { - intValue = 0; - vectorcounterName = parseBetween(s,"counter{","}"); - if(counterName.size()) - { - AbilityFactory abf(target->getObserver()); - Counter * counter = abf.parseCounter(counterName[1], NULL); - if(counter && target->counters && target->counters->hasCounter(counter->name.c_str(),counter->power,counter->toughness)) - { - Counter * targetCounter = target->counters->hasCounter(counter->name.c_str(), counter->power, counter->toughness); - intValue = targetCounter->nb; - } - SAFE_DELETE(counter); - } - } - else if (s.find("convertedcost:") != string::npos || s.find("power:") != string::npos || s.find("toughness:") != string::npos) - { - bool powerCheck = false; - bool toughnessCheck = false; - bool costCheck = false; - intValue = 0; - vectorconvertedType = parseBetween(s,"convertedcost:",":"); - if(convertedType.size()) - costCheck = true; - else - { - convertedType = parseBetween(s,"power:",":"); - if(convertedType.size()) - powerCheck = true; - else - { - convertedType = parseBetween(s,"toughness:",":"); - if(convertedType.size()) - toughnessCheck = true; - } - } - if(!convertedType.size()) - return; - bool high = false; - int highest = 0; - int lowest = 5000; - if(convertedType[1].find("highest") != string::npos) - high = true; - - string theType = convertedType[2]; - size_t zoned = theType.find(":"); - if(zoned == string::npos) - { - theType.append("|mybattlefield"); - } - else - { - replace(theType.begin(), theType.end(), ':', '|'); - } - TargetChooserFactory tf(card->getObserver()); - TargetChooser * tc = tf.createTargetChooser(theType.c_str(),NULL); - tc->other = other; - int check = 0; - for (int i = 0; i < 2; i++) - { - Player * p = card->getObserver()->players[i]; - MTGGameZone * zones[] = { p->game->battlefield, p->game->graveyard, p->game->hand, p->game->library, p->game->exile }; - for (int k = 0; k < 5; k++) - { - MTGGameZone * zone = zones[k]; - if(tc->targetsZone(zone,target)) - { - for(unsigned int w = 0;w < zone->cards.size();++w) - { - MTGCardInstance * cCard = zone->cards[w]; - if(tc->canTarget(cCard)) - { - if(costCheck) - check = cCard->getManaCost()->getConvertedCost(); - if(powerCheck) - check = cCard->power; - if(toughnessCheck) - check = cCard->toughness; - - if(check > highest) - highest = check; - if(check <= lowest) - lowest = check; - } - } - } - } - } - if(lowest == 5000) - lowest = 0; - SAFE_DELETE(tc); - intValue = high?highest:lowest; - } - else if (s == "sunburst") - { - intValue = 0; - if (card && card->previous && card->previous->previous) - { - intValue = card->previous->previous->sunburst; - } - } - else if (s == "converge") - { - intValue = 0; - for (int i = Constants::MTG_COLOR_GREEN; i <= Constants::MTG_COLOR_WHITE; ++i) - { - if(card->getManaCost()->getManaUsedToCast()->hasColor(i)) - intValue +=1; - } - } - else if (s == "penergy" || s == "oenergy") - { - intValue = (s == "penergy")?card->controller()->energyCount:card->controller()->opponent()->energyCount; - } - else if (s == "pyidarocount" || s == "oyidarocount") - { - intValue = (s == "pyidarocount")?card->controller()->yidaroCount:card->controller()->opponent()->yidaroCount; - } - else if (s == "pmonarch" || s == "omonarch") - { - intValue = (s == "pmonarch")?card->controller()->monarch:card->controller()->opponent()->monarch; - } - else if (s == "psurveiloffset" || s == "osurveiloffset") - { - intValue = (s == "psurveiloffset")?card->controller()->surveilOffset:card->controller()->opponent()->surveilOffset; - } - else if (s == "pdevotionoffset" || s == "odevotionoffset") - { - intValue = (s == "pdevotionoffset")?card->controller()->devotionOffset:card->controller()->opponent()->devotionOffset; - } - else if (s == "praidcount" || s == "oraidcount") - { - intValue = (s == "praidcount")?card->controller()->raidcount:card->controller()->opponent()->raidcount; - } - else if (s == "pstormcount" || s == "ostormcount") - { - intValue = (s == "pstormcount")?card->controller()->game->stack->seenThisTurn("*", Constants::CAST_ALL):card->controller()->opponent()->game->stack->seenThisTurn("*", Constants::CAST_ALL); - } - else if (s == "countallspell") - { - intValue = card->controller()->game->stack->seenThisTurn("*", Constants::CAST_ALL) + card->controller()->opponent()->game->stack->seenThisTurn("*", Constants::CAST_ALL); - } - else if (s == "countmycrespell" || s == "countmynoncrespell") - { - intValue = (s == "countmycrespell")?card->controller()->game->stack->seenThisTurn("creature", Constants::CAST_ALL):card->controller()->game->stack->seenThisTurn("*[-creature]", Constants::CAST_ALL); - } - else if(s == "pnumofcommandcast" || s == "onumofcommandcast") - { - intValue = (s == "pnumofcommandcast")?card->controller()->numOfCommandCast:card->controller()->opponent()->numOfCommandCast; - } - else if (s == "evictpw" || s == "evictth") - { - if(card->imprintedCards.size() > 0) intValue = (s == "evictpw")?card->imprintedCards.back()->getPower():card->imprintedCards.back()->getToughness(); - } - else if (s == "evictg" || s == "evictu") - { - intValue = (s == "evictg")?card->imprintG:card->imprintU; - } - else if (s == "evictr" || s == "evictb") - { - intValue = (s == "evictr")?card->imprintR:card->imprintB; - } - else if (s == "evictw" || s == "commongreen") - { - intValue = (s == "evictw")?card->imprintW:mostCommonColor(Constants::MTG_COLOR_GREEN, card); - } - else if (s == "commonblue" || s == "commonred") - { - intValue = (s == "commonblue")?mostCommonColor(Constants::MTG_COLOR_BLUE, card):mostCommonColor(Constants::MTG_COLOR_RED, card); - } - else if (s == "commonblack" || s == "commonwhite") - { - intValue = (s == "commonblack")?mostCommonColor(Constants::MTG_COLOR_BLACK, card):mostCommonColor(Constants::MTG_COLOR_WHITE, card); - } - else if (s == "targetedcurses") - { - if(card->playerTarget) - intValue = card->playerTarget->curses.size(); - } - else if (s == "lifetotal" || s == "opponentlifetotal") - { - intValue = (s == "lifetotal")?target->controller()->life:target->controller()->opponent()->life; - } - else if (s == "startinglife" || s == "ostartinglife") - { - intValue = (s == "startinglife")?target->controller()->initLife:target->controller()->opponent()->initLife; - } - else if (s == "pdiffinitlife" || s == "odiffinitlife") - { - intValue = (s == "pdiffinitlife")?(target->controller()->life - target->controller()->initLife):(target->controller()->opponent()->life - target->controller()->opponent()->initLife); - } - else if (s == "phalfinitlife" || s == "ohalfinitlife") - { - if(s == "phalfinitlife"){ - intValue = (target->controller()->initLife > 2*target->controller()->life)?1:0; - } else { - intValue = (target->controller()->opponent()->initLife > 2*target->controller()->opponent()->life)?1:0; - } - } - else if (s == "abundantlife")//current life is morethan or equal to starting life - { - intValue = (target->controller()->life >= target->controller()->initLife)?1:0; - } - else if (s == "plibrarycount") - { - intValue = (target->controller()->game->library->nb_cards)?target->controller()->game->library->nb_cards:0; - } - else if (s == "olibrarycount") - { - intValue = (target->controller()->opponent()->game->library->nb_cards)?target->controller()->opponent()->game->library->nb_cards:0; - } - else if (s == "highestlifetotal") - { - intValue = target->controller()->life <= target->controller()->opponent()->life?target->controller()->opponent()->life:target->controller()->life; - } - else if (s == "lowestlifetotal") - { - intValue = target->controller()->life <= target->controller()->opponent()->life?target->controller()->life:target->controller()->opponent()->life; - } - else if (s == "thatmuch") - { - //the value that much is a variable to be used with triggered abilities. - //ie:when ever you gain life, draw that many cards. when used in a trigger draw:thatmuch, will return the value - //that the triggered event stored in the card for "that much". - intValue = target->thatmuch; - int checkagain = 0; - if(target->hasSubtype(Subtypes::TYPE_AURA) || target->hasSubtype(Subtypes::TYPE_EQUIPMENT)){ - if(target->target){ - checkagain = target->target->thatmuch; - } - } - if(checkagain > intValue) - intValue = checkagain; - if(card && card->thatmuch > intValue) - intValue = card->thatmuch; - } - else if (s == "lifelost" || s == "oplifelost") - { - intValue = (s == "lifelost")?target->controller()->lifeLostThisTurn:target->controller()->opponent()->lifeLostThisTurn; - } - else if (s == "lifegain" || s == "oplifegain") - { - intValue = (s == "lifegain")?target->controller()->lifeGainedThisTurn:target->controller()->opponent()->lifeGainedThisTurn; - } - else if (s == "pdcount" || s == "odcount") - { - intValue = (s == "pdcount")?target->controller()->damageCount:target->controller()->opponent()->damageCount; - } - else if (s == "pdnoncount" || s == "odnoncount") - { - intValue = (s == "pdnoncount")?target->controller()->nonCombatDamage:target->controller()->opponent()->nonCombatDamage; - } - else if (s == "mypoisoncount" || s == "opponentpoisoncount") - { - intValue = (s == "mypoisoncount")?target->controller()->poisonCount:target->controller()->opponent()->poisonCount; - } - else if(s == "lastrollresult" || s == "lastrollchoice") - { - intValue = (s == "lastrollresult")?target->lastRollResult:target->dieSide; - } - else if(s == "lastflipresult" || s == "lastflipchoice") - { - intValue = (s == "lastflipresult")?target->lastFlipResult:target->coinSide; - } - else if (s == "pdrewcount" || s == "odrewcount") - { - intValue = (s == "pdrewcount")?target->controller()->drawCounter:target->controller()->opponent()->drawCounter; - } - else if (s == "epicactivated" || s == "currentturn") - { - intValue = (s == "epicactivated")?target->controller()->epic:target->getObserver()->turn; - } - else if (s == "canforetellcast") - { - intValue = (target->foretellTurn < 0)?0:(target->getObserver()->turn-target->foretellTurn); // Check if you can use the foretell cost from exile (CurrentTurn > ForetellTurn). - } - else if (s == "isflipped" || s == "snowcount") // Return 1 if card has been flipped -- // Snowcount is just to count the number of snow mana produced ... just for debugging purposes... - { - intValue = (s == "isflipped")?card->isFlipped:target->controller()->snowManaG + target->controller()->snowManaU +target->controller()->snowManaR + target->controller()->snowManaB + target->controller()->snowManaW + target->controller()->snowManaC; - } - else if (s == "mypoolcount" || s == "opponentpoolcount") // total manapool - { - intValue = (s == "mypoolcount")?target->controller()->getManaPool()->getConvertedCost():target->controller()->opponent()->getManaPool()->getConvertedCost(); - } - else if (s == "mygreenpoolcount" || s == "opponentgreenpoolcount") - { - intValue = (s == "mygreenpoolcount")?target->controller()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_GREEN):target->controller()->opponent()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_GREEN); - } - else if (s == "myredpoolcount" || s == "opponentredpoolcount") - { - intValue = (s == "myredpoolcount")?target->controller()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_RED):target->controller()->opponent()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_RED); - } - else if (s == "mybluepoolcount" || s == "opponentbluepoolcount") - { - intValue = (s == "mybluepoolcount")?target->controller()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_BLUE):target->controller()->opponent()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_BLUE); - } - else if (s == "mywhitepoolcount" || s == "opponentwhitepoolcount") - { - intValue = (s == "mywhitepoolcount")?target->controller()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_WHITE):target->controller()->opponent()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_WHITE); - } - else if (s == "myblackpoolcount" || s == "opponentblackpoolcount") - { - intValue = (s == "myblackpoolcount")?target->controller()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_BLACK):target->controller()->opponent()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_BLACK); - } - else if (s == "mycolorlesspoolcount" || s == "opponentcolorlesspoolcount") - { - intValue = (s == "mycolorlesspoolcount")?target->controller()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_ARTIFACT):target->controller()->opponent()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_ARTIFACT); - } - else if (s == "p" || s == "power") - { - intValue = target->getCurrentPower(); - } - else if (s == "t" || s == "toughness") - { - intValue = target->getCurrentToughness(); - } - else if (s == "countedamount" || s == "countedbamount") - { - intValue = (s == "countedamount")?target->CountedObjects:target->CountedObjectsB; - } - else if (s == "kicked" || s == "handsize") - { - intValue = (s == "kicked")?target->kicked:target->controller()->handsize; - } - else if (s == "olandg" || s == "olandu") - { - intValue = (s == "olandg")?countManaProducedby(Constants::MTG_COLOR_GREEN, target, target->controller()->opponent()):countManaProducedby(Constants::MTG_COLOR_BLUE, target, target->controller()->opponent()); - } - else if (s == "olandr" || s == "olandb") - { - intValue = (s == "olandr")?countManaProducedby(Constants::MTG_COLOR_RED, target, target->controller()->opponent()):countManaProducedby(Constants::MTG_COLOR_BLACK, target, target->controller()->opponent()); - } - else if (s == "olandw" || s == "olandc") - { - intValue = (s == "olandw")?countManaProducedby(Constants::MTG_COLOR_WHITE, target, target->controller()->opponent()):(countManaProducedby(Constants::MTG_COLOR_ARTIFACT, target, target->controller()->opponent()) + countManaProducedby(Constants::MTG_COLOR_WASTE, target, target->controller()->opponent())); - } - else if (s == "plandg" || s == "plandu") - { - intValue = (s == "plandg")?countManaProducedby(Constants::MTG_COLOR_GREEN, target, target->controller()):countManaProducedby(Constants::MTG_COLOR_BLUE, target, target->controller()); - } - else if (s == "plandr" || s == "plandb") - { - intValue = (s == "plandr")?countManaProducedby(Constants::MTG_COLOR_RED, target, target->controller()):countManaProducedby(Constants::MTG_COLOR_BLACK, target, target->controller()); - } - else if (s == "plandw" || s == "plandc") - { - intValue = (s == "plandw")?countManaProducedby(Constants::MTG_COLOR_WHITE, target, target->controller()):(countManaProducedby(Constants::MTG_COLOR_ARTIFACT, target, target->controller()) + countManaProducedby(Constants::MTG_COLOR_WASTE, target, target->controller())); - } - else if (s == "cantargetmycre" || s == "cantargetoppocre")// can target my creature - can target opponent creature - { - intValue = (s == "cantargetmycre")?countCanTargetby("creature", card, card->controller()):countCanTargetby("creature", card, card->controller()->opponent()); - } - else if (s == "cantargetcre" || s == "myname")// can target any creature - name of the card you control - { - intValue = (s == "cantargetcre")?countCanTargetby("creature", card, card->controller()) + countCanTargetby("creature", card, card->controller()->opponent()):countCardNameinZone(card->name,card->controller()->inPlay()); - } - else if (s == "controllerturn")//intvalue = 1 if its your turn this(variable{controllerturn}) - { - intValue = 0; - if ( target->controller() == target->getObserver()->currentPlayer) - intValue = 1; - } - else if (s == "opponentturn")//intvalue = 1 if its your turn this(variable{opponentturn}) - { - intValue = 0; - if ( target->controller()->opponent() == target->getObserver()->currentPlayer) - intValue = 1; - } - else if (s == "phandcount" || s == "ohandcount") - { - intValue = (s == "phandcount")?target->controller()->game->hand->nb_cards:target->controller()->opponent()->game->hand->nb_cards; - } - else if (s == "urzatron")//Urza lands - { - if(card->controller()->game->battlefield->hasAlias(4192) && card->controller()->game->battlefield->hasAlias(4193) && card->controller()->game->battlefield->hasAlias(4194)) - intValue = 1; - else - intValue = 0; - } - else if (s == "worshipped")//Worship - { - if(card->controller()->game->battlefield->hasType("creature")) - intValue = card->controller()->life; - else - intValue = 0; - } - else if (s == "crewtotalpower")//crew count total power - { - intValue = 0; - for (int j = card->controller()->game->battlefield->nb_cards - 1; j >= 0; --j) - { - MTGCardInstance * crew = card->controller()->game->battlefield->cards[j]; - if (crew != card && crew->isCreature() && !crew->isTapped() && !crew->isPhased && !crew->has(Constants::CANTCREW)) - intValue += crew->power; - } - } - else if (s == "pancientooze")//Ancient Ooze - { - intValue = 0; - for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j) - if (card->controller()->game->inPlay->cards[j]->hasType(Subtypes::TYPE_CREATURE) && card->controller()->game->inPlay->cards[j] != card) - intValue += card->controller()->game->inPlay->cards[j]->getManaCost()->getConvertedCost(); - } - else if (s == "pdauntless")//Dauntless Dourbark - { - MTGGameZone * checkZone = card->controller()->inPlay(); - intValue = - countCardTypeinZone("forest",checkZone) + - countCardTypeinZone("treefolk",checkZone); - } - else if (s == "pbasiclandtypes")//Basic Land types - { - MTGGameZone * checkZone = card->controller()->inPlay(); - intValue = //mtg rules 205.4c - cardHasTypeinZone("waste", checkZone) + - cardHasTypeinZone("forest", checkZone) + - cardHasTypeinZone("plains", checkZone) + - cardHasTypeinZone("swamp", checkZone) + - cardHasTypeinZone("island", checkZone) + - cardHasTypeinZone("mountain", checkZone) + - cardHasTypeinZone("snow-covered forest", checkZone) + - cardHasTypeinZone("snow-covered plains", checkZone) + - cardHasTypeinZone("snow-covered swamp", checkZone) + - cardHasTypeinZone("snow-covered island", checkZone) + - cardHasTypeinZone("snow-covered mountain", checkZone); - } - else if (s == "pdomain")//player domain - { - MTGGameZone * checkZone = card->controller()->inPlay(); - intValue = cardHasTypeinZone("forest", checkZone) + - cardHasTypeinZone("plains", checkZone) + - cardHasTypeinZone("swamp", checkZone) + - cardHasTypeinZone("island", checkZone) + - cardHasTypeinZone("mountain", checkZone); - } - else if (s == "odomain")//opponent domain - { - MTGGameZone * checkZone = card->controller()->opponent()->inPlay(); - intValue = cardHasTypeinZone("forest", checkZone) + - cardHasTypeinZone("plains", checkZone) + - cardHasTypeinZone("swamp", checkZone) + - cardHasTypeinZone("island", checkZone) + - cardHasTypeinZone("mountain", checkZone); - } - else if (s == "allmyname")//Plague Rats and others - { - intValue = 0; - for (int i = 0; i < 2; i++) - intValue += countCardNameinZone(card->name,card->getObserver()->players[i]->game->battlefield); - } - else if (s == "pgbzombie")//Soulless One - { - intValue = 0; - for (int i = 0; i < 2; i++) - { - intValue += countCardTypeinZone("zombie",card->getObserver()->players[i]->game->graveyard); - intValue += countCardTypeinZone("zombie",card->getObserver()->players[i]->game->battlefield); - } - } - else if (s == "pginstantsorcery")//Spellheart Chimera - { - intValue = 0; - for (int j = card->controller()->game->graveyard->nb_cards - 1; j >= 0; --j) - { - if (card->controller()->game->graveyard->cards[j]->hasType(Subtypes::TYPE_INSTANT) - ||card->controller()->game->graveyard->cards[j]->hasType(Subtypes::TYPE_SORCERY)) - intValue += 1; - } - } - else if (s == "gravecardtypes")//Tarmogoyf - { - intValue = 0; - int pc = 0, tc = 0, sc = 0, lc = 0, ic = 0, ec = 0, cc = 0, ac = 0; - for (int j = 0; j < 2; j++) - { - MTGGameZone * checkZone = card->getObserver()->players[j]->game->graveyard; - if(cardHasTypeinZone("planeswalker",checkZone)) - pc = 1; - if(cardHasTypeinZone("tribal",checkZone)) - tc = 1; - if(cardHasTypeinZone("sorcery",checkZone)) - sc = 1; - if(cardHasTypeinZone("land",checkZone)) - lc = 1; - if(cardHasTypeinZone("instant",checkZone)) - ic = 1; - if(cardHasTypeinZone("enchantment",checkZone)) - ec = 1; - if(cardHasTypeinZone("creature",checkZone)) - cc = 1; - if(cardHasTypeinZone("artifact",checkZone)) - ac = 1; - } - intValue = pc+tc+sc+lc+ic+ec+cc+ac; - } - else if (s == "powertotalinplay")//Count Total Power of Creatures you control... Formidable - { - intValue = 0; - for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j) - { - if (card->controller()->game->inPlay->cards[j]->hasType(Subtypes::TYPE_CREATURE)) - intValue += card->controller()->game->inPlay->cards[j]->getCurrentPower(); - } - } - else if (s == "toughnesstotalinplay")//Count Total toughness of Creatures you control... - { - intValue = 0; - for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j) - { - if (card->controller()->game->inPlay->cards[j]->hasType(Subtypes::TYPE_CREATURE)) - intValue += card->controller()->game->inPlay->cards[j]->getCurrentToughness(); - } - } - else if (s == "calculateparty")//Count Total Creatures of party (a party consists of up to one each of Cleric, Rogue, Warrior, and Wizard)... Zendikar Rising - { - intValue = 0; - bool found_cleric = false; - bool found_warrior = false; - bool found_wizard = false; - bool found_rogue = false; - for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0 && intValue < 4; --j) - { - if (card->controller()->game->inPlay->cards[j]->hasType("Cleric") && !found_cleric){ - intValue += 1; - found_cleric = true; - continue; - } - if (card->controller()->game->inPlay->cards[j]->hasType("Rogue") && !found_rogue){ - intValue += 1; - found_rogue = true; - continue; - } - if (card->controller()->game->inPlay->cards[j]->hasType("Wizard") && !found_wizard){ - intValue += 1; - found_wizard = true; - continue; - } - if (card->controller()->game->inPlay->cards[j]->hasType("Warrior") && !found_warrior){ - intValue += 1; - found_warrior = true; - continue; - } - } - } - else if (s.find("cardcounttype") != string::npos)//Count Total Creatures of specific type - { - intValue = 0; - bool different_names = (s.find("diffcardcounttype")!=string::npos)?true:false; - string type = (s.find("diffcardcounttype")!=string::npos)?s.substr(17):s.substr(13); - vector list; - for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j) - { - if (card->controller()->game->inPlay->cards[j]->hasType(type)){ - if(!different_names) - intValue += 1; - else{ - bool name_found = false; - for(unsigned int i = 0; i < list.size() && !name_found; i++){ - if(list[i] == card->controller()->game->inPlay->cards[j]->name) - name_found = true; - } - if(!name_found){ - list.push_back(card->controller()->game->inPlay->cards[j]->name); - intValue += 1; - } - } - } - } - } - else if (s == "cursedscrollresult")//Return 1 if the cursed scroll has to give damage (calculated randomly basing on the number of unique cards in the player hand)... - { - intValue = 0; - if(card->controller()->game->hand->nb_cards){ - list unique_cards; - for (int j = 0; j < card->controller()->game->hand->nb_cards; j++){ - bool found = false; - for (unsigned int k = 0; k < unique_cards.size() && !found; k++){ - list::iterator it; - for (it = unique_cards.begin(); it != unique_cards.end(); it++){ - if(card->controller()->game->hand->cards[j]->name == *it) - found = true; - } - } - if(!found) - unique_cards.push_back(card->controller()->game->hand->cards[j]->name); - } - if(!(std::rand() % unique_cards.size())) - intValue = 1; - unique_cards.clear(); - } - } - else if (s == "mypos" || s == "bushidopoints")//hand,exile,grave & library only (library zpos is inverted so the recent one is always the top) -- bushido point - { - intValue = (s == "mypos")?card->zpos:card->bushidoPoints; - } - else if (s == "revealedp") - { - if (card->revealedLast) - intValue = card->revealedLast->power; - } - else if (s == "revealedt") - { - if (card->revealedLast) - intValue = card->revealedLast->toughness; - } - else if (s == "revealedmana") - { - if (card->revealedLast) - intValue = card->revealedLast->getManaCost()->getConvertedCost(); - } - else if(!intValue)//found nothing, try parsing a atoi - { - intValue = atoi(s.c_str()); - } - if (intValue > 0)//dont divide by 0 the rest are valid. - { - if (halfup) - { - if (intValue % 2 == 1) - intValue++; - intValue = intValue / 2; - } - if (halfdown) - intValue = intValue / 2; - - if (thirdup) - { - if (intValue % 3 > 0) - intValue = (intValue / 3) + 1; - else - intValue = intValue / 3; - } - if (thirddown) - intValue = intValue / 3; - } - if (twice) - intValue = intValue * 2; - if (thrice) - intValue = intValue * 3; - if (intValue < 0) - { - //we remove "-" at the start and are parsing for real values. - //if we ended up with a value less than 0, then we return just 0 - intValue = 0; - } - - intValue *= multiplier; - } -public: - - int countDevotionTo(MTGCardInstance * card, MTGGameZone * zone, int color1, int color2) - { - int counthybrid = 0; - TargetChooserFactory dtf(card->getObserver()); - TargetChooser * dtc = dtf.createTargetChooser("*",NULL); - if (dtc->targetsZone(zone, card)) - { - counthybrid += zone->countDevotion(dtc, color1, color2); - } - SAFE_DELETE(dtc); - return card->controller()->devotionOffset + counthybrid; // Increase total devotion with an offset (e.g. Altar of the Pantheon) - } - - int countCardNameinZone(string name, MTGGameZone * zone) - { - int count = 0; - for( int i= 0; i < zone->nb_cards; i ++) - if(zone->cards[i]->name == name) - count += 1; - return count; - } - - int countCardsInPlaybyColor(int color, GameObserver * observer) - { - int count = 0; - for (int i = 0; i < 2; i++) - { - for( int j= 0; j < observer->players[i]->inPlay()->nb_cards; j++) - if(observer->players[i]->inPlay()->cards[j]->hasColor(color)) - count += 1; - } - return count; - } - - int mostCommonColor(int color, MTGCardInstance * card) - { - int maxColor = 0; - vector colors; - - for(int i = 1; i < 6; i++) - colors.push_back( countCardsInPlaybyColor(i, card->getObserver()) ); - - for(int j = 0; j < 5; j++) - if ( colors[j] > maxColor ) - maxColor = colors[j]; - - if (countCardsInPlaybyColor(color, card->getObserver()) >= maxColor && maxColor > 0) - return 1; - - return 0; - } - - int countCardTypeinZone(string type, MTGGameZone * zone) - { - int count = 0; - for( int i= 0; i < zone->nb_cards; i ++) - if(zone->cards[i]->hasType(type)) - count += 1; - return count; - } - - int cardHasTypeinZone(const char * type, MTGGameZone * zone) - { - int count = 0; - if(zone->hasType(type)) - count = 1; - return count; - } - - int countCanTargetby(string type, MTGCardInstance * card, Player * player) - { - int count = 0; - for (int j = player->game->battlefield->nb_cards - 1; j >= 0; --j) - { - if (player->game->battlefield->cards[j]->hasType(type) && !player->game->battlefield->cards[j]->protectedAgainst(card)) - count += 1; - } - return count; - } - - int countManaProducedby(int color, MTGCardInstance * target, Player * player) - { - int count = 0; - MTGGameZone * zone = player->game->battlefield; - for(int k = 0; k < zone->nb_cards; k++) - { - MTGCardInstance * card = zone->cards[k]; - if(card->isLand() && (card != target) && card->hasSubtype("forest") && color == 1) - count++; - if(card->isLand() && (card != target) && card->hasSubtype("island") && color == 2) - count++; - if(card->isLand() && (card != target) && card->hasSubtype("mountain") && color == 3) - count++; - if(card->isLand() && (card != target) && card->hasSubtype("swamp") && color == 4) - count++; - if(card->isLand() && (card != target) && card->hasSubtype("plains") && color == 5) - count++; - if(card->isLand() && (card != target) && card->cardsAbilities.size()) - { - for(unsigned int j = 0; j < card->cardsAbilities.size(); j++) - { - if(dynamic_cast (card->cardsAbilities[j]) && dynamic_cast (card->cardsAbilities[j])->output->hasColor(color) ) - count++; - } - } - } - return count; - } - - WParsedInt(int value = 0) - { - intValue = value; - } - - WParsedInt(string s, Spell * spell, MTGCardInstance * card) - { - init(s, spell, card); - } - - WParsedInt(string s, MTGCardInstance * card) - { - init(s, NULL, card); - } - - int getValue() - { - return intValue; - } - - string getStringValue() - { - stringstream sval; - sval << intValue; - return sval.str(); - } -}; - -class WParsedPT -{ -public: - bool ok; - WParsedInt power, toughness; - - WParsedPT(int p, int t) - { - power.intValue = p; - toughness.intValue = t; - ok = true; - } - - WParsedPT(string s, Spell * spell, MTGCardInstance * card) - { - size_t found = s.find("/"); - ok = false; - if (found != string::npos) - { - size_t end = s.find(" ", found); - if (end == string::npos) end = s.size(); - size_t start = s.find_last_of(" ", found); - if (start == string::npos) - start = 0; - else - start++; - power = WParsedInt(s.substr(start, found - start), spell, card); - toughness = WParsedInt(s.substr(found + 1, end - found - 1), spell, card); - - ok = true; - } - } -}; - // //Triggers // - // Triggers When a card gets added to a zone (@movedTo) class TrCardAddedToZone: public Trigger { diff --git a/projects/mtg/include/MTGDefinitions.h b/projects/mtg/include/MTGDefinitions.h index acc566a68..5d4b1d9f2 100644 --- a/projects/mtg/include/MTGDefinitions.h +++ b/projects/mtg/include/MTGDefinitions.h @@ -300,7 +300,8 @@ class Constants CYCLING = 173, FORETELL = 174, ANYTYPEOFMANAABILITY = 175, - NB_BASIC_ABILITIES = 176, + BOAST = 176, + NB_BASIC_ABILITIES = 177, RARITY_S = 'S', //Special Rarity RARITY_M = 'M', //Mythics diff --git a/projects/mtg/include/WParsedInt.h b/projects/mtg/include/WParsedInt.h new file mode 100644 index 000000000..f5f7d3176 --- /dev/null +++ b/projects/mtg/include/WParsedInt.h @@ -0,0 +1,35 @@ +class WParsedInt +{ +private: + void init(string s, Spell * spell, MTGCardInstance * card); + +public: + int intValue; + + int getValue(); + string getStringValue(); + + int computeX(Spell * spell, MTGCardInstance * card); + int countDevotionTo(MTGCardInstance * card, MTGGameZone * zone, int color1, int color2); + int countCardNameinZone(string name, MTGGameZone * zone); + int countCardsInPlaybyColor(int color, GameObserver * observer); + int mostCommonColor(int color, MTGCardInstance * card); + int countCardTypeinZone(string type, MTGGameZone * zone); + int cardHasTypeinZone(const char * type, MTGGameZone * zone); + int countCanTargetby(string type, MTGCardInstance * card, Player * player); + int countManaProducedby(int color, MTGCardInstance * target, Player * player); + + WParsedInt(int value = 0); + WParsedInt(string s, Spell * spell, MTGCardInstance * card); + WParsedInt(string s, MTGCardInstance * card); +}; + +class WParsedPT +{ +public: + bool ok; + WParsedInt power, toughness; + + WParsedPT(int p, int t); + WParsedPT(string s, Spell * spell, MTGCardInstance * card); +}; \ No newline at end of file diff --git a/projects/mtg/src/MTGDefinitions.cpp b/projects/mtg/src/MTGDefinitions.cpp index 6516c3926..d61df18c0 100644 --- a/projects/mtg/src/MTGDefinitions.cpp +++ b/projects/mtg/src/MTGDefinitions.cpp @@ -206,7 +206,8 @@ const char* Constants::MTGBasicAbilities[] = { "gainedhanddeath", //It goes to hand after death (use just to give add ability to instants and sorceries which originally have not, e.g. with transforms keyword) "cycling", //It has cycling ability "foretell", //It has foretell cost - "anytypeofmanaability" //It allows to spend mana as it were of any color to activate abilities. + "anytypeofmanaability", //It allows to spend mana as it were of any color to activate abilities. + "boast" //It has boast ability }; map Constants::MTGBasicAbilitiesMap; diff --git a/projects/mtg/src/WParsedInt.cpp b/projects/mtg/src/WParsedInt.cpp new file mode 100644 index 000000000..07bad02da --- /dev/null +++ b/projects/mtg/src/WParsedInt.cpp @@ -0,0 +1,1086 @@ +#include "PrecompiledHeader.h" +#include "AllAbilities.h" + +int WParsedInt::computeX(Spell * spell, MTGCardInstance * card) +{ + if (spell) + return spell->computeX(card); + if (card) + return card->X; + return 1; //this should only hapen when the ai calls the ability. This is to give it an idea of the "direction" of X (positive/negative) +} + +void WParsedInt::init(string s, Spell * spell, MTGCardInstance * card) +{ + if(!s.size()) + return; + if (!card) + { + intValue = atoi(s.c_str());//if there is no card, try parsing a number. + return; + } + MTGCardInstance * target = card->target; + if(!card->storedCard) + card->storedCard = card->storedSourceCard; + intValue = 0; + bool halfup = false; + bool halfdown = false; + bool thirdup = false; + bool thirddown = false; + bool twice = false; + bool thrice = false; + bool other = false;//othertype:[subtype] + + if (!target) target = card; + int multiplier = 1; + if (s[0] == '-') + { + s = s.substr(1); + multiplier = -1; + if(s.find("stored") != string::npos) + { + string altered ="-"; + altered.append(s.substr(+6)); + return init(altered,spell,card->storedCard); + } + } + if(s[0] == '+') + { + //ignore "+" signs.... + s = s.substr(1); + } + if(s.find("stored") != string::npos) + { + return init(s.substr(+6),spell,card->storedCard); + } + //rounding values, the words can be written anywhere in the line, + //they are erased after parsing. + if(s.find("halfup") != string::npos) + { + halfup = true; + size_t hU = s.find("halfup"); + s.erase(hU,hU + 6); + } + if(s.find("halfdown") != string::npos) + { + halfdown = true; + size_t hD = s.find("halfdown"); + s.erase(hD,hD + 8); + } + if(s.find("thirdup") != string::npos) + { + thirdup = true; + size_t tU = s.find("thirdup"); + s.erase(tU,tU + 7); + } + if(s.find("thirddown") != string::npos) + { + thirddown = true; + size_t tD = s.find("thirddown"); + s.erase(tD,tD + 9); + } + if(s.find("twice") != string::npos) + { + twice = true; + size_t tXX = s.find("twice"); + s.erase(tXX,tXX + 5); + } + if(s.find("thrice") != string::npos) + { + thrice = true; + size_t tXXX = s.find("thrice"); + s.erase(tXXX,tXXX + 6); + } + + if(s.find("othertype") != string::npos) + { + other = true; + size_t oth = s.find("othertype"); + s.erase(oth,oth + 5); + } + if(s.find("otherpower") != string::npos) + { + other = true; + size_t otp = s.find("otherpower"); + s.erase(otp,otp + 5); + } + if(s.find("othertoughness") != string::npos) + { + other = true; + size_t ott = s.find("othertoughness"); + s.erase(ott,ott + 5); + } + if(s.find("otherconvertedcost") != string::npos) + { + other = true; + size_t otc = s.find("otherconvertedcost"); + s.erase(otc,otc + 5); + } + + if (s.find("plusend") != string::npos || s.find("minusend") != string::npos || s.find("math") != string::npos) + { + //plus#plusend and minus#minusend splits the first part and second parts and parses the + //ints for each part, then either adds or subtracts those 2 variables as specified. + vectormathFound = parseBetween(s, "math", "mathend", true); + if (mathFound.size())//maths allows us to get the value before applying multipliers + { + WParsedInt numPar(mathFound[1], NULL, card); + intValue = numPar.getValue(); + + } + else + { + vectorplusSplit = parseBetween(s, "", "plus", true); + if (plusSplit.size()) + { + WParsedInt numPar(plusSplit[1], NULL, card); + intValue = numPar.getValue(); + } + vectorplusFound = parseBetween(s, "plus", "plusend", true); + if (plusFound.size()) + { + WParsedInt numPar(plusFound[1], NULL, card); + intValue += numPar.getValue(); + } + vectorminusSplit = parseBetween(s, "", "minus", true); + if (minusSplit.size()) + { + WParsedInt numPar(minusSplit[1], NULL, card); + intValue = numPar.getValue(); + } + vectorminusFound = parseBetween(s, "minus", "minusend", true); + if (minusFound.size()) + { + WParsedInt numPar(minusFound[1], NULL, card); + intValue -= numPar.getValue(); + } + } + } + else if(s == "prex") + { + if (card->setX > -1) + { + intValue = card->setX; + } + else + { + ManaCost * cX = card->controller()->getManaPool()->Diff(card->getManaCost()); + intValue = cX->getCost(Constants::NB_Colors); + delete cX; + } + } + else if (s == "x" || s == "X" || s == "fullpaid") + { + intValue = computeX(spell, card); + if(intValue < 0) intValue = 0; + } + else if (s == "xx" || s == "XX" || s == "halfpaid") + { + intValue = computeX(spell, card) / 2; + if(intValue < 0) intValue = 0; + } + else if (s == "castx" || s == "Iroas")//calculate castx - devotion to red white + { + intValue = (s == "castx")?card->castX:countDevotionTo(card, card->controller()->inPlay(), Constants::MTG_COLOR_RED, Constants::MTG_COLOR_WHITE); + } + else if (s == "azorius" || s == "boros")//devotion blue white - devotion red white + { + intValue = (s == "azorius")?countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_WHITE):countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_WHITE,Constants::MTG_COLOR_RED); + } + else if (s == "dimir" || s == "golgari")//devotion blue black - devotion to green black + { + intValue = (s == "dimir")?countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_BLUE):countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_GREEN); + } + else if (s == "gruul" || s == "izzet")//devotion to green red - devotion to red blue + { + intValue = (s == "gruul")?countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_GREEN,Constants::MTG_COLOR_RED):countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_RED); + } + else if (s == "orzhov" || s == "rakdos")//devotion to white black - devotion to red black + { + intValue = (s == "orzhov")?countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_WHITE):countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_RED); + } + else if (s == "selesnya" || s == "simic")//devotion to green white - devotion to green blue + { + intValue = (s == "selesnya")?countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_GREEN,Constants::MTG_COLOR_WHITE):countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_GREEN); + } + else if (s == "gear" || s == "auras") + { + intValue = (s == "gear")?target->equipment:target->auras; + } + else if (s == "mutations" || s == "colors") + { + intValue = (s == "mutations")?target->mutation:target->countColors(); + } + else if (s == "manacost") + { + intValue = (target->currentZone == target->controller()->game->stack)?(target->myconvertedcost + target->castX):target->myconvertedcost;//X is 0 except if it's on the stack + } + else if (s.find("type:") != string::npos) + { + size_t begins = s.find("type:"); + string theType = s.substr(begins + 5); + size_t typepos = theType.find("chosentype"); + if(typepos != string::npos && card->chooseasubtype != "") + theType.replace(typepos, 10, card->chooseasubtype); + size_t colpos = theType.find("chosencolor"); + if(colpos != string::npos && card->chooseacolor >= 0){ + if(card->chooseacolor == Constants::MTG_COLOR_ARTIFACT) + theType.replace(colpos, 11, "artifact"); + else if(card->chooseacolor == Constants::MTG_COLOR_GREEN) + theType.replace(colpos, 11, "green"); + else if(card->chooseacolor == Constants::MTG_COLOR_BLUE) + theType.replace(colpos, 11, "blue"); + else if(card->chooseacolor == Constants::MTG_COLOR_RED) + theType.replace(colpos, 11, "red"); + else if(card->chooseacolor == Constants::MTG_COLOR_BLACK) + theType.replace(colpos, 11, "black"); + else if(card->chooseacolor == Constants::MTG_COLOR_WHITE) + theType.replace(colpos, 11, "white"); + else if(card->chooseacolor == Constants::MTG_COLOR_WASTE) + theType.replace(colpos, 11, "waste"); + else if(card->chooseacolor == Constants::MTG_COLOR_LAND) + theType.replace(colpos, 11, "land"); + } + size_t zoned = theType.find(":"); + if(zoned == string::npos) + { + theType.append("|mybattlefield"); + } + else + { + replace(theType.begin(), theType.end(), ':', '|'); + } + int color = 0; + if (theType.find("mana") != string::npos) { + color = ManaCost::parseManaSymbol(theType[4]); + theType.replace(0, 5, "*"); + } + TargetChooserFactory tf(card->getObserver()); + TargetChooser * tc = tf.createTargetChooser(theType.c_str(),NULL); + tc->other = other; + for (int i = 0; i < 2; i++) + { + Player * p = card->getObserver()->players[i]; + MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->commandzone, p->game->sideboard };//wish cards use sideboard + for (int k = 0; k < 7; k++) + { + MTGGameZone * zone = zones[k]; + if (tc->targetsZone(zone, card)) + { + if (color) + { + intValue += card->controller()->devotionOffset + zone->countTotalManaSymbols(tc, color); // Increase total devotion with an offset (e.g. Altar of the Pantheon) + } + else + { + intValue += zone->countByCanTarget(tc); + } + } + } + } + SAFE_DELETE(tc); + } + else if (s.find("restriction{") != string::npos) + { + vector splitRest = parseBetween(s,"restriction{","}"); + if (splitRest.size()) + { + AbilityFactory abf(target->getObserver()); + int checkCond = abf.parseCastRestrictions(target,target->controller(),splitRest[1].c_str()); + if(checkCond) + intValue = 1; + } + } + else if (s.find("counter{") != string::npos) + { + intValue = 0; + vectorcounterName = parseBetween(s,"counter{","}"); + if(counterName.size()) + { + AbilityFactory abf(target->getObserver()); + Counter * counter = abf.parseCounter(counterName[1], NULL); + if(counter && target->counters && target->counters->hasCounter(counter->name.c_str(),counter->power,counter->toughness)) + { + Counter * targetCounter = target->counters->hasCounter(counter->name.c_str(), counter->power, counter->toughness); + intValue = targetCounter->nb; + } + SAFE_DELETE(counter); + } + } + else if (s.find("convertedcost:") != string::npos || s.find("power:") != string::npos || s.find("toughness:") != string::npos) + { + bool powerCheck = false; + bool toughnessCheck = false; + bool costCheck = false; + intValue = 0; + vectorconvertedType = parseBetween(s,"convertedcost:",":"); + if(convertedType.size()) + costCheck = true; + else + { + convertedType = parseBetween(s,"power:",":"); + if(convertedType.size()) + powerCheck = true; + else + { + convertedType = parseBetween(s,"toughness:",":"); + if(convertedType.size()) + toughnessCheck = true; + } + } + if(!convertedType.size()) + return; + bool high = false; + int highest = 0; + int lowest = 5000; + if(convertedType[1].find("highest") != string::npos) + high = true; + + string theType = convertedType[2]; + size_t zoned = theType.find(":"); + if(zoned == string::npos) + { + theType.append("|mybattlefield"); + } + else + { + replace(theType.begin(), theType.end(), ':', '|'); + } + TargetChooserFactory tf(card->getObserver()); + TargetChooser * tc = tf.createTargetChooser(theType.c_str(),NULL); + tc->other = other; + int check = 0; + for (int i = 0; i < 2; i++) + { + Player * p = card->getObserver()->players[i]; + MTGGameZone * zones[] = { p->game->battlefield, p->game->graveyard, p->game->hand, p->game->library, p->game->exile }; + for (int k = 0; k < 5; k++) + { + MTGGameZone * zone = zones[k]; + if(tc->targetsZone(zone,target)) + { + for(unsigned int w = 0;w < zone->cards.size();++w) + { + MTGCardInstance * cCard = zone->cards[w]; + if(tc->canTarget(cCard)) + { + if(costCheck) + check = cCard->getManaCost()->getConvertedCost(); + if(powerCheck) + check = cCard->power; + if(toughnessCheck) + check = cCard->toughness; + + if(check > highest) + highest = check; + if(check <= lowest) + lowest = check; + } + } + } + } + } + if(lowest == 5000) + lowest = 0; + SAFE_DELETE(tc); + intValue = high?highest:lowest; + } + else if (s == "sunburst") + { + intValue = 0; + if (card && card->previous && card->previous->previous) + { + intValue = card->previous->previous->sunburst; + } + } + else if (s == "converge") + { + intValue = 0; + for (int i = Constants::MTG_COLOR_GREEN; i <= Constants::MTG_COLOR_WHITE; ++i) + { + if(card->getManaCost()->getManaUsedToCast()->hasColor(i)) + intValue +=1; + } + } + else if (s == "penergy" || s == "oenergy") + { + intValue = (s == "penergy")?card->controller()->energyCount:card->controller()->opponent()->energyCount; + } + else if (s == "pyidarocount" || s == "oyidarocount") + { + intValue = (s == "pyidarocount")?card->controller()->yidaroCount:card->controller()->opponent()->yidaroCount; + } + else if (s == "pmonarch" || s == "omonarch") + { + intValue = (s == "pmonarch")?card->controller()->monarch:card->controller()->opponent()->monarch; + } + else if (s == "psurveiloffset" || s == "osurveiloffset") + { + intValue = (s == "psurveiloffset")?card->controller()->surveilOffset:card->controller()->opponent()->surveilOffset; + } + else if (s == "pdevotionoffset" || s == "odevotionoffset") + { + intValue = (s == "pdevotionoffset")?card->controller()->devotionOffset:card->controller()->opponent()->devotionOffset; + } + else if (s == "praidcount" || s == "oraidcount") + { + intValue = (s == "praidcount")?card->controller()->raidcount:card->controller()->opponent()->raidcount; + } + else if (s == "pstormcount" || s == "ostormcount") + { + intValue = (s == "pstormcount")?card->controller()->game->stack->seenThisTurn("*", Constants::CAST_ALL):card->controller()->opponent()->game->stack->seenThisTurn("*", Constants::CAST_ALL); + } + else if (s == "countallspell") + { + intValue = card->controller()->game->stack->seenThisTurn("*", Constants::CAST_ALL) + card->controller()->opponent()->game->stack->seenThisTurn("*", Constants::CAST_ALL); + } + else if (s == "countmycrespell" || s == "countmynoncrespell") + { + intValue = (s == "countmycrespell")?card->controller()->game->stack->seenThisTurn("creature", Constants::CAST_ALL):card->controller()->game->stack->seenThisTurn("*[-creature]", Constants::CAST_ALL); + } + else if(s == "pnumofcommandcast" || s == "onumofcommandcast") + { + intValue = (s == "pnumofcommandcast")?card->controller()->numOfCommandCast:card->controller()->opponent()->numOfCommandCast; + } + else if (s == "evictpw" || s == "evictth") + { + if(card->imprintedCards.size() > 0) intValue = (s == "evictpw")?card->imprintedCards.back()->getPower():card->imprintedCards.back()->getToughness(); + } + else if (s == "evictg" || s == "evictu") + { + intValue = (s == "evictg")?card->imprintG:card->imprintU; + } + else if (s == "evictr" || s == "evictb") + { + intValue = (s == "evictr")?card->imprintR:card->imprintB; + } + else if (s == "evictw" || s == "commongreen") + { + intValue = (s == "evictw")?card->imprintW:mostCommonColor(Constants::MTG_COLOR_GREEN, card); + } + else if (s == "commonblue" || s == "commonred") + { + intValue = (s == "commonblue")?mostCommonColor(Constants::MTG_COLOR_BLUE, card):mostCommonColor(Constants::MTG_COLOR_RED, card); + } + else if (s == "commonblack" || s == "commonwhite") + { + intValue = (s == "commonblack")?mostCommonColor(Constants::MTG_COLOR_BLACK, card):mostCommonColor(Constants::MTG_COLOR_WHITE, card); + } + else if (s == "targetedcurses") + { + intValue = (card->playerTarget)?card->playerTarget->curses.size():0; + } + else if (s == "lifetotal" || s == "opponentlifetotal") + { + intValue = (s == "lifetotal")?target->controller()->life:target->controller()->opponent()->life; + } + else if (s == "startinglife" || s == "ostartinglife") + { + intValue = (s == "startinglife")?target->controller()->initLife:target->controller()->opponent()->initLife; + } + else if (s == "pdiffinitlife" || s == "odiffinitlife") + { + intValue = (s == "pdiffinitlife")?(target->controller()->life - target->controller()->initLife):(target->controller()->opponent()->life - target->controller()->opponent()->initLife); + } + else if (s == "phalfinitlife" || s == "ohalfinitlife") + { + if(s == "phalfinitlife"){ + intValue = (target->controller()->initLife > 2*target->controller()->life)?1:0; + } else { + intValue = (target->controller()->opponent()->initLife > 2*target->controller()->opponent()->life)?1:0; + } + } + else if (s == "abundantlife")//current life is morethan or equal to starting life + { + intValue = (target->controller()->life >= target->controller()->initLife)?1:0; + } + else if (s == "plibrarycount") + { + intValue = (target->controller()->game->library->nb_cards)?target->controller()->game->library->nb_cards:0; + } + else if (s == "olibrarycount") + { + intValue = (target->controller()->opponent()->game->library->nb_cards)?target->controller()->opponent()->game->library->nb_cards:0; + } + else if (s == "highestlifetotal") + { + intValue = target->controller()->life <= target->controller()->opponent()->life?target->controller()->opponent()->life:target->controller()->life; + } + else if (s == "lowestlifetotal") + { + intValue = target->controller()->life <= target->controller()->opponent()->life?target->controller()->life:target->controller()->opponent()->life; + } + else if (s == "thatmuch") + { + //the value that much is a variable to be used with triggered abilities. + //ie:when ever you gain life, draw that many cards. when used in a trigger draw:thatmuch, will return the value + //that the triggered event stored in the card for "that much". + intValue = target->thatmuch; + int checkagain = 0; + if(target->hasSubtype(Subtypes::TYPE_AURA) || target->hasSubtype(Subtypes::TYPE_EQUIPMENT)){ + if(target->target){ + checkagain = target->target->thatmuch; + } + } + if(checkagain > intValue) + intValue = checkagain; + if(card && card->thatmuch > intValue) + intValue = card->thatmuch; + } + else if (s == "lifelost" || s == "oplifelost") + { + intValue = (s == "lifelost")?target->controller()->lifeLostThisTurn:target->controller()->opponent()->lifeLostThisTurn; + } + else if (s == "lifegain" || s == "oplifegain") + { + intValue = (s == "lifegain")?target->controller()->lifeGainedThisTurn:target->controller()->opponent()->lifeGainedThisTurn; + } + else if (s == "pdcount" || s == "odcount") + { + intValue = (s == "pdcount")?target->controller()->damageCount:target->controller()->opponent()->damageCount; + } + else if (s == "pdnoncount" || s == "odnoncount") + { + intValue = (s == "pdnoncount")?target->controller()->nonCombatDamage:target->controller()->opponent()->nonCombatDamage; + } + else if (s == "mypoisoncount" || s == "opponentpoisoncount") + { + intValue = (s == "mypoisoncount")?target->controller()->poisonCount:target->controller()->opponent()->poisonCount; + } + else if(s == "lastrollresult" || s == "lastrollchoice") + { + intValue = (s == "lastrollresult")?target->lastRollResult:target->dieSide; + } + else if(s == "lastflipresult" || s == "lastflipchoice") + { + intValue = (s == "lastflipresult")?target->lastFlipResult:target->coinSide; + } + else if (s == "pdrewcount" || s == "odrewcount") + { + intValue = (s == "pdrewcount")?target->controller()->drawCounter:target->controller()->opponent()->drawCounter; + } + else if (s == "epicactivated" || s == "currentturn") + { + intValue = (s == "epicactivated")?target->controller()->epic:target->getObserver()->turn; + } + else if (s == "canforetellcast") + { + intValue = (target->foretellTurn < 0)?0:(target->getObserver()->turn-target->foretellTurn); // Check if you can use the foretell cost from exile (CurrentTurn > ForetellTurn). + } + else if (s == "isflipped" || s == "snowcount") // Return 1 if card has been flipped -- // Snowcount is just to count the number of snow mana produced ... just for debugging purposes... + { + intValue = (s == "isflipped")?card->isFlipped:target->controller()->snowManaG + target->controller()->snowManaU +target->controller()->snowManaR + target->controller()->snowManaB + target->controller()->snowManaW + target->controller()->snowManaC; + } + else if (s == "mypoolcount" || s == "opponentpoolcount") // total manapool + { + intValue = (s == "mypoolcount")?target->controller()->getManaPool()->getConvertedCost():target->controller()->opponent()->getManaPool()->getConvertedCost(); + } + else if (s == "mygreenpoolcount" || s == "opponentgreenpoolcount") + { + intValue = (s == "mygreenpoolcount")?target->controller()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_GREEN):target->controller()->opponent()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_GREEN); + } + else if (s == "myredpoolcount" || s == "opponentredpoolcount") + { + intValue = (s == "myredpoolcount")?target->controller()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_RED):target->controller()->opponent()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_RED); + } + else if (s == "mybluepoolcount" || s == "opponentbluepoolcount") + { + intValue = (s == "mybluepoolcount")?target->controller()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_BLUE):target->controller()->opponent()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_BLUE); + } + else if (s == "mywhitepoolcount" || s == "opponentwhitepoolcount") + { + intValue = (s == "mywhitepoolcount")?target->controller()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_WHITE):target->controller()->opponent()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_WHITE); + } + else if (s == "myblackpoolcount" || s == "opponentblackpoolcount") + { + intValue = (s == "myblackpoolcount")?target->controller()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_BLACK):target->controller()->opponent()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_BLACK); + } + else if (s == "mycolorlesspoolcount" || s == "opponentcolorlesspoolcount") + { + intValue = (s == "mycolorlesspoolcount")?target->controller()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_ARTIFACT):target->controller()->opponent()->getManaPool()->getManaSymbols(Constants::MTG_COLOR_ARTIFACT); + } + else if (s == "p" || s == "power") + { + intValue = target->getCurrentPower(); + } + else if (s == "t" || s == "toughness") + { + intValue = target->getCurrentToughness(); + } + else if (s == "countedamount" || s == "countedbamount") + { + intValue = (s == "countedamount")?target->CountedObjects:target->CountedObjectsB; + } + else if (s == "kicked" || s == "handsize") + { + intValue = (s == "kicked")?target->kicked:target->controller()->handsize; + } + else if (s == "olandg" || s == "olandu") + { + intValue = (s == "olandg")?countManaProducedby(Constants::MTG_COLOR_GREEN, target, target->controller()->opponent()):countManaProducedby(Constants::MTG_COLOR_BLUE, target, target->controller()->opponent()); + } + else if (s == "olandr" || s == "olandb") + { + intValue = (s == "olandr")?countManaProducedby(Constants::MTG_COLOR_RED, target, target->controller()->opponent()):countManaProducedby(Constants::MTG_COLOR_BLACK, target, target->controller()->opponent()); + } + else if (s == "olandw" || s == "olandc") + { + intValue = (s == "olandw")?countManaProducedby(Constants::MTG_COLOR_WHITE, target, target->controller()->opponent()):(countManaProducedby(Constants::MTG_COLOR_ARTIFACT, target, target->controller()->opponent()) + countManaProducedby(Constants::MTG_COLOR_WASTE, target, target->controller()->opponent())); + } + else if (s == "plandg" || s == "plandu") + { + intValue = (s == "plandg")?countManaProducedby(Constants::MTG_COLOR_GREEN, target, target->controller()):countManaProducedby(Constants::MTG_COLOR_BLUE, target, target->controller()); + } + else if (s == "plandr" || s == "plandb") + { + intValue = (s == "plandr")?countManaProducedby(Constants::MTG_COLOR_RED, target, target->controller()):countManaProducedby(Constants::MTG_COLOR_BLACK, target, target->controller()); + } + else if (s == "plandw" || s == "plandc") + { + intValue = (s == "plandw")?countManaProducedby(Constants::MTG_COLOR_WHITE, target, target->controller()):(countManaProducedby(Constants::MTG_COLOR_ARTIFACT, target, target->controller()) + countManaProducedby(Constants::MTG_COLOR_WASTE, target, target->controller())); + } + else if (s == "cantargetmycre" || s == "cantargetoppocre")// can target my creature - can target opponent creature + { + intValue = (s == "cantargetmycre")?countCanTargetby("creature", card, card->controller()):countCanTargetby("creature", card, card->controller()->opponent()); + } + else if (s == "cantargetcre" || s == "myname")// can target any creature - name of the card you control + { + intValue = (s == "cantargetcre")?countCanTargetby("creature", card, card->controller()) + countCanTargetby("creature", card, card->controller()->opponent()):countCardNameinZone(card->name,card->controller()->inPlay()); + } + else if (s == "controllerturn")//intvalue = 1 if its your turn this(variable{controllerturn}) + { + intValue = (target->controller() == target->getObserver()->currentPlayer)?1:0; + } + else if (s == "opponentturn")//intvalue = 1 if its your turn this(variable{opponentturn}) + { + intValue = (target->controller()->opponent() == target->getObserver()->currentPlayer)?1:0; + } + else if (s == "phandcount" || s == "ohandcount") + { + intValue = (s == "phandcount")?target->controller()->game->hand->nb_cards:target->controller()->opponent()->game->hand->nb_cards; + } + else if (s == "urzatron")//Urza lands + { + intValue = (card->controller()->game->battlefield->hasAlias(4192) && card->controller()->game->battlefield->hasAlias(4193) && card->controller()->game->battlefield->hasAlias(4194))?1:0; + } + else if (s == "worshipped")//Worship + { + intValue = (card->controller()->game->battlefield->hasType("creature"))?card->controller()->life:0; + } + else if (s == "crewtotalpower")//crew count total power + { + intValue = 0; + for (int j = card->controller()->game->battlefield->nb_cards - 1; j >= 0; --j) + { + MTGCardInstance * crew = card->controller()->game->battlefield->cards[j]; + if (crew != card && crew->isCreature() && !crew->isTapped() && !crew->isPhased && !crew->has(Constants::CANTCREW)) + intValue += crew->power; + } + } + else if (s == "pancientooze")//Ancient Ooze + { + intValue = 0; + for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j) + if (card->controller()->game->inPlay->cards[j]->hasType(Subtypes::TYPE_CREATURE) && card->controller()->game->inPlay->cards[j] != card) + intValue += card->controller()->game->inPlay->cards[j]->getManaCost()->getConvertedCost(); + } + else if (s == "pdauntless")//Dauntless Dourbark + { + MTGGameZone * checkZone = card->controller()->inPlay(); + intValue = + countCardTypeinZone("forest",checkZone) + + countCardTypeinZone("treefolk",checkZone); + } + else if (s == "pbasiclandtypes")//Basic Land types + { + MTGGameZone * checkZone = card->controller()->inPlay(); + intValue = //mtg rules 205.4c + cardHasTypeinZone("waste", checkZone) + + cardHasTypeinZone("forest", checkZone) + + cardHasTypeinZone("plains", checkZone) + + cardHasTypeinZone("swamp", checkZone) + + cardHasTypeinZone("island", checkZone) + + cardHasTypeinZone("mountain", checkZone) + + cardHasTypeinZone("snow-covered forest", checkZone) + + cardHasTypeinZone("snow-covered plains", checkZone) + + cardHasTypeinZone("snow-covered swamp", checkZone) + + cardHasTypeinZone("snow-covered island", checkZone) + + cardHasTypeinZone("snow-covered mountain", checkZone); + } + else if (s == "pdomain")//player domain + { + MTGGameZone * checkZone = card->controller()->inPlay(); + intValue = cardHasTypeinZone("forest", checkZone) + + cardHasTypeinZone("plains", checkZone) + + cardHasTypeinZone("swamp", checkZone) + + cardHasTypeinZone("island", checkZone) + + cardHasTypeinZone("mountain", checkZone); + } + else if (s == "odomain")//opponent domain + { + MTGGameZone * checkZone = card->controller()->opponent()->inPlay(); + intValue = cardHasTypeinZone("forest", checkZone) + + cardHasTypeinZone("plains", checkZone) + + cardHasTypeinZone("swamp", checkZone) + + cardHasTypeinZone("island", checkZone) + + cardHasTypeinZone("mountain", checkZone); + } + else if (s == "allmyname")//Plague Rats and others + { + intValue = 0; + for (int i = 0; i < 2; i++) + intValue += countCardNameinZone(card->name,card->getObserver()->players[i]->game->battlefield); + } + else if (s == "pgbzombie")//Soulless One + { + intValue = 0; + for (int i = 0; i < 2; i++) + { + intValue += countCardTypeinZone("zombie",card->getObserver()->players[i]->game->graveyard); + intValue += countCardTypeinZone("zombie",card->getObserver()->players[i]->game->battlefield); + } + } + else if (s == "pginstantsorcery")//Spellheart Chimera + { + intValue = 0; + for (int j = card->controller()->game->graveyard->nb_cards - 1; j >= 0; --j) + { + if (card->controller()->game->graveyard->cards[j]->hasType(Subtypes::TYPE_INSTANT) + ||card->controller()->game->graveyard->cards[j]->hasType(Subtypes::TYPE_SORCERY)) + intValue += 1; + } + } + else if (s == "gravecardtypes")//Tarmogoyf + { + intValue = 0; + int pc = 0, tc = 0, sc = 0, lc = 0, ic = 0, ec = 0, cc = 0, ac = 0; + for (int j = 0; j < 2; j++) + { + MTGGameZone * checkZone = card->getObserver()->players[j]->game->graveyard; + if(cardHasTypeinZone("planeswalker",checkZone)) + pc = 1; + if(cardHasTypeinZone("tribal",checkZone)) + tc = 1; + if(cardHasTypeinZone("sorcery",checkZone)) + sc = 1; + if(cardHasTypeinZone("land",checkZone)) + lc = 1; + if(cardHasTypeinZone("instant",checkZone)) + ic = 1; + if(cardHasTypeinZone("enchantment",checkZone)) + ec = 1; + if(cardHasTypeinZone("creature",checkZone)) + cc = 1; + if(cardHasTypeinZone("artifact",checkZone)) + ac = 1; + } + intValue = pc+tc+sc+lc+ic+ec+cc+ac; + } + else if (s == "powertotalinplay")//Count Total Power of Creatures you control... Formidable + { + intValue = 0; + for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j) + { + if (card->controller()->game->inPlay->cards[j]->hasType(Subtypes::TYPE_CREATURE)) + intValue += card->controller()->game->inPlay->cards[j]->getCurrentPower(); + } + } + else if (s == "toughnesstotalinplay")//Count Total toughness of Creatures you control... + { + intValue = 0; + for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j) + { + if (card->controller()->game->inPlay->cards[j]->hasType(Subtypes::TYPE_CREATURE)) + intValue += card->controller()->game->inPlay->cards[j]->getCurrentToughness(); + } + } + else if (s == "calculateparty")//Count Total Creatures of party (a party consists of up to one each of Cleric, Rogue, Warrior, and Wizard)... Zendikar Rising + { + intValue = 0; + bool found_cleric = false; + bool found_warrior = false; + bool found_wizard = false; + bool found_rogue = false; + for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0 && intValue < 4; --j) + { + if (card->controller()->game->inPlay->cards[j]->hasType("Cleric") && !found_cleric){ + intValue += 1; + found_cleric = true; + continue; + } + if (card->controller()->game->inPlay->cards[j]->hasType("Rogue") && !found_rogue){ + intValue += 1; + found_rogue = true; + continue; + } + if (card->controller()->game->inPlay->cards[j]->hasType("Wizard") && !found_wizard){ + intValue += 1; + found_wizard = true; + continue; + } + if (card->controller()->game->inPlay->cards[j]->hasType("Warrior") && !found_warrior){ + intValue += 1; + found_warrior = true; + continue; + } + } + } + else if (s.find("cardcounttype") != string::npos)//Count Total Creatures of specific type + { + intValue = 0; + bool different_names = (s.find("diffcardcounttype")!=string::npos)?true:false; + string type = (s.find("diffcardcounttype")!=string::npos)?s.substr(17):s.substr(13); + vector list; + for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j) + { + if (card->controller()->game->inPlay->cards[j]->hasType(type)){ + if(!different_names) + intValue += 1; + else{ + bool name_found = false; + for(unsigned int i = 0; i < list.size() && !name_found; i++){ + if(list[i] == card->controller()->game->inPlay->cards[j]->name) + name_found = true; + } + if(!name_found){ + list.push_back(card->controller()->game->inPlay->cards[j]->name); + intValue += 1; + } + } + } + } + } + else if (s == "cursedscrollresult")//Return 1 if the cursed scroll has to give damage (calculated randomly basing on the number of unique cards in the player hand)... + { + intValue = 0; + if(card->controller()->game->hand->nb_cards){ + list unique_cards; + for (int j = 0; j < card->controller()->game->hand->nb_cards; j++){ + bool found = false; + for (unsigned int k = 0; k < unique_cards.size() && !found; k++){ + list::iterator it; + for (it = unique_cards.begin(); it != unique_cards.end(); it++){ + if(card->controller()->game->hand->cards[j]->name == *it) + found = true; + } + } + if(!found) + unique_cards.push_back(card->controller()->game->hand->cards[j]->name); + } + if(!(std::rand() % unique_cards.size())) + intValue = 1; + unique_cards.clear(); + } + } + else if (s == "mypos" || s == "bushidopoints")//hand,exile,grave & library only (library zpos is inverted so the recent one is always the top) -- bushido point + { + intValue = (s == "mypos")?card->zpos:card->bushidoPoints; + } + else if ((s == "revealedp" || s == "revealedt" || s == "revealedmana") && card->revealedLast) + { + if (s == "revealedp" || s == "revealedt") + intValue = (s == "revealedp")?card->revealedLast->power:card->revealedLast->toughness; + else + intValue = card->revealedLast->getManaCost()->getConvertedCost(); + } + else if(!intValue)//found nothing, try parsing a atoi + { + intValue = atoi(s.c_str()); + } + if (intValue > 0)//dont divide by 0 the rest are valid. + { + if (halfup) + { + if (intValue % 2 == 1) + intValue++; + intValue = intValue / 2; + } + if (halfdown) + intValue = intValue / 2; + + if (thirdup) + { + if (intValue % 3 > 0) + intValue = (intValue / 3) + 1; + else + intValue = intValue / 3; + } + if (thirddown) + intValue = intValue / 3; + } + if (twice) + intValue = intValue * 2; + if (thrice) + intValue = intValue * 3; + if (intValue < 0) + { + //we remove "-" at the start and are parsing for real values. + //if we ended up with a value less than 0, then we return just 0 + intValue = 0; + } + + intValue *= multiplier; +} + +int WParsedInt::countDevotionTo(MTGCardInstance * card, MTGGameZone * zone, int color1, int color2) +{ + int counthybrid = 0; + TargetChooserFactory dtf(card->getObserver()); + TargetChooser * dtc = dtf.createTargetChooser("*",NULL); + if (dtc->targetsZone(zone, card)) + { + counthybrid += zone->countDevotion(dtc, color1, color2); + } + SAFE_DELETE(dtc); + return card->controller()->devotionOffset + counthybrid; // Increase total devotion with an offset (e.g. Altar of the Pantheon) +} + +int WParsedInt::countCardNameinZone(string name, MTGGameZone * zone) +{ + int count = 0; + for( int i= 0; i < zone->nb_cards; i ++) + if(zone->cards[i]->name == name) + count += 1; + return count; +} + +int WParsedInt::countCardsInPlaybyColor(int color, GameObserver * observer) +{ + int count = 0; + for (int i = 0; i < 2; i++) + { + for( int j= 0; j < observer->players[i]->inPlay()->nb_cards; j++) + if(observer->players[i]->inPlay()->cards[j]->hasColor(color)) + count += 1; + } + return count; +} + +int WParsedInt::mostCommonColor(int color, MTGCardInstance * card) +{ + int maxColor = 0; + vector colors; + + for(int i = 1; i < 6; i++) + colors.push_back( countCardsInPlaybyColor(i, card->getObserver()) ); + + for(int j = 0; j < 5; j++) + if ( colors[j] > maxColor ) + maxColor = colors[j]; + + if (countCardsInPlaybyColor(color, card->getObserver()) >= maxColor && maxColor > 0) + return 1; + + return 0; +} + +int WParsedInt::countCardTypeinZone(string type, MTGGameZone * zone) +{ + int count = 0; + for( int i= 0; i < zone->nb_cards; i ++) + if(zone->cards[i]->hasType(type)) + count += 1; + return count; +} + +int WParsedInt::cardHasTypeinZone(const char * type, MTGGameZone * zone) +{ + int count = 0; + if(zone->hasType(type)) + count = 1; + return count; +} + +int WParsedInt::countCanTargetby(string type, MTGCardInstance * card, Player * player) +{ + int count = 0; + for (int j = player->game->battlefield->nb_cards - 1; j >= 0; --j) + { + if (player->game->battlefield->cards[j]->hasType(type) && !player->game->battlefield->cards[j]->protectedAgainst(card)) + count += 1; + } + return count; +} + +int WParsedInt::countManaProducedby(int color, MTGCardInstance * target, Player * player) +{ + int count = 0; + MTGGameZone * zone = player->game->battlefield; + for(int k = 0; k < zone->nb_cards; k++) + { + MTGCardInstance * card = zone->cards[k]; + if(card->isLand() && (card != target) && card->hasSubtype("forest") && color == 1) + count++; + if(card->isLand() && (card != target) && card->hasSubtype("island") && color == 2) + count++; + if(card->isLand() && (card != target) && card->hasSubtype("mountain") && color == 3) + count++; + if(card->isLand() && (card != target) && card->hasSubtype("swamp") && color == 4) + count++; + if(card->isLand() && (card != target) && card->hasSubtype("plains") && color == 5) + count++; + if(card->isLand() && (card != target) && card->cardsAbilities.size()) + { + for(unsigned int j = 0; j < card->cardsAbilities.size(); j++) + { + if(dynamic_cast (card->cardsAbilities[j]) && dynamic_cast (card->cardsAbilities[j])->output->hasColor(color) ) + count++; + } + } + } + return count; +} + +WParsedInt::WParsedInt(int value) +{ + intValue = value; +} + +WParsedInt::WParsedInt(string s, Spell * spell, MTGCardInstance * card) +{ + init(s, spell, card); +} + +WParsedInt::WParsedInt(string s, MTGCardInstance * card) +{ + init(s, NULL, card); +} + +int WParsedInt::getValue() +{ + return intValue; +} + +string WParsedInt::getStringValue() +{ + stringstream sval; + sval << intValue; + return sval.str(); +} + +WParsedPT::WParsedPT(int p, int t) +{ + power.intValue = p; + toughness.intValue = t; + ok = true; +} + +WParsedPT::WParsedPT(string s, Spell * spell, MTGCardInstance * card) +{ + size_t found = s.find("/"); + ok = false; + if (found != string::npos) + { + size_t end = s.find(" ", found); + if (end == string::npos) end = s.size(); + size_t start = s.find_last_of(" ", found); + if (start == string::npos) + start = 0; + else + start++; + power = WParsedInt(s.substr(start, found - start), spell, card); + toughness = WParsedInt(s.substr(found + 1, end - found - 1), spell, card); + + ok = true; + } +} \ No newline at end of file diff --git a/projects/mtg/template.vcxproj b/projects/mtg/template.vcxproj index 4dd72c676..53311d870 100644 --- a/projects/mtg/template.vcxproj +++ b/projects/mtg/template.vcxproj @@ -452,6 +452,7 @@ + @@ -574,6 +575,7 @@ + diff --git a/projects/mtg/template.vcxproj.filters b/projects/mtg/template.vcxproj.filters index 263d9ab9e..8123329bd 100644 --- a/projects/mtg/template.vcxproj.filters +++ b/projects/mtg/template.vcxproj.filters @@ -340,6 +340,9 @@ src + + src + @@ -699,6 +702,9 @@ inc + + inc + diff --git a/projects/mtg/wagic.pri b/projects/mtg/wagic.pri index 3157ebf84..2bdfed2c6 100644 --- a/projects/mtg/wagic.pri +++ b/projects/mtg/wagic.pri @@ -158,6 +158,7 @@ SOURCES += \ src/WFilter.cpp\ src/WFont.cpp\ src/WGui.cpp\ + src/WParsedInt.cpp\ src/WResourceManager.cpp \ src/AIPlayerBakaB.cpp \ src/TestSuiteAI.cpp @@ -265,6 +266,7 @@ HEADERS += \ include/GuiPhaseBar.h\ include/ReplacementEffects.h\ include/WGui.h\ + include/WParsedInt.h\ include/DeckStats.h\ include/GuiPlay.h\ include/Rules.h\