//Specific life cost SpecificLifeCost * SpecificLifeCost::clone() const { SpecificLifeCost * ec = NEW SpecificLifeCost(*this); if (tc) ec->tc = tc->clone(); return ec; }
ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstance * c) { ManaCost * manaCost; GameObserver* g = c?c->getObserver():NULL; if (_manaCost) { manaCost = _manaCost; } else { manaCost = NEW ManaCost(); } manaCost->xColor = -1; int state = 0; size_t start = 0; size_t end = 0; while (!s.empty() && state != -1) { switch (state) { case 0: start = s.find_first_of("{"); if(s.find_first_of("{") != string::npos && start > 0) { string value = s.substr(start -1,end); if(value == "n{")//"restrictio n{m orbid} would read the n{m as {m} millcost return manaCost; } if (start == string::npos) { return manaCost; } else { state = 1; } break; case 1: end = s.find_first_of("}"); if (end == string::npos) { state = -1; } else { string value = s.substr(start + 1, end - 1 - start); if (value == "u") { manaCost->add(Constants::MTG_COLOR_BLUE, 1); } else if (value == "b") { manaCost->add(Constants::MTG_COLOR_BLACK, 1); } else if (value == "w") { manaCost->add(Constants::MTG_COLOR_WHITE, 1); } else if (value == "g") { manaCost->add(Constants::MTG_COLOR_GREEN, 1); } else if (value == "r") { manaCost->add(Constants::MTG_COLOR_RED, 1); } else { //Parse target for extraCosts TargetChooserFactory tcf(g); TargetChooser * tc = NULL; size_t target_start = value.find("("); size_t target_end = value.find(")"); if (target_start != string::npos && target_end != string::npos) { string target = value.substr(target_start + 1, target_end - 1 - target_start); tc = tcf.createTargetChooser(target, c); } //switch on the first letter. If two costs share their first letter, add an "if" within the switch std::transform(value.begin(), value.end(), value.begin(), ::tolower); switch (value[0]) { case 'x': if(value == "x") { manaCost->x(); } else { vector<string>colorSplit = parseBetween(value,"x:"," ",false); if(colorSplit.size()) { int color = -1; const string ColorStrings[] = { Constants::kManaColorless, Constants::kManaGreen, Constants::kManaBlue, Constants::kManaRed, Constants::kManaBlack, Constants::kManaWhite }; for (unsigned int i = 0; i < sizeof(ColorStrings)/sizeof(ColorStrings[0]); ++i) { if (s.find(ColorStrings[i]) != string::npos) { color = i; } } manaCost->specificX(color); } } break; case 'v': if (value.find("value:") != string::npos) { vector<string> splitParsedVar = parseBetween(value, "value:", " ", false); WParsedInt* res = NEW WParsedInt(splitParsedVar[1], NULL, c); manaCost->add(Constants::MTG_COLOR_ARTIFACT, res->getValue()); SAFE_DELETE(res); } break; case 't': //Tap if (value == "t") { manaCost->addExtraCost(NEW TapCost); } else { manaCost->addExtraCost(NEW TapTargetCost(tc)); } break; case 's': if (value.find("s2l") != string::npos) { //Send To Library Cost (move from anywhere to Library) manaCost->addExtraCost(NEW ToLibraryCost(tc)); } else if (value.find("s2g") != string::npos) { //Send to Graveyard Cost (move from anywhere to Graveyard) manaCost->addExtraCost(NEW ToGraveCost(tc)); } else { //Sacrifice manaCost->addExtraCost(NEW SacrificeCost(tc)); } break; case 'e': //Exile manaCost->addExtraCost(NEW ExileTargetCost(tc)); break; case 'h': //bounce (move to Hand) manaCost->addExtraCost(NEW BounceTargetCost(tc)); break; case 'l': if (value == "l2e") { //Mill to exile yourself as a cost (Library 2 Exile) manaCost->addExtraCost(NEW MillExileCost(tc)); } else if (value == "l") { //Life cost manaCost->addExtraCost(NEW LifeCost(tc)); } else { //Specific Life cost vector<string>valSplit = parseBetween(value,"l:"," ",false); if (valSplit.size()) { WParsedInt* lifetopay = NEW WParsedInt(valSplit[1], NULL, c); manaCost->addExtraCost(NEW SpecificLifeCost(tc,lifetopay->getValue())); SAFE_DELETE(lifetopay); } } break; case 'd': //DiscardRandom cost if (value.find("delve") != string::npos) { if(!tc) tc = tcf.createTargetChooser("*|mygraveyard", c); manaCost->addExtraCost(NEW Delve(tc)); } else if (value == "d") { manaCost->addExtraCost(NEW DiscardRandomCost(tc)); } else { manaCost->addExtraCost(NEW DiscardCost(tc)); } break; case 'm': //Mill yourself as a cost manaCost->addExtraCost(NEW MillCost(tc)); break; case 'n': //return unblocked attacker cost { TargetChooserFactory tcf(g); tc = tcf.createTargetChooser("creature|myBattlefield", c); manaCost->addExtraCost(NEW Ninja(tc)); break; } case 'k': //kill offering { TargetChooserFactory tcf(g); if (value == "kgoblin") { tc = tcf.createTargetChooser("creature[goblin]|myBattlefield", c); } else if (value == "kfox") { tc = tcf.createTargetChooser("creature[fox]|myBattlefield", c); } else if (value == "kmoonfolk") { tc = tcf.createTargetChooser("creature[moonfolk]|myBattlefield", c); } else if (value == "krat") { tc = tcf.createTargetChooser("creature[rat]|myBattlefield", c); } else if (value == "ksnake") { tc = tcf.createTargetChooser("creature[snake]|myBattlefield", c); } //TODO iterate subtypes of creatures manaCost->addExtraCost(NEW Offering(tc)); break; } case 'p' : { SAFE_DELETE(tc); size_t start = value.find("("); size_t end = value.rfind(")"); string manaType = value.substr(start + 1, end - start - 1); manaCost->addExtraCost(NEW LifeorManaCost(NULL,manaType)); break; } case 'i' : { SAFE_DELETE(tc); manaCost->add(0,1); manaCost->addExtraCost(NEW SnowCost); break; } case 'q': if(value == "q") { manaCost->addExtraCost(NEW UnTapCost); } else { manaCost->addExtraCost(NEW UnTapTargetCost(tc)); } break; case 'c': //Counters or cycle { if (value.find("convoke") != string::npos) { if (!tc) tc = tcf.createTargetChooser("creature|mybattlefield", c); manaCost->addExtraCost(NEW Convoke(tc)); } else if(value == "chosencolor") { if(c) manaCost->add(c->chooseacolor, 1); } else if(value == "cycle") { manaCost->addExtraCost(NEW CycleCost(tc)); } else if(value.find("(") != string::npos) { size_t counter_start = value.find("("); size_t counter_end = value.find(")", counter_start); AbilityFactory abf(g); string counterString = value.substr(counter_start + 1, counter_end - counter_start - 1); Counter * counter = abf.parseCounter(counterString, c); size_t separator = value.find(",", counter_start); size_t separator2 = string::npos; if (separator != string::npos) { separator2 = value.find(",", counter_end + 1); } SAFE_DELETE(tc); size_t target_start = string::npos; if (separator2 != string::npos) { target_start = value.find(",", counter_end + 1); } size_t target_end = value.length(); if (target_start != string::npos && target_end != string::npos) { string target = value.substr(target_start + 1, target_end - 1 - target_start); tc = tcf.createTargetChooser(target, c); } manaCost->addExtraCost(NEW CounterCost(counter, tc)); break; } else if(value == "c") { manaCost->add(Constants::MTG_COLOR_WASTE, 1); break; } break; } default: //uncolored cost and hybrid costs and special cost { if(value == "unattach") { manaCost->addExtraCost(NEW UnattachCost(c)); break; } int intvalue = atoi(value.c_str()); int colors[2]; int values[2]; if (intvalue < 10 && value.size() > 1) { for (int i = 0; i < 2; i++) { char c = value[i]; if (c >= '0' && c <= '9') { colors[i] = Constants::MTG_COLOR_ARTIFACT; values[i] = c - '0'; } else { for (int j = 0; j < Constants::NB_Colors; j++) { if (c == Constants::MTGColorChars[j]) { colors[i] = j; values[i] = 1; } } } } if (values[0] > 0 || values[1] > 0) manaCost->addHybrid(colors[0], values[0], colors[1], values[1]); } else { manaCost->add(Constants::MTG_COLOR_ARTIFACT, intvalue); } break; } } } s = s.substr(end + 1); state = 0; } break; default: break; } } return manaCost; }