Files
wagic/projects/mtg/src/WParsedInt.cpp

1237 lines
51 KiB
C++

#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.
vector<string>mathFound = 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
{
vector<string>plusSplit = parseBetween(s, "", "plus", true);
if (plusSplit.size())
{
WParsedInt numPar(plusSplit[1], NULL, card);
intValue = numPar.getValue();
}
vector<string>plusFound = parseBetween(s, "plus", "plusend", true);
if (plusFound.size())
{
WParsedInt numPar(plusFound[1], NULL, card);
intValue += numPar.getValue();
}
vector<string>minusSplit = parseBetween(s, "", "minus", true);
if (minusSplit.size())
{
WParsedInt numPar(minusSplit[1], NULL, card);
intValue = numPar.getValue();
}
vector<string>minusFound = 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.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<string> 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;
vector<string>counterName = 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("pwr:") != string::npos || s.find("toughness:") != string::npos || s.find("ths:") != string::npos)
{
bool powerCheck = false;
bool toughnessCheck = false;
bool costCheck = false;
intValue = 0;
vector<string>convertedType = parseBetween(s,"convertedcost:",":");
if(convertedType.size())
costCheck = true;
else
{
size_t pos = s.find("pwr:");
if(pos != string::npos)
s.replace(pos, 4, "power:");
convertedType = parseBetween(s,"power:",":");
if(convertedType.size()){
powerCheck = true;
}
else
{
size_t pos = s.find("ths:");
if(pos != string::npos)
s.replace(pos, 4, "toughness:");
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 == "isflipped" || s == "iscopied") // Return 1 if card has been flipped -- Return 1 if card has copied another card
{
intValue = (s == "isflipped")?card->isFlipped:card->isACopier;
}
else if (s == "evictmc" || s == "hasevict")
{
if(card->imprintedCards.size() > 0) intValue = (s == "evictmc")?card->imprintedCards.back()->getManaCost()->getConvertedCost():card->imprintedCards.size();
}
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 == "excessdamage") // Return the amount of exceeded damage of a target
{
if(target->exceededDamage < 0)
intValue = target->exceededDamage;
int checkagain = 0;
if(target->hasSubtype(Subtypes::TYPE_AURA) || target->hasSubtype(Subtypes::TYPE_EQUIPMENT)){
if(target->target){
if(target->target->exceededDamage < 0)
checkagain = target->target->exceededDamage;
}
}
if(checkagain < intValue)
intValue = checkagain;
if(card && card->exceededDamage < intValue)
intValue = card->exceededDamage;
if(intValue < 0)
intValue = abs(intValue);
}
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.find("hasability") != string::npos) //Return 1 if card has the specified ability
{
intValue = 0;
for(size_t i = 0; i < Constants::NB_BASIC_ABILITIES; i++)
if(Constants::MTGBasicAbilities[i] == s.substr(10))
intValue = card->basicAbilities[i];
}
else if (s.find("hascnt") != string::npos) //Return the amount of specific counters on card
{
intValue = 0;
if (card->counters){
Counters * counters = card->counters;
for(size_t i = 0; i < counters->counters.size(); ++i){
Counter * counter = counters->counters[i];
if(counter->name == "" && (s.substr(6) == "11" || s.substr(6) == "-1-1")){
if((counter->power == 1 && counter->toughness == 1 && s.substr(6) == "11") || (counter->power == -1 && counter->toughness == -1 && s.substr(6) == "-1-1")){
intValue = counter->nb;
break;
}
} else if(counter->name == s.substr(6)){
intValue = counter->nb;
break;
}
}
}
}
else if (s.find("genrand") != string::npos) //Return a random value between 0 and a specific number (minus 1);
{
intValue = std::rand() % atoi(s.substr(7).c_str());
}
else if (s == "manacost") //Return the converted 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 == "snowdiffmana") //Return 1 if the difference between snowpool and converted manacost is more than 0
{
int snowpool = target->controller()->snowManaG + target->controller()->snowManaU + target->controller()->snowManaR + target->controller()->snowManaB + target->controller()->snowManaW + target->controller()->snowManaC;
int manacost = (target->currentZone == target->controller()->game->stack)?(target->myconvertedcost + target->castX):target->myconvertedcost;//X is 0 except if it's on the stack
intValue = (snowpool >= manacost)?1:0;
}
else if (s == "mysnowpoolcount" || s == "opponentsnowpoolcount") // snowpoolcount is just to count the number of snow mana produced ...
{
intValue = (s == "mysnowpoolcount")?(target->controller()->snowManaG + target->controller()->snowManaU + target->controller()->snowManaR + target->controller()->snowManaB + target->controller()->snowManaW + target->controller()->snowManaC):(target->controller()->opponent()->snowManaG + target->controller()->opponent()->snowManaU + target->controller()->opponent()->snowManaR + target->controller()->opponent()->snowManaB + target->controller()->opponent()->snowManaW + target->controller()->opponent()->snowManaC);
}
else if (s == "mysnowgreenpoolcount" || s == "opponentsnowgreenpoolcount")
{
intValue = (s == "mysnowgreenpoolcount")?target->controller()->snowManaG:target->controller()->opponent()->snowManaG;
}
else if (s == "mysnowredpoolcount" || s == "opponentsnowredpoolcount")
{
intValue = (s == "mysnowredpoolcount")?target->controller()->snowManaR:target->controller()->opponent()->snowManaR;
}
else if (s == "mysnowbluepoolcount" || s == "opponentsnowbluepoolcount")
{
intValue = (s == "mysnowbluepoolcount")?target->controller()->snowManaU:target->controller()->opponent()->snowManaU;
}
else if (s == "mysnowwhitepoolcount" || s == "opponentsnowwhitepoolcount")
{
intValue = (s == "mysnowwhitepoolcount")?target->controller()->snowManaW:target->controller()->opponent()->snowManaW;
}
else if (s == "mysnowblackpoolcount" || s == "opponentsnowblackpoolcount")
{
intValue = (s == "mysnowblackpoolcount")?target->controller()->snowManaB:target->controller()->opponent()->snowManaB;
}
else if (s == "mysnowcolorlesspoolcount" || s == "opponentsnowcolorlesspoolcount")
{
intValue = (s == "mysnowcolorlesspoolcount")?target->controller()->snowManaC:target->controller()->opponent()->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 cards 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<string> 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.find("sametypecreatures") != string::npos)//Count the greatest number creatures that share same subtype
{
intValue = 0;
bool opponent = (s.find("oppsametypecreatures")!=string::npos)?true:false;
vector<int> list;
vector<string> values = MTGAllCards::getCreatureValuesById();
for (size_t i = 0; i < values.size(); ++i){
list.push_back(0);
if(opponent){
for (int j = card->controller()->opponent()->game->inPlay->nb_cards - 1; j >= 0; --j){
if (card->controller()->opponent()->game->inPlay->cards[j]->hasType(values[i])){
list[i]++;
}
}
} else {
for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j){
if (card->controller()->game->inPlay->cards[j]->hasType(values[i])){
list[i]++;
}
}
}
if (list[i] > intValue)
intValue = list[i];
}
}
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<string> 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<string>::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 (s == "scryedcards")//returns how many card have been scryed from current card
{
intValue = card->scryedCards;
}
else if (s.find("findfirsttype") != string::npos)//find the index of first card with specified type in target player library
{
intValue = 0;
bool opponent = (s.find("oppofindfirsttype")!=string::npos)?true:false;
string type = (s.find("oppofindfirsttype")!=string::npos)?s.substr(17):s.substr(13);
bool negate = (type.find("non")!=string::npos)?true:false;
type = negate?type.substr(3):type;
Player* p = card->controller();
if (opponent)
p = card->controller()->opponent();
for (int j = p->game->library->nb_cards - 1; j >= 0; --j){
if (type == "permanent" && !negate && !p->game->library->cards[j]->hasType(Subtypes::TYPE_INSTANT) && !p->game->library->cards[j]->hasType(Subtypes::TYPE_SORCERY)){
intValue = p->game->library->nb_cards - j;
break;
}
else if (type == "permanent" && negate && (p->game->library->cards[j]->hasType(Subtypes::TYPE_INSTANT) || p->game->library->cards[j]->hasType(Subtypes::TYPE_SORCERY))){
intValue = p->game->library->nb_cards - j;
break;
}
else if (type != "permanent" && !negate && p->game->library->cards[j]->hasType(type)){
intValue = p->game->library->nb_cards - j;
break;
}
else if (type != "permanent" && negate && !p->game->library->cards[j]->hasType(type)){
intValue = p->game->library->nb_cards - j;
break;
}
}
}
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<int> 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<AManaProducer*> (card->cardsAbilities[j]) && dynamic_cast<AManaProducer*> (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;
}
}