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\