From 4f54e30e0ea97a77afac729132941b509bb8783d Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Thu, 5 Nov 2015 07:16:49 +0800 Subject: [PATCH 1/6] Libraryeater and Canplayfromexile extend canplayfromgraveyard with canplayfromexile libraryeater for undead alchemist --- projects/mtg/bin/Res/sets/primitives/mtg.txt | 26 ++++++++++++++-- .../bin/Res/sets/primitives/unsupported.txt | 31 +++---------------- projects/mtg/include/MTGAbility.h | 2 +- projects/mtg/include/MTGDefinitions.h | 3 +- projects/mtg/include/MTGRules.h | 2 +- projects/mtg/src/Damage.cpp | 28 +++++++++++++++++ projects/mtg/src/MTGDefinitions.cpp | 3 +- projects/mtg/src/MTGRules.cpp | 8 ++--- 8 files changed, 67 insertions(+), 36 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index 2cd71814f..257c81f05 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -99087,11 +99087,10 @@ text=Syphon Soul deals 2 damage to each other player. You gain life equal to the mana={2}{B} type=Sorcery [/card] -#workaround szadek. [card] name=Szadek, Lord of Secrets +alias=89092 abilities=flying -auto=@combatdamaged(player) from(this):deplete:thatmuch opponent && life:thatmuch opponent && counter(1/1,thatmuch) text=Flying -- If Szadek, Lord of Secrets would deal combat damage to a player, instead put that many +1/+1 counters on Szadek and that player puts that many cards from the top of his or her library into his or her graveyard. mana={3}{U}{U}{B}{B} type=Legendary Creature @@ -100972,6 +100971,18 @@ mana={3}{p(U)} type=Sorcery [/card] [card] +name=Thada Adel, Acquisitor +abilities=islandwalk +auto=@combatdamagefoeof(player) from(this):name(exile artifact) notatarget(artifact|opponentlibrary) moveto(myexile) and!( transforms((,newability[canplayfromexile],newability[phaseactionmulti[endofturn once] moveto(ownerexile) all(this|exile)])) ueot)! +auto=@combatdamageof(player) from(this):name(exile artifact) notatarget(artifact|mylibrary) moveto(myexile) and!( transforms((,newability[canplayfromexile],newability[phaseactionmulti[endofturn once] moveto(ownerexile) all(this|exile)])) ueot)! +text=Islandwalk -- Whenever Thada Adel, Acquisitor deals combat damage to a player, search that player's library for an artifact card and exile it. Then that player shuffles his or her library. Until end of turn, you may play that card. +mana={1}{U}{U} +type=Legendary Creature +subtype=Merfolk Rogue +power=2 +toughness=2 +[/card] +[card] name=Thalakos Deceiver abilities=shadow auto=@combat(notblocked) source(this):may moveTo(myBattlefield) target(creature|opponentBattlefield) && sacrifice all(this) @@ -106105,6 +106116,17 @@ type=Enchantment subtype=Aura [/card] [card] +name=Undead Alchemist +auto=lord(zombie|mybattlefield) libraryeater +auto=@movedTo(creature|opponentgraveyard) from(opponentlibrary):all(trigger[to]) moveto(exile) and!(token(Zombie,Creature Zombie,2/2,black) controller)! +text=If a Zombie you control would deal combat damage to a player, instead that player puts that many cards from the top of his or her library into his or her graveyard. -- Whenever a creature card is put into an opponent's graveyard from his or her library, exile that card and put a 2/2 black Zombie creature token onto the battlefield. +mana={3}{U} +type=Creature +subtype=Zombie +power=4 +toughness=2 +[/card] +[card] name=Undead Executioner auto=@movedto(this|graveyard) from(battlefield):may target(creature) -2/-2 ueot text=When Undead Executioner dies, you may have target creature get -2/-2 until end of turn. diff --git a/projects/mtg/bin/Res/sets/primitives/unsupported.txt b/projects/mtg/bin/Res/sets/primitives/unsupported.txt index 77ec526d5..6338488fa 100644 --- a/projects/mtg/bin/Res/sets/primitives/unsupported.txt +++ b/projects/mtg/bin/Res/sets/primitives/unsupported.txt @@ -13490,6 +13490,7 @@ subtype=Elemental power=3 toughness=2 [/card] +#seems possible [card] name=Roiling Horror text=Roiling Horror's power and toughness are each equal to your life total minus the life total of an opponent with the most life. -- Suspend X - {X}{B}{B}{B}. X can't be 0. (Rather than cast this card from your hand, you may pay {X}{B}{B}{B} and exile it with X time counters on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost. It has haste.) -- Whenever a time counter is removed from Roiling Horror while it's exiled, target player loses 1 life and you gain 1 life. @@ -13939,6 +13940,7 @@ subtype=Giant Warrior power=4 toughness=5 [/card] +#modded ingest [card] name=Scalpelexis text=Flying (This creature can't be blocked except by creatures with flying or reach.) -- Whenever Scalpelexis deals combat damage to a player, that player exiles the top four cards of his or her library. If two or more of those cards have the same name, repeat this process. @@ -14093,6 +14095,7 @@ text=Look at the top X cards of target opponent's library. Exile one of those ca mana={X}{U}{B} type=Sorcery [/card] +#moverandom? [card] name=Search for Survivors text=Reorder your graveyard at random. An opponent chooses a card at random in your graveyard. If it's a creature card, put it onto the battlefield. Otherwise, exile it. @@ -14480,6 +14483,7 @@ mana={3}{U} type=Instant subtype=Arcane [/card] +#phaseactionmulti? [card] name=Shifty Doppelganger text={3}{U}, Exile Shifty Doppelganger: You may put a creature card from your hand onto the battlefield. If you do, that creature gains haste until end of turn. At the beginning of the next end step, sacrifice that creature. If you do, return Shifty Doppelganger to the battlefield. @@ -14944,6 +14948,7 @@ type=Enchantment subtype=Aura text=Enchant creature Enchanted creature gets +1/+1 and has "Whenever this creature deals damage to an opponent, you may draw a card." Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.) [/card] +#manaflashback rule [card] name=Snapcaster Mage abilities=flash @@ -16224,12 +16229,6 @@ type=Sorcery text=Put a 1/1 colorless Expansion-Symbol creature token into play for each different expansion symbol among permanents you control. [/card] [card] -name=Syncopate -text=Counter target spell unless its controller pays {X}. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. -mana={X}{U} -type=Instant -[/card] -[card] name=Synod Artificer text={X}, {T}: Tap X target noncreature artifacts. -- {X}, {T}: Untap X target noncreature artifacts. mana={2}{U} @@ -16490,15 +16489,6 @@ type=Planeswalker subtype=Tezzeret [/card] [card] -name=Thada Adel, Acquisitor -text=Islandwalk -- Whenever Thada Adel, Acquisitor deals combat damage to a player, search that player's library for an artifact card and exile it. Then that player shuffles his or her library. Until end of turn, you may play that card. -mana={1}{U}{U} -type=Legendary Creature -subtype=Merfolk Rogue -power=2 -toughness=2 -[/card] -[card] name=Thalakos Dreamsower text=Shadow (This creature can block or be blocked by only creatures with shadow.) -- You may choose not to untap Thalakos Dreamsower during your untap step. -- Whenever Thalakos Dreamsower deals damage to an opponent, tap target creature. That creature doesn't untap during its controller's untap step for as long as Thalakos Dreamsower remains tapped. mana={2}{U} @@ -17284,17 +17274,6 @@ mana={2}{U} type=Sorcery [/card] [card] -name=Undead Alchemist -auto=@combatdamaged(player) from(zombie|mybattlefield):deplete:thatmuch opponent && life:thatmuch opponent -auto=@movedTo(creature|opponentgraveyard) from(opponentlibrary):token(Zombie,Creature Zombie,2/2,black) -text=If a Zombie you control would deal combat damage to a player, instead that player puts that many cards from the top of his or her library into his or her graveyard. -- Whenever a creature card is put into an opponent's graveyard from his or her library, exile that card and put a 2/2 black Zombie creature token onto the battlefield. -mana={3}{U} -type=Creature -subtype=Zombie -power=4 -toughness=2 -[/card] -[card] name=Undercity Informer text={1}, Sacrifice a creature: Target player reveals cards from the top of his or her library until he or she reveals a land card, then puts those cards into his or her graveyard. mana={2}{B} diff --git a/projects/mtg/include/MTGAbility.h b/projects/mtg/include/MTGAbility.h index 876bb97e2..af8cbbeee 100644 --- a/projects/mtg/include/MTGAbility.h +++ b/projects/mtg/include/MTGAbility.h @@ -213,7 +213,7 @@ public: COUNTERS = 30, PUT_INTO_PLAY_WITH_KICKER = 31, STANDARD_FIZZLER = 32, - CASTINGRAVEYARD_COST = 33, + CASTINGRAVEEXILE_COST = 33, }; }; diff --git a/projects/mtg/include/MTGDefinitions.h b/projects/mtg/include/MTGDefinitions.h index a3df629bc..c201679e4 100644 --- a/projects/mtg/include/MTGDefinitions.h +++ b/projects/mtg/include/MTGDefinitions.h @@ -237,7 +237,8 @@ class Constants PAYZERO = 119, TRINISPHERE = 120, CANPLAYFROMEXILE = 121, - NB_BASIC_ABILITIES = 122, + LIBRARYEATER = 122, + NB_BASIC_ABILITIES = 123, RARITY_S = 'S', //Special Rarity diff --git a/projects/mtg/include/MTGRules.h b/projects/mtg/include/MTGRules.h index 13be1c5b3..f99bdb7d4 100644 --- a/projects/mtg/include/MTGRules.h +++ b/projects/mtg/include/MTGRules.h @@ -184,7 +184,7 @@ public: MTGPlayFromGraveyardRule(GameObserver* observer, int _id); const string getMenuText() { - return "Cast Card From Graveyard"; + return "Cast Card From This Zone"; } virtual MTGPlayFromGraveyardRule * clone() const; }; diff --git a/projects/mtg/src/Damage.cpp b/projects/mtg/src/Damage.cpp index 3f6a329c9..3b677ff18 100644 --- a/projects/mtg/src/Damage.cpp +++ b/projects/mtg/src/Damage.cpp @@ -126,7 +126,35 @@ int Damage::resolve() } _target->doDamageTest = 1; } + if (target->type_as_damageable == Damageable::DAMAGEABLE_PLAYER) + { + if(source->has(Constants::LIBRARYEATER) && typeOfDamage == 1) + { + for (int j = damage; j > 0; j--) + { + if(((Player*)target)->game->library->nb_cards) + ((Player*)target)->game->putInZone(((Player*)target)->game->library->cards[((Player*)target)->game->library->nb_cards - 1], ((Player*)target)->game->library, ((Player*)target)->game->graveyard); + } + damage = 0; + } + if(source->alias == 89092 && typeOfDamage == 1)//Szadek Lord of Secrets + { + for (int j = damage; j > 0; j--) + { + if(((Player*)target)->game->library->nb_cards) + ((Player*)target)->game->putInZone(((Player*)target)->game->library->cards[((Player*)target)->game->library->nb_cards - 1], ((Player*)target)->game->library, ((Player*)target)->game->graveyard); + source->counters->addCounter(1, 1); + } + damage = 0; + } + if (!damage) + { + state = RESOLVED_NOK; + delete (e); + return 0; + } + } int a = damage; if (target->type_as_damageable == Damageable::DAMAGEABLE_MTGCARDINSTANCE && (source->has(Constants::WITHER) || source->has( diff --git a/projects/mtg/src/MTGDefinitions.cpp b/projects/mtg/src/MTGDefinitions.cpp index dbeaca32d..a1645eb0a 100644 --- a/projects/mtg/src/MTGDefinitions.cpp +++ b/projects/mtg/src/MTGDefinitions.cpp @@ -150,7 +150,8 @@ const char* Constants::MTGBasicAbilities[] = { "oppgcreatureexiler", "payzero", "trinisphere", - "canplayfromexile" + "canplayfromexile", + "libraryeater" }; map Constants::MTGBasicAbilitiesMap; diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index f1b14a941..bb62985fd 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -1132,7 +1132,7 @@ MTGMorphCostRule * MTGMorphCostRule::clone() const MTGPlayFromGraveyardRule::MTGPlayFromGraveyardRule(GameObserver* observer, int _id) : MTGAlternativeCostRule(observer, _id) { - aType = MTGAbility::CASTINGRAVEYARD_COST; + aType = MTGAbility::CASTINGRAVEEXILE_COST; } int MTGPlayFromGraveyardRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) @@ -1140,9 +1140,9 @@ int MTGPlayFromGraveyardRule::isReactingToClick(MTGCardInstance * card, ManaCost Player * player = game->currentlyActing(); ManaCost * cost = card->getManaCost(); - if (!player->game->graveyard->hasCard(card)) + if (!player->game->graveyard->hasCard(card) && !player->game->exile->hasCard(card)) return 0; - if (!card->has(Constants::CANPLAYFROMGRAVEYARD)) + if ((!card->has(Constants::CANPLAYFROMGRAVEYARD) && player->game->graveyard->hasCard(card))||(!card->has(Constants::CANPLAYFROMEXILE) && player->game->exile->hasCard(card))) return 0; return MTGAlternativeCostRule::isReactingToClick(card, mana, cost); @@ -1155,7 +1155,7 @@ int MTGPlayFromGraveyardRule::reactToClick(MTGCardInstance * card) ManaCost * cost = card->getManaCost(); - card->paymenttype = MTGAbility::CASTINGRAVEYARD_COST; + card->paymenttype = MTGAbility::CASTINGRAVEEXILE_COST; return MTGAlternativeCostRule::reactToClick(card, cost, ManaCost::MANA_PAID_WITH_OTHERCOST); } From 536a0e429a887afbdbb22b0d8e63fdafedfb152d Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Thu, 5 Nov 2015 07:17:58 +0800 Subject: [PATCH 2/6] AI considers playing from exile and graveyard --- projects/mtg/src/AIPlayerBaka.cpp | 304 ++++++++++++++++++++++++++++++ projects/mtg/src/GameObserver.cpp | 2 +- projects/mtg/src/MTGAbility.cpp | 3 - 3 files changed, 305 insertions(+), 4 deletions(-) diff --git a/projects/mtg/src/AIPlayerBaka.cpp b/projects/mtg/src/AIPlayerBaka.cpp index d75616eaf..4c54c565d 100644 --- a/projects/mtg/src/AIPlayerBaka.cpp +++ b/projects/mtg/src/AIPlayerBaka.cpp @@ -627,6 +627,14 @@ int OrderedAIAction::getEfficiency() { efficiency += 65; } + else if (dynamic_cast(a)) + { + efficiency += 55; + } + else if (dynamic_cast(a)) + { + efficiency += 45; + } SAFE_DELETE(transAbility); return efficiency; } @@ -1726,6 +1734,302 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty cd.setType(type); card = NULL; gotPayments = vector(); + //canplayfromgraveyard + while ((card = cd.nextmatch(game->graveyard, card))&& card->has(Constants::CANPLAYFROMGRAVEYARD)) + { + if (!CanHandleCost(card->getManaCost(),card)) + continue; + + if (card->hasType(Subtypes::TYPE_LAND)) + { + if (game->playRestrictions->canPutIntoZone(card, game->inPlay) == PlayRestriction::CANT_PLAY) + continue; + } + else + { + if (game->playRestrictions->canPutIntoZone(card, game->stack) == PlayRestriction::CANT_PLAY) + continue; + } + + if (card->hasType(Subtypes::TYPE_LEGENDARY) && game->inPlay->findByName(card->name)) + continue; + + if (card->hasType(Subtypes::TYPE_PLANESWALKER) && card->types.size() > 0 && game->inPlay->hasTypeSpecificInt(Subtypes::TYPE_PLANESWALKER,card->types[1])) + continue; + + if(hints && hints->HintSaysItsForCombo(observer,card)) + { + if(hints->canWeCombo(observer,card,this)) + { + AbilityFactory af(observer); + int canPlay = af.parseCastRestrictions(card,card->controller(),card->getRestrictions()); + if(!canPlay) + continue; + nextCardToPlay = card; + gotPayments.clear(); + if((!pMana->canAfford(nextCardToPlay->getManaCost()) || nextCardToPlay->getManaCost()->getKicker())) + gotPayments = canPayMana(nextCardToPlay,nextCardToPlay->getManaCost()); + return activateCombo(); + } + else + { + nextCardToPlay = NULL; + continue; + } + } + int currentCost = card->getManaCost()->getConvertedCost(); + int hasX = card->getManaCost()->hasX(); + gotPayments.clear(); + if((!pMana->canAfford(card->getManaCost()) || card->getManaCost()->getKicker())) + gotPayments = canPayMana(card,card->getManaCost()); + //for preformence reason we only look for specific mana if the payment couldn't be made with pmana. + if ((currentCost > maxCost || hasX) && (gotPayments.size() || pMana->canAfford(card->getManaCost()))) + { + TargetChooserFactory tcf(observer); + TargetChooser * tc = tcf.createTargetChooser(card); + int shouldPlayPercentage = 0; + if (tc) + { + int hasTarget = chooseTarget(tc,NULL,NULL,true); + if( + (tc->maxtargets > hasTarget && tc->maxtargets > 1 && !tc->targetMin && tc->maxtargets != TargetChooser::UNLITMITED_TARGETS) ||//target=<3>creature + (tc->maxtargets == TargetChooser::UNLITMITED_TARGETS && hasTarget < 1)//target=creatures + ) + hasTarget = 0; + if (!hasTarget)//single target covered here. + { + SAFE_DELETE(tc); + continue; + } + shouldPlayPercentage = 90; + if(tc->targetMin && hasTarget < tc->maxtargets) + shouldPlayPercentage = 0; + if(tc->maxtargets > 1 && tc->maxtargets != TargetChooser::UNLITMITED_TARGETS && hasTarget <= tc->maxtargets) + { + int maxA = hasTarget-tc->maxtargets; + shouldPlayPercentage += (10*maxA);//reduce the chances of playing multitarget if we are not above max targets. + } + if(tc->maxtargets == TargetChooser::UNLITMITED_TARGETS) + { + shouldPlayPercentage = 40 + (10*hasTarget); + int totalCost = pMana->getConvertedCost()-currentCost; + int totalTargets = hasTarget+hasTarget; + if(hasX && totalCost <= totalTargets)// {x} spell with unlimited targeting tend to divide damage, we want atleast 1 damage per target before casting. + { + shouldPlayPercentage = 0; + } + } + SAFE_DELETE(tc); + } + else + { + int shouldPlay = effectBadOrGood(card); + if (shouldPlay == BAKA_EFFECT_GOOD) + { + shouldPlayPercentage = 90; + } + else if (BAKA_EFFECT_DONTKNOW == shouldPlay) + { + //previously shouldPlayPercentage = 80;, I found this a little to high + //for cards which AI had no idea how to use. + shouldPlayPercentage = 60; + } + else if (card->isLand()) + { + shouldPlayPercentage = 90; + } + else + { + // shouldPlay == baka_effect_bad giving it a 1 for odd ball lottery chance. + shouldPlayPercentage = 1; + } + + } + //Reduce the chances of playing a spell with X cost if available mana is low + if (hasX) + { + int xDiff = pMana->getConvertedCost() - currentCost; + if (xDiff < 0) + xDiff = 0; + shouldPlayPercentage = shouldPlayPercentage - static_cast ((shouldPlayPercentage * 1.9f) / (1 + xDiff)); + } + if(card->getManaCost() && card->getManaCost()->getKicker() && card->getManaCost()->getKicker()->isMulti) + { + shouldPlayPercentage = 10* size_t(gotPayments.size())/int(1+(card->getManaCost()->getConvertedCost()+card->getManaCost()->getKicker()->getConvertedCost())); + if(shouldPlayPercentage <= 10) + shouldPlayPercentage = shouldPlayPercentage/3; + } + DebugTrace("Should I play " << (card ? card->name : "Nothing" ) << "?" << endl + <<"shouldPlayPercentage = "<< shouldPlayPercentage); + if(card->getRestrictions().size()) + { + AbilityFactory af(observer); + int canPlay = af.parseCastRestrictions(card,card->controller(),card->getRestrictions()); + if(!canPlay) + continue; + } + int randomChance = randomGenerator.random(); + int chance = randomChance % 100; + if (chance > shouldPlayPercentage) + continue; + if(shouldPlayPercentage <= 10) + { + DebugTrace("shouldPlayPercentage was less than 10 this was a lottery roll on RNG"); + } + nextCardToPlay = card; + maxCost = currentCost; + if (hasX) + maxCost = pMana->getConvertedCost(); + } + } + //canplayfromexile + while ((card = cd.nextmatch(game->exile, card))&& card->has(Constants::CANPLAYFROMEXILE)) + { + if (!CanHandleCost(card->getManaCost(),card)) + continue; + + if (card->hasType(Subtypes::TYPE_LAND)) + { + if (game->playRestrictions->canPutIntoZone(card, game->inPlay) == PlayRestriction::CANT_PLAY) + continue; + } + else + { + if (game->playRestrictions->canPutIntoZone(card, game->stack) == PlayRestriction::CANT_PLAY) + continue; + } + + if (card->hasType(Subtypes::TYPE_LEGENDARY) && game->inPlay->findByName(card->name)) + continue; + + if (card->hasType(Subtypes::TYPE_PLANESWALKER) && card->types.size() > 0 && game->inPlay->hasTypeSpecificInt(Subtypes::TYPE_PLANESWALKER,card->types[1])) + continue; + + if(hints && hints->HintSaysItsForCombo(observer,card)) + { + if(hints->canWeCombo(observer,card,this)) + { + AbilityFactory af(observer); + int canPlay = af.parseCastRestrictions(card,card->controller(),card->getRestrictions()); + if(!canPlay) + continue; + nextCardToPlay = card; + gotPayments.clear(); + if((!pMana->canAfford(nextCardToPlay->getManaCost()) || nextCardToPlay->getManaCost()->getKicker())) + gotPayments = canPayMana(nextCardToPlay,nextCardToPlay->getManaCost()); + return activateCombo(); + } + else + { + nextCardToPlay = NULL; + continue; + } + } + int currentCost = card->getManaCost()->getConvertedCost(); + int hasX = card->getManaCost()->hasX(); + gotPayments.clear(); + if((!pMana->canAfford(card->getManaCost()) || card->getManaCost()->getKicker())) + gotPayments = canPayMana(card,card->getManaCost()); + //for preformence reason we only look for specific mana if the payment couldn't be made with pmana. + if ((currentCost > maxCost || hasX) && (gotPayments.size() || pMana->canAfford(card->getManaCost()))) + { + TargetChooserFactory tcf(observer); + TargetChooser * tc = tcf.createTargetChooser(card); + int shouldPlayPercentage = 0; + if (tc) + { + int hasTarget = chooseTarget(tc,NULL,NULL,true); + if( + (tc->maxtargets > hasTarget && tc->maxtargets > 1 && !tc->targetMin && tc->maxtargets != TargetChooser::UNLITMITED_TARGETS) ||//target=<3>creature + (tc->maxtargets == TargetChooser::UNLITMITED_TARGETS && hasTarget < 1)//target=creatures + ) + hasTarget = 0; + if (!hasTarget)//single target covered here. + { + SAFE_DELETE(tc); + continue; + } + shouldPlayPercentage = 90; + if(tc->targetMin && hasTarget < tc->maxtargets) + shouldPlayPercentage = 0; + if(tc->maxtargets > 1 && tc->maxtargets != TargetChooser::UNLITMITED_TARGETS && hasTarget <= tc->maxtargets) + { + int maxA = hasTarget-tc->maxtargets; + shouldPlayPercentage += (10*maxA);//reduce the chances of playing multitarget if we are not above max targets. + } + if(tc->maxtargets == TargetChooser::UNLITMITED_TARGETS) + { + shouldPlayPercentage = 40 + (10*hasTarget); + int totalCost = pMana->getConvertedCost()-currentCost; + int totalTargets = hasTarget+hasTarget; + if(hasX && totalCost <= totalTargets)// {x} spell with unlimited targeting tend to divide damage, we want atleast 1 damage per target before casting. + { + shouldPlayPercentage = 0; + } + } + SAFE_DELETE(tc); + } + else + { + int shouldPlay = effectBadOrGood(card); + if (shouldPlay == BAKA_EFFECT_GOOD) + { + shouldPlayPercentage = 90; + } + else if (BAKA_EFFECT_DONTKNOW == shouldPlay) + { + //previously shouldPlayPercentage = 80;, I found this a little to high + //for cards which AI had no idea how to use. + shouldPlayPercentage = 60; + } + else if (card->isLand()) + { + shouldPlayPercentage = 90; + } + else + { + // shouldPlay == baka_effect_bad giving it a 1 for odd ball lottery chance. + shouldPlayPercentage = 1; + } + + } + //Reduce the chances of playing a spell with X cost if available mana is low + if (hasX) + { + int xDiff = pMana->getConvertedCost() - currentCost; + if (xDiff < 0) + xDiff = 0; + shouldPlayPercentage = shouldPlayPercentage - static_cast ((shouldPlayPercentage * 1.9f) / (1 + xDiff)); + } + if(card->getManaCost() && card->getManaCost()->getKicker() && card->getManaCost()->getKicker()->isMulti) + { + shouldPlayPercentage = 10* size_t(gotPayments.size())/int(1+(card->getManaCost()->getConvertedCost()+card->getManaCost()->getKicker()->getConvertedCost())); + if(shouldPlayPercentage <= 10) + shouldPlayPercentage = shouldPlayPercentage/3; + } + DebugTrace("Should I play " << (card ? card->name : "Nothing" ) << "?" << endl + <<"shouldPlayPercentage = "<< shouldPlayPercentage); + if(card->getRestrictions().size()) + { + AbilityFactory af(observer); + int canPlay = af.parseCastRestrictions(card,card->controller(),card->getRestrictions()); + if(!canPlay) + continue; + } + int randomChance = randomGenerator.random(); + int chance = randomChance % 100; + if (chance > shouldPlayPercentage) + continue; + if(shouldPlayPercentage <= 10) + { + DebugTrace("shouldPlayPercentage was less than 10 this was a lottery roll on RNG"); + } + nextCardToPlay = card; + maxCost = currentCost; + if (hasX) + maxCost = pMana->getConvertedCost(); + } + } while ((card = cd.nextmatch(game->hand, card))) { if (!CanHandleCost(card->getManaCost(),card)) diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index 03bf15211..2731b2429 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -1156,7 +1156,7 @@ void GameObserver::Affinity() card->getManaCost()->remove(color,1); } } - //SAFE_DELETE(original); + SAFE_DELETE(original); }//end } } diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 44c40898d..6b157fb32 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -3689,9 +3689,6 @@ int AbilityFactory::abilityEfficiency(MTGAbility * a, Player * p, int mode, Targ badAbilities[(int)Constants::WEAK] = true; badAbilities[(int)Constants::NOLIFEGAIN] = true; badAbilities[(int)Constants::NOLIFEGAINOPPONENT] = true; - badAbilities[(int)Constants::CANTLOSE] = false; - badAbilities[(int)Constants::CANTLIFELOSE] = false; - badAbilities[(int)Constants::CANTMILLLOSE] = false; if (AInstantBasicAbilityModifierUntilEOT * abi = dynamic_cast(a)) { From 1c8852a7a255eb7667a83e287f62b563e6be01de Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Thu, 5 Nov 2015 23:25:39 +0800 Subject: [PATCH 3/6] Manacost Changes todo: kicker (other possible additional costs?) and change rule keyword to payzerorule... --- projects/mtg/bin/Res/sets/primitives/mtg.txt | 2 +- projects/mtg/include/MTGCardInstance.h | 19 +---- projects/mtg/include/MTGRules.h | 11 ++- projects/mtg/src/AIPlayerBaka.cpp | 2 +- projects/mtg/src/MTGAbility.cpp | 2 +- projects/mtg/src/MTGCardInstance.cpp | 19 +++++ projects/mtg/src/MTGDefinitions.cpp | 2 +- projects/mtg/src/MTGRules.cpp | 83 +++++++++++++------- 8 files changed, 86 insertions(+), 54 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index 257c81f05..16080c3b0 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -41603,7 +41603,7 @@ toughness=3 [card] name=Gravecrawler abilities=cantblock -autograveyard=aslongas(zombie|myBattlefield) transforms((,newability[CanPlayFromGraveyard])) +autograveyard=aslongas(zombie|myBattlefield) CanPlayFromGraveyard text=Gravecrawler can't block. -- You may cast Gravecrawler from your graveyard as long as you control a Zombie. mana={B} type=Creature diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index 9eb7a64da..8c1882e91 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -254,24 +254,7 @@ public: bool isTargetter(); int cardistargetter; int myconvertedcost; - ManaCost * computeNewCost(MTGCardInstance * card,ManaCost * oldCost) - { - if(card->isLand()) - return oldCost; - - if(!card) - return NULL; - //i don't know why this method doesn't affect cards in hand, but is working on other zones....// - //pay zero costs// - //kicker???...// - //morph cost todo// - //trinisphere must be here below// - if(card->has(Constants::TRINISPHERE)) - for(int jj = oldCost->getConvertedCost(); jj < 3; jj++) - oldCost->add(Constants::MTG_COLOR_ARTIFACT, 1); - - return oldCost; - }; + ManaCost * computeNewCost(MTGCardInstance * card,ManaCost * oldCost); void eventattacked(); void eventattackedAlone(); diff --git a/projects/mtg/include/MTGRules.h b/projects/mtg/include/MTGRules.h index f99bdb7d4..f617f556a 100644 --- a/projects/mtg/include/MTGRules.h +++ b/projects/mtg/include/MTGRules.h @@ -175,18 +175,21 @@ public: virtual MTGMorphCostRule * clone() const; }; -class MTGPlayFromGraveyardRule: public MTGAlternativeCostRule +class MTGPayZeroRule: public MTGAlternativeCostRule { public: int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL); int reactToClick(MTGCardInstance * card); + string CustomName; virtual ostream& toString(ostream& out) const; - MTGPlayFromGraveyardRule(GameObserver* observer, int _id); + MTGPayZeroRule(GameObserver* observer, int _id); const string getMenuText() { - return "Cast Card From This Zone"; + if(CustomName.size()) + return CustomName.c_str(); + return "Pay Zero To Cast"; } - virtual MTGPlayFromGraveyardRule * clone() const; + virtual MTGPayZeroRule * clone() const; }; diff --git a/projects/mtg/src/AIPlayerBaka.cpp b/projects/mtg/src/AIPlayerBaka.cpp index 4c54c565d..e0d269e69 100644 --- a/projects/mtg/src/AIPlayerBaka.cpp +++ b/projects/mtg/src/AIPlayerBaka.cpp @@ -631,7 +631,7 @@ int OrderedAIAction::getEfficiency() { efficiency += 55; } - else if (dynamic_cast(a)) + else if (dynamic_cast(a)) { efficiency += 45; } diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 6b157fb32..10e9d30cc 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -1159,7 +1159,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG found = s.find("playfromgraveyardrule"); if(found != string::npos) { - observer->addObserver(NEW MTGPlayFromGraveyardRule(observer, -1)); + observer->addObserver(NEW MTGPayZeroRule(observer, -1)); return NULL; } //this rule handles attacking ability during attacker phase diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index a70ef93b6..a56247912 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -918,6 +918,25 @@ JQuadPtr MTGCardInstance::getIcon() return WResourceManager::Instance()->RetrieveCard(this, CACHE_THUMB); } +ManaCost * MTGCardInstance::computeNewCost(MTGCardInstance * card,ManaCost * oldCost) +{ + if(card->isLand()) + return oldCost; + + if(!card) + return oldCost; + //use forcedalive// + //pay zero costs// + //kicker???...// + //morph cost todo// + //trinisphere must be here below// + if(card->has(Constants::TRINISPHERE)) + for(int jj = oldCost->getConvertedCost(); jj < 3; jj++) + oldCost->add(Constants::MTG_COLOR_ARTIFACT, 1); + + return oldCost; +} + MTGCardInstance * MTGCardInstance::getNextPartner() { MTGInPlay * inplay = controller()->game->inPlay; diff --git a/projects/mtg/src/MTGDefinitions.cpp b/projects/mtg/src/MTGDefinitions.cpp index a1645eb0a..7728bd1d2 100644 --- a/projects/mtg/src/MTGDefinitions.cpp +++ b/projects/mtg/src/MTGDefinitions.cpp @@ -148,7 +148,7 @@ const char* Constants::MTGBasicAbilities[] = { "protectionfromcoloredspells", "mygcreatureexiler", "oppgcreatureexiler", - "payzero", + "zerocast", "trinisphere", "canplayfromexile", "libraryeater" diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index bb62985fd..03b6dc136 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -284,8 +284,10 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost *) { int cardsinhand = game->players[0]->game->hand->nb_cards; Player * player = game->currentlyActing(); - if (!player->game->hand->hasCard(card)) - return 0; + if (!player->game->hand->hasCard(card) && !player->game->graveyard->hasCard(card) && !player->game->exile->hasCard(card)) + return 0; + if ((player->game->graveyard->hasCard(card) && !card->has(Constants::CANPLAYFROMGRAVEYARD)) || (player->game->exile->hasCard(card) && !card->has(Constants::CANPLAYFROMEXILE))) + return 0; if ((game->turn < 1) && (cardsinhand != 0) && (card->basicAbilities[(int)Constants::LEYLINE]) && game->getCurrentGamePhase() == MTG_PHASE_FIRSTMAIN && game->players[0]->game->graveyard->nb_cards == 0 @@ -295,7 +297,7 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost *) if (card->basicAbilities[(int)Constants::LEYLINE]) { - MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp); + MTGCardInstance * copy = player->game->putInZone(card, card->currentZone, player->game->temp); Spell * spell = NEW Spell(game, copy); spell->resolve(); delete spell; @@ -412,7 +414,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card) delete previousManaPool; if (card->isLand()) { - MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp); + MTGCardInstance * copy = player->game->putInZone(card, card->currentZone, player->game->temp); Spell * spell = NEW Spell(game, 0,copy,NULL,NULL, payResult); spell->resolve(); delete spellCost; @@ -421,7 +423,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card) else { Spell * spell = NULL; - MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack); + MTGCardInstance * copy = player->game->putInZone(card, card->currentZone, player->game->stack); if (game->targetChooser) { spell = game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, spellCost, payResult, 0); @@ -475,8 +477,10 @@ int MTGKickerRule::isReactingToClick(MTGCardInstance * card, ManaCost *) if(OptionKicker::KICKER_ALWAYS == options[Options::KICKERPAYMENT].number) return 0; Player * player = game->currentlyActing(); - if(!player->game->hand->hasCard(card)) - return 0; + if (!player->game->hand->hasCard(card) && !player->game->graveyard->hasCard(card) && !player->game->exile->hasCard(card)) + return 0; + if ((player->game->graveyard->hasCard(card) && !card->has(Constants::CANPLAYFROMGRAVEYARD)) || (player->game->exile->hasCard(card) && !card->has(Constants::CANPLAYFROMEXILE))) + return 0; ManaCost * kicker = card->getManaCost()->getKicker(); if(!kicker) { @@ -484,7 +488,7 @@ int MTGKickerRule::isReactingToClick(MTGCardInstance * card, ManaCost *) return 0; } ManaCost * playerMana = player->getManaPool(); - ManaCost * withKickerCost= NEW ManaCost(card->getManaCost()); + ManaCost * withKickerCost= NEW ManaCost(card->model->data->getManaCost()); withKickerCost->add(withKickerCost->getKicker()); if(!playerMana->canAfford(withKickerCost)) { @@ -503,7 +507,7 @@ int MTGKickerRule::reactToClick(MTGCardInstance * card) return 0; Player * player = game->currentlyActing(); - ManaCost * withKickerCost= NEW ManaCost(card->getManaCost());//using pointers here alters the real cost of the card. + ManaCost * withKickerCost= NEW ManaCost(card->model->data->getManaCost());//using pointers here alters the real cost of the card. if (card->getManaCost()->getKicker()->isMulti) { while(player->getManaPool()->canAfford(withKickerCost)) @@ -545,7 +549,7 @@ int MTGKickerRule::reactToClick(MTGCardInstance * card) delete previousManaPool; if (card->isLand()) { - MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp); + MTGCardInstance * copy = player->game->putInZone(card, card->currentZone, player->game->temp); Spell * spell = NEW Spell(game, 0,copy,NULL,NULL, ManaCost::MANA_PAID_WITH_KICKER); spell->resolve(); delete spellCost; @@ -554,7 +558,7 @@ int MTGKickerRule::reactToClick(MTGCardInstance * card) else { Spell * spell = NULL; - MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack); + MTGCardInstance * copy = player->game->putInZone(card, card->currentZone, player->game->stack); if (game->targetChooser) { spell = game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, spellCost, ManaCost::MANA_PAID_WITH_KICKER, 0); @@ -616,7 +620,9 @@ PermanentAbility(observer, _id) int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) { ManaCost * alternateCost = card->getManaCost()->getAlternative(); - if (!game->currentlyActing()->game->hand->hasCard(card)) + if (!game->currentlyActing()->game->hand->hasCard(card) && !game->currentlyActing()->game->graveyard->hasCard(card) && !game->currentlyActing()->game->exile->hasCard(card)) + return 0; + if ((game->currentlyActing()->game->graveyard->hasCard(card) && !card->has(Constants::CANPLAYFROMGRAVEYARD)) || (game->currentlyActing()->game->exile->hasCard(card) && !card->has(Constants::CANPLAYFROMEXILE))) return 0; return isReactingToClick( card, mana, alternateCost ); } @@ -630,7 +636,12 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * if(!allowedToAltCast(card,player)) return 0; - if(card->model->data->getManaCost()->getAlternative() && card->model->data->getManaCost()->getAlternative()->alternativeName.size()) + + if(card->has(Constants::CANPLAYFROMGRAVEYARD)) + alternativeName = "Alternate Cast Card From Graveyard"; + else if(card->has(Constants::CANPLAYFROMEXILE)) + alternativeName = "Alternate Cast Card From Exile"; + else if(card->model->data->getManaCost()->getAlternative() && card->model->data->getManaCost()->getAlternative()->alternativeName.size()) alternativeName = card->model->data->getManaCost()->getAlternative()->alternativeName; if (card->isLand()) @@ -763,8 +774,10 @@ MTGAlternativeCostRule(observer, _id) int MTGBuyBackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) { Player * player = game->currentlyActing(); - if (!player->game->hand->hasCard(card)) - return 0; + if (!player->game->hand->hasCard(card) && !player->game->graveyard->hasCard(card) && !player->game->exile->hasCard(card)) + return 0; + if ((player->game->graveyard->hasCard(card) && !card->has(Constants::CANPLAYFROMGRAVEYARD)) || (player->game->exile->hasCard(card) && !card->has(Constants::CANPLAYFROMEXILE))) + return 0; if(!allowedToCast(card,player)) return 0; return MTGAlternativeCostRule::isReactingToClick( card, mana, card->getManaCost()->getBuyback() ); @@ -1129,46 +1142,60 @@ MTGMorphCostRule * MTGMorphCostRule::clone() const //------------------------------------------------------------------------- //------------------------------------------------------------------------- -MTGPlayFromGraveyardRule::MTGPlayFromGraveyardRule(GameObserver* observer, int _id) : +MTGPayZeroRule::MTGPayZeroRule(GameObserver* observer, int _id) : MTGAlternativeCostRule(observer, _id) { aType = MTGAbility::CASTINGRAVEEXILE_COST; } -int MTGPlayFromGraveyardRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) +int MTGPayZeroRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) { Player * player = game->currentlyActing(); - ManaCost * cost = card->getManaCost(); + ManaCost * cost = NEW ManaCost(ManaCost::parseManaCost("{0}",NULL,NULL)); + if(card->getIncreasedManaCost()->getConvertedCost()) + cost->add(card->getIncreasedManaCost()); + if(card->getReducedManaCost()->getConvertedCost()) + cost->remove(card->getReducedManaCost()); - if (!player->game->graveyard->hasCard(card) && !player->game->exile->hasCard(card)) + if(card->isLand()) + return 0; + if(!card->has(Constants::PAYZERO)) + return 0; + if (!player->game->graveyard->hasCard(card) && !player->game->exile->hasCard(card) && !player->game->hand->hasCard(card)) return 0; if ((!card->has(Constants::CANPLAYFROMGRAVEYARD) && player->game->graveyard->hasCard(card))||(!card->has(Constants::CANPLAYFROMEXILE) && player->game->exile->hasCard(card))) return 0; - + if(card->has(Constants::CANPLAYFROMGRAVEYARD)) + CustomName = "Pay Zero To Cast From Graveyard"; + else if(card->has(Constants::CANPLAYFROMEXILE)) + CustomName = "Pay Zero To Cast From Exile"; + else + CustomName = "Pay Zero To Cast"; + return MTGAlternativeCostRule::isReactingToClick(card, mana, cost); } -int MTGPlayFromGraveyardRule::reactToClick(MTGCardInstance * card) +int MTGPayZeroRule::reactToClick(MTGCardInstance * card) { if (!isReactingToClick(card)) return 0; - ManaCost * cost = card->getManaCost(); + ManaCost * cost = NEW ManaCost(ManaCost::parseManaCost("{0}",NULL,NULL)); card->paymenttype = MTGAbility::CASTINGRAVEEXILE_COST; - return MTGAlternativeCostRule::reactToClick(card, cost, ManaCost::MANA_PAID_WITH_OTHERCOST); + return MTGAlternativeCostRule::reactToClick(card, cost, ManaCost::MANA_PAID); } -ostream& MTGPlayFromGraveyardRule::toString(ostream& out) const +ostream& MTGPayZeroRule::toString(ostream& out) const { - out << "MTGPlayFromGraveyardRule ::: ("; + out << "MTGPayZeroRule ::: ("; return MTGAbility::toString(out) << ")"; } -MTGPlayFromGraveyardRule * MTGPlayFromGraveyardRule::clone() const +MTGPayZeroRule * MTGPayZeroRule::clone() const { - return NEW MTGPlayFromGraveyardRule(*this); + return NEW MTGPayZeroRule(*this); } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1718,7 +1745,7 @@ int MTGMomirRule::reactToClick(MTGCardInstance * card_to_discard, int cardId) ManaCost * cost = player->getManaPool(); player->getManaPool()->pay(cost); MTGCardInstance * card = genCreature(cardId); - player->game->putInZone(card_to_discard, player->game->hand, player->game->graveyard); + player->game->putInZone(card_to_discard, card_to_discard->currentZone, player->game->graveyard); player->game->stack->addCard(card); Spell * spell = NEW Spell(game, card); From 71390046f5aea64f667284b03dd2b997f528184a Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Fri, 6 Nov 2015 19:47:30 +0800 Subject: [PATCH 4/6] anyzone for cdaactive should handle most of them except sewer nemesis, chameleon colossus --- projects/mtg/bin/Res/sets/primitives/mtg.txt | 180 +++++++++---------- projects/mtg/src/MTGAbility.cpp | 8 +- projects/mtg/src/MTGDeck.cpp | 10 ++ 3 files changed, 106 insertions(+), 92 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index 16080c3b0..e33f7dbf8 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -2,7 +2,7 @@ #Please keep these card alphabetized, and try to have the "name=" line at the top of each card [card] name=Aeon Chronicler -auto=phandcount/phandcount cdaactive +anyzone=phandcount/phandcount cdaactive autoexile=@counterremoved(0/0,1,Time) from(sourcecard) suspended:draw:1 suspend(0)={X}{3}{U} text=Aeon Chronicler's power and toughness are each equal to the number of cards in your hand. -- Suspend X - {X}{3}{U}. X can't be 0. (Rather than cast this card from your hand, you may pay {X}{3}{U} and exile it with X time counters on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost. It has haste.) -- Whenever a time counter is removed from Aeon Chronicler while it's exiled, draw a card. @@ -878,7 +878,7 @@ type=Instant [/card] [card] name=Adamaro, First to Desire -auto=type:*:opponenthand/type:*:opponenthand cdaactive +anyzone=type:*:opponenthand/type:*:opponenthand cdaactive text=Adamaro, First to Desire's power and toughness are each equal to the number of cards in the hand of the opponent with the most cards in hand. mana={1}{R}{R} type=Legendary Creature @@ -1493,7 +1493,7 @@ subtype=Ajani [/card] [card] name=Avatar Token -auto=lifetotal/lifetotal cdaactive +anyzone=lifetotal/lifetotal cdaactive type=Creature subtype=Avatar power=* @@ -2351,7 +2351,7 @@ toughness=1 [card] name=Altar Golem abilities=trample,doesnotuntap -auto=type:creature:battlefield/type:creature:battlefield cdaactive +anyzone=type:creature:battlefield/type:creature:battlefield cdaactive auto={T(creature|myBattlefield)}{T(creature|myBattlefield)}{T(creature|myBattlefield)}{T(creature|myBattlefield)}{T(creature|myBattlefield)}:untap text=Trample -- Altar Golem's power and toughness are each equal to the number of creatures on the battlefield. -- Altar Golem doesn't untap during your untap step. -- Tap five untapped creatures you control: Untap Altar Golem. mana={7} @@ -2937,7 +2937,7 @@ toughness=3 [/card] [card] name=Ancient Ooze -auto=pancientooze/pancientooze cdaactive +anyzone=pancientooze/pancientooze cdaactive text=Ancient Ooze's power and toughness are each equal to the total converted mana cost of other creatures you control. mana={5}{G}{G} type=Creature @@ -8068,7 +8068,7 @@ toughness=2 [card] name=Battle Squadron abilities=flying -auto=type:creature:myBattlefield/type:creature:myBattlefield cdaactive +anyzone=type:creature:myBattlefield/type:creature:myBattlefield cdaactive text=Flying -- Battle Squadron's power and toughness are each equal to the number of creatures you control. mana={3}{R}{R} type=Creature @@ -8381,7 +8381,7 @@ type=Enchantment [/card] [card] name=Beast of Burden -auto=type:creature:Battlefield/type:creature:Battlefield cdaactive +anyzone=type:creature:Battlefield/type:creature:Battlefield cdaactive text=Beast of Burden's power and toughness are each equal to the number of creatures on the battlefield. mana={6} type=Artifact Creature @@ -8671,7 +8671,7 @@ toughness=2 [/card] [card] name=Benalish Commander -auto=type:soldier:mybattlefield/type:soldier:mybattlefield cdaactive +anyzone=type:soldier:mybattlefield/type:soldier:mybattlefield cdaactive autoexile=@counterremoved(0/0,1,Time) from(sourcecard) suspended:token(Soldier,Creature Soldier,1/1,white) suspend(0)={X}{W}{W} text=Benalish Commander's power and toughness are each equal to the number of Soldiers you control. -- Suspend X - {X}{W}{W}. X can't be 0. (Rather than cast this card from your hand, you may pay {X}{W}{W} and exile it with X time counters on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost. It has haste.) -- Whenever a time counter is removed from Benalish Commander while it's exiled, put a 1/1 white Soldier creature token onto the battlefield. @@ -11580,7 +11580,7 @@ toughness=2 [/card] [card] name=Boneyard Wurm -auto=type:creature:mygraveyard/type:creature:mygraveyard cdaactive +anyzone=type:creature:mygraveyard/type:creature:mygraveyard cdaactive text=Boneyard Wurm's power and toughness are each equal to the number of creature cards in your graveyard. mana={1}{G} type=Creature @@ -12926,7 +12926,7 @@ toughness=4 [card] name=Broodstar abilities=affinityartifacts,flying -auto=type:artifact:mybattlefield/type:artifact:mybattlefield cdaactive +anyzone=type:artifact:mybattlefield/type:artifact:mybattlefield cdaactive text=Affinity for artifacts (This spell costs {1} less to cast for each artifact you control.) -- Flying -- Broodstar's power and toughness are each equal to the number of artifacts you control. mana={8}{U}{U} type=Creature @@ -14098,7 +14098,7 @@ type=Sorcery [card] name=Cantivore abilities=vigilance -auto=type:enchantment:graveyard/type:enchantment:graveyard cdaactive +anyzone=type:enchantment:graveyard/type:enchantment:graveyard cdaactive text=Vigilance -- Cantivore's power and toughness are each equal to the number of enchantment cards in all graveyards. mana={1}{W}{W} type=Creature @@ -18066,7 +18066,7 @@ type=Instant [card] name=Cognivore abilities=flying -auto=type:instant:graveyard/type:instant:graveyard cdaactive +anyzone=type:instant:graveyard/type:instant:graveyard cdaactive text=Flying -- Cognivore's power and toughness are each equal to the number of instant cards in all graveyards. mana={6}{U}{U} type=Creature @@ -18086,7 +18086,7 @@ toughness=1 [/card] [card] name=Coiling Woodworm -auto=type:forest:battlefield/1 cdaactive +anyzone=type:forest:battlefield/1 cdaactive text=Coiling Woodworm's power is equal to the number of Forests on the battlefield. mana={2}{G} type=Creature @@ -20220,7 +20220,7 @@ toughness=4 [card] name=Crowd of Cinders abilities=fear -auto=type:*[black]:myBattlefield/type:*[black]:myBattlefield cdaactive +anyzone=type:*[black]:myBattlefield/type:*[black]:myBattlefield cdaactive text=Fear (This creature can't be blocked except by artifact creatures and/or black creatures.) -- Crowd of Cinders's power and toughness are each equal to the number of black permanents you control. mana={3}{B} type=Creature @@ -20455,7 +20455,7 @@ type=Enchantment [/card] [card] name=Crusader of Odric -auto=type:creature:mybattlefield/type:creature:mybattlefield cdaactive +anyzone=type:creature:mybattlefield/type:creature:mybattlefield cdaactive text=Crusader of Odric's power and toughness are each equal to the number of creatures you control. mana={2}{W} type=Creature @@ -21338,7 +21338,7 @@ subtype=Aura [/card] [card] name=Dakkon Blackblade -auto=type:land:myBattlefield/type:land:myBattlefield cdaactive +anyzone=type:land:myBattlefield/type:land:myBattlefield cdaactive text=Dakkon Blackblade's power and toughness are each equal to the number of lands you control. mana={2}{W}{U}{U}{B} type=Legendary Creature @@ -21401,7 +21401,7 @@ toughness=1 [/card] [card] name=Dakmor Sorceress -auto=type:swamp:myBattlefield/4 cdaactive +anyzone=type:swamp:myBattlefield/4 cdaactive text=Dakmor Sorceress's power is equal to the number of Swamps you control. mana={5}{B} type=Creature @@ -21917,7 +21917,7 @@ type=Artifact [card] name=Darksteel Juggernaut abilities=mustattack,indestructible -auto=type:artifact:mybattlefield/type:artifact:mybattlefield cdaactive +anyzone=type:artifact:mybattlefield/type:artifact:mybattlefield cdaactive text=Darksteel Juggernaut's power and toughness are equal to the number of artifacts you control. -- Darksteel Juggernaut is indestructible and attacks each turn if able. mana={5} type=Artifact Creature @@ -22113,7 +22113,7 @@ toughness=3 [/card] [card] name=Dauntless Dourbark -auto=pdauntless/pdauntless cdaactive +anyzone=pdauntless/pdauntless cdaactive auto=aslongas(other treefolk|myBattlefield) trample text=Dauntless Dourbark's power and toughness are each equal to the number of Forests you control plus the number of Treefolk you control. -- Dauntless Dourbark has trample as long as you control another Treefolk. mana={3}{G} @@ -22257,7 +22257,7 @@ toughness=1 [card] name=Dauthi Warlord abilities=shadow -auto=type:creature[shadow]:battlefield/1 cdaactive +anyzone=type:creature[shadow]:battlefield/1 cdaactive text=Shadow (This creature can block or be blocked by only creatures with shadow.) -- Dauthi Warlord's power is equal to the number of creatures with shadow on the battlefield. mana={1}{B} type=Creature @@ -24371,7 +24371,7 @@ text=Destroy target artifact with converted mana cost X. It can't be regenerated [/card] [card] name=Detritivore -auto=type:land[-basic]:opponentgraveyard/type:land[-basic]:opponentgraveyard cdaactive +anyzone=type:land[-basic]:opponentgraveyard/type:land[-basic]:opponentgraveyard cdaactive autoexile=@counterremoved(0/0,1,Time) from(sourcecard) suspended:destroy target(land[-basic]) suspend(0)={X}{3}{R} text=Detritivore's power and toughness are each equal to the number of nonbasic land cards in your opponents' graveyards. -- Suspend X - {X}{3}{R}. X can't be 0. (Rather than cast this card from your hand, you may pay {X}{3}{R} and exile it with X time counters on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost. It has haste.) -- Whenever a time counter is removed from Detritivore while it's exiled, destroy target nonbasic land. @@ -25844,7 +25844,7 @@ type=Artifact [card] name=Doubtless One auto=spiritlink -auto=type:cleric:battlefield/type:cleric:battlefield cdaactive +anyzone=type:cleric:battlefield/type:cleric:battlefield cdaactive text=Doubtless One's power and toughness are each equal to the number of Clerics on the battlefield. -- Whenever Doubtless One deals damage, you gain that much life. mana={3}{W} type=Creature @@ -26976,7 +26976,7 @@ toughness=5 [card] name=Drift of the Dead abilities=defender -auto=type:land[snow]:myBattlefield/type:land[snow]:myBattlefield cdaactive +anyzone=type:land[snow]:myBattlefield/type:land[snow]:myBattlefield cdaactive text=Defender (This creature can't attack.) -- Drift of the Dead's power and toughness are each equal to the number of snow lands you control. mana={3}{B} type=Creature @@ -27335,7 +27335,7 @@ toughness=1 [card] name=Drove of Elves abilities=opponentshroud -auto=type:*[green]:myBattlefield/type:*[green]:myBattlefield cdaactive +anyzone=type:*[green]:myBattlefield/type:*[green]:myBattlefield cdaactive text=Drove of Elves's power and toughness are each equal to the number of green permanents you control. -- Drove of Elves can't be the target of spells or abilities your opponents control. mana={3}{G} type=Creature @@ -27686,7 +27686,7 @@ toughness=1 [card] name=Dungrove Elder abilities=opponentshroud -auto=type:forest:mybattlefield/type:forest:mybattlefield cdaactive +anyzone=type:forest:mybattlefield/type:forest:mybattlefield cdaactive text=Hexproof (This creature can't be the target of spells or abilities your opponents control.) -- Dungrove Elder's power and toughness are each equal to the number of Forests you control. mana={2}{G} type=Creature @@ -29051,7 +29051,7 @@ type=Sorcery name=Elephant T1 type=Creature subtype=Elephant -auto=type:creature:mygraveyard/type:creature:mygraveyard cdaactive +anyzone=type:creature:mygraveyard/type:creature:mygraveyard cdaactive text=This creature's power and toughness are each equal to the number of creature cards in its controller's graveyard. power=* toughness=* @@ -30620,7 +30620,7 @@ toughness=2 [/card] [card] name=Entropic Specter -auto=type:*:opponenthand/type:*:opponenthand cdaactive +anyzone=type:*:opponenthand/type:*:opponenthand cdaactive auto=@damageof(player) from(this):ability$!name(discard) target(*|myhand) reject!$ controller auto=@damagefoeof(player) from(this):ability$!name(discard) target(*|myhand) reject!$ opponent text=Flying -- As Entropic Specter enters the battlefield, choose an opponent. -- Entropic Specter's power and toughness are each equal to the number of cards in the chosen player's hand. -- Whenever Entropic Specter deals damage to a player, that player discards a card. @@ -32256,7 +32256,7 @@ toughness=1 [card] name=Faerie Swarm abilities=flying -auto=type:*[blue]:myBattlefield/type:*[blue]:myBattlefield cdaactive +anyzone=type:*[blue]:myBattlefield/type:*[blue]:myBattlefield cdaactive text=Flying -- Faerie Swarm's power and toughness are each equal to the number of blue permanents you control. mana={3}{U} type=Creature @@ -37804,7 +37804,7 @@ type=Instant name=Geist-Honored Monk abilities=vigilance auto=token(Spirit,Creature Spirit,1/1,white,flying)*2 -auto=type:creature:mybattlefield/type:creature:mybattlefield cdaactive +anyzone=type:creature:mybattlefield/type:creature:mybattlefield cdaactive text=Vigilance -- Geist-Honored Monk's power and toughness are each equal to the number of creatures you control. -- When Geist-Honored Monk enters the battlefield, put two 1/1 white Spirit creature tokens with flying onto the battlefield. mana={3}{W}{W} type=Creature @@ -44933,7 +44933,7 @@ subtype=Arcane [card] name=Heedless One abilities=trample -auto=type:elf:battlefield/type:elf:battlefield cdaactive +anyzone=type:elf:battlefield/type:elf:battlefield cdaactive text=Trample -- Heedless One's power and toughness are each equal to the number of Elves on the battlefield. mana={3}{G} type=Creature @@ -50066,7 +50066,7 @@ toughness=4 [/card] [card] name=Jagged-Scar Archers -auto=type:elf:myBattlefield/type:elf:myBattlefield cdaactive +anyzone=type:elf:myBattlefield/type:elf:myBattlefield cdaactive auto={T}:target(creature[flying]) dynamicability text=Jagged-Scar Archers's power and toughness are each equal to the number of Elves you control. -- {T}: Jagged-Scar Archers deals damage equal to its power to target creature with flying. mana={1}{G}{G} @@ -51346,7 +51346,7 @@ abilities=defender [/card] [card] name=Kagemaro, First to Suffer -auto=type:*:myhand/type:*:myhand cdaactive +anyzone=type:*:myhand/type:*:myhand cdaactive auto={B}{S}:-type:*:myhand/-type:*:myhand all(creature) text=Kagemaro, First to Suffer's power and toughness are each equal to the number of cards in your hand. -- {B}, Sacrifice Kagemaro: All creatures get -X/-X until end of turn, where X is the number of cards in your hand. mana={3}{B}{B} @@ -51417,7 +51417,7 @@ toughness=3 [/card] [card] name=Kalonian Twingrove -auto=type:forest:mybattlefield/type:forest:mybattlefield cdaactive +anyzone=type:forest:mybattlefield/type:forest:mybattlefield cdaactive auto=token(-383290) text=Kalonian Twingrove's power and toughness are each equal to the number of Forests you control. -- When Kalonian Twingrove enters the battlefield, put a green Treefolk Warrior creature token onto the battlefield with "this creature's power and toughness are each equal to the number of forests you control." mana={5}{G} @@ -51428,7 +51428,7 @@ toughness=* [/card] [card] name=Treefolk Warrior -auto=type:forest:mybattlefield/type:forest:mybattlefield cdaactive +anyzone=type:forest:mybattlefield/type:forest:mybattlefield cdaactive text=This creature's power and toughness are each equal to the number of forests you control. color=green type=Creature @@ -52469,7 +52469,7 @@ toughness=1 [/card] [card] name=Keldon Warlord -auto=type:creature[-wall]:myBattlefield/type:creature[-wall]:myBattlefield cdaactive +anyzone=type:creature[-wall]:myBattlefield/type:creature[-wall]:myBattlefield cdaactive text=Keldon Warlord's power and toughness are each equal to the number of non-Wall creatures you control. mana={2}{R}{R} type=Creature @@ -53129,7 +53129,7 @@ toughness=2 [card] name=Kithkin Rabble abilities=vigilance -auto=type:*[white]:myBattlefield/type:*[white]:myBattlefield cdaactive +anyzone=type:*[white]:myBattlefield/type:*[white]:myBattlefield cdaactive text=Vigilance -- Kithkin Rabble's power and toughness are each equal to the number of white permanents you control. mana={3}{W} type=Creature @@ -53253,7 +53253,7 @@ toughness=1 [/card] [card] name=Kiyomaro, First to Stand -auto=type:*:myhand/type:*:myhand cdaactive +anyzone=type:*:myhand/type:*:myhand cdaactive auto=aslongas(*|myhand) vigilance >3 auto=@damaged(creature,player) from(this) restriction{type(*|myhand)~morethan~6}:if type(*|myhand)~morethan~6 then life:7 controller text=Kiyomaro, First to Stand's power and toughness are each equal to the number of cards in your hand. -- As long as you have four or more cards in hand, Kiyomaro has vigilance. -- Whenever Kiyomaro deals damage, if you have seven or more cards in hand, you gain 7 life. @@ -53756,7 +53756,7 @@ toughness=1 [card] name=Kolaghan Forerunners abilities=trample -auto=type:creature:mybattlefield/3 cdaactive +anyzone=type:creature:mybattlefield/3 cdaactive other={R}{2} name(Dash) auto=if paid(alternative) then transforms((,newability[haste],newability[phaseaction[endofturn sourceinplay] moveto(ownerhand) all(this)])) forever text=Trample -- Kolaghan Forerunners's power is equal to the number of creatures you control. -- Dash {2}{R} (You may cast this spell for its dash cost. If you do, it gains haste, and it's returned from the battlefield to its owner's hand at the beginning of the next end step.) @@ -53990,7 +53990,7 @@ toughness=1 [card] name=Korlash Heir to Blackblade auto={discard(korlash heir to blackblade|myhand)}:moveto(mybattlefield) and!(tap)! target(swamp|mylibrary) -auto=type:swamp:mybattlefield/type:swamp:mybattlefield cdaactive +anyzone=type:swamp:mybattlefield/type:swamp:mybattlefield cdaactive auto={1}{B}:regenerate text=Korlash, Heir to Blackblade's power and toughness are each equal to the number of Swamps you control. -- {1}{B}: Regenerate Korlash. -- Grandeur - Discard another card named Korlash, Heir to Blackblade: Search your library for up to two Swamp cards, put them onto the battlefield tapped, then shuffle your library. mana={2}{B}{B} @@ -54444,7 +54444,7 @@ subtype=Aura [card] name=Krovikan Mist abilities=flying -auto=type:illusion:battlefield/type:illusion:battlefield cdaactive +anyzone=type:illusion:battlefield/type:illusion:battlefield cdaactive text=Flying -- Krovikan Mist's power and toughness are each equal to the number of Illusions on the battlefield. mana={1}{U} type=Creature @@ -56072,7 +56072,7 @@ toughness=5 [/card] [card] name=Lhurgoyf -auto=type:creature:graveyard/plusonetype:creature:graveyard cdaactive +anyzone=type:creature:graveyard/plusonetype:creature:graveyard cdaactive text=Lhurgoyf's power is equal to the number of creature cards in all graveyards and its toughness is equal to that number plus 1. mana={2}{G}{G} type=Creature @@ -57452,7 +57452,7 @@ toughness=2 [/card] [card] name=Lord of Extinction -auto=type:*:graveyard/type:*:graveyard cdaactive +anyzone=type:*:graveyard/type:*:graveyard cdaactive text=Lord of Extinction's power and toughness are each equal to the number of cards in all graveyards. mana={3}{B}{G} type=Creature @@ -58817,7 +58817,7 @@ toughness=6 [card] name=Magnivore abilities=haste -auto=type:sorcery:graveyard/type:sorcery:graveyard cdaactive +anyzone=type:sorcery:graveyard/type:sorcery:graveyard cdaactive text=Haste (This creature can attack the turn it comes under your control.) -- Magnivore's power and toughness are each equal to the number of sorcery cards in all graveyards. mana={2}{R}{R} type=Creature @@ -59639,7 +59639,7 @@ toughness=3 [/card] [card] name=Maraxus of Keld -auto=type:*[-tapped&-enchantment;-tapped&-planeswalker]/type:*[-tapped&-enchantment;-tapped&-planeswalker] cdaactive +anyzone=type:*[-tapped&-enchantment;-tapped&-planeswalker]/type:*[-tapped&-enchantment;-tapped&-planeswalker] cdaactive text=Maraxus of Keld's power and toughness are each equal to the number of untapped artifacts, creatures, and lands you control. mana={4}{R}{R} type=Legendary Creature @@ -60025,7 +60025,7 @@ toughness=4 [/card] [card] name=Maro -auto=type:*:myhand/type:*:myhand cdaactive +anyzone=type:*:myhand/type:*:myhand cdaactive text=Maro's power and toughness are each equal to the number of cards in your hand. mana={2}{G}{G} type=Creature @@ -60558,7 +60558,7 @@ toughness=2 [card] name=Master of Etherium auto=lord(other creature[artifact]|mybattlefield) 1/1 -auto=type:artifact:mybattlefield/type:artifact:mybattlefield cdaactive +anyzone=type:artifact:mybattlefield/type:artifact:mybattlefield cdaactive text=Master of Etherium's power and toughness are each equal to the number of artifacts you control. -- Other artifact creatures you control get +1/+1. mana={2}{U} type=Artifact Creature @@ -60663,7 +60663,7 @@ toughness=4 [/card] [card] name=Masumaro, First to Live -auto=twicetype:*:myhand/twicetype:*:myhand cdaactive +anyzone=twicetype:*:myhand/twicetype:*:myhand cdaactive text=Masumaro, First to Live's power and toughness are each equal to twice the number of cards in your hand. mana={3}{G}{G}{G} type=Legendary Creature @@ -60673,7 +60673,7 @@ toughness=* [/card] [card] name=Matca Rioters -auto=pbasiclandtypes/pbasiclandtypes cdaactive +anyzone=pbasiclandtypes/pbasiclandtypes cdaactive text=Domain - Matca Rioters's power and toughness are each equal to the number of basic land types among lands you control. mana={2}{G} type=Creature @@ -63699,7 +63699,7 @@ toughness=8 [card] name=Molimo, Maro-Sorcerer abilities=trample -auto=type:land:myBattlefield/type:land:myBattlefield cdaactive +anyzone=type:land:myBattlefield/type:land:myBattlefield cdaactive text=Trample (If this creature would deal enough damage to its blockers to destroy them, you may have it deal the rest of its damage to defending player or planeswalker.) -- Molimo, Maro-Sorcerer's power and toughness are each equal to the number of lands you control. mana={4}{G}{G}{G} type=Legendary Creature @@ -64585,7 +64585,7 @@ toughness=2 [card] name=Mortivore auto={B}:regenerate -auto=type:creature:graveyard/type:creature:graveyard cdaactive +anyzone=type:creature:graveyard/type:creature:graveyard cdaactive text=Mortivore's power and toughness are each equal to the number of creature cards in all graveyards. -- {B}: Regenerate Mortivore. (The next time this creature would be destroyed this turn, it isn't. Instead tap it, remove all damage from it, and remove it from combat.) mana={2}{B}{B} type=Creature @@ -64980,7 +64980,7 @@ toughness=2 [card] name=Multani, Maro-Sorcerer abilities=shroud -auto=type:*:hand/type:*:hand cdaactive +anyzone=type:*:hand/type:*:hand cdaactive text=Shroud (This permanent can't be the target of spells or abilities.) -- Multani's power and toughness are each equal to the total number of cards in all players' hands. mana={4}{G}{G} type=Legendary Creature @@ -65793,7 +65793,7 @@ subtype=Shapeshifter name=Nameless One facedown={3} autofacedown={2}{U}:morph -auto=type:wizard:battlefield/type:wizard:battlefield cdaactive +anyzone=type:wizard:battlefield/type:wizard:battlefield cdaactive text=Nameless One's power and toughness are each equal to the number of Wizards on the battlefield. -- Morph {2}{U} (You may cast this face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.) mana={3}{U} type=Creature @@ -67248,7 +67248,7 @@ type=Sorcery [card] name=Nightmare abilities=flying -auto=type:swamp:mybattlefield/type:swamp:mybattlefield cdaactive +anyzone=type:swamp:mybattlefield/type:swamp:mybattlefield cdaactive text=Flying -- Nightmare's power and toughness are each equal to the number of Swamps you control. mana={5}{B} type=Creature @@ -67366,7 +67366,7 @@ toughness=4 [/card] [card] name=Nightstalker Engine -auto=type:creature:myGraveyard/3 cdaactive +anyzone=type:creature:myGraveyard/3 cdaactive text=Nightstalker Engine's power is equal to the number of creature cards in your graveyard. mana={4}{B} type=Creature @@ -70197,7 +70197,7 @@ toughness=2 [/card] [card] name=Overbeing of Myth -auto=type:*:myhand/type:*:myhand cdaactive +anyzone=type:*:myhand/type:*:myhand cdaactive auto=@each my draw:draw:1 text=Overbeing of Myth's power and toughness are each equal to the number of cards in your hand. -- At the beginning of your draw step, draw an additional card. mana={GU}{GU}{GU}{GU}{GU} @@ -70450,7 +70450,7 @@ type=Sorcery [/card] [card] name=Pack Rat -auto=type:rat:mybattlefield/type:rat:mybattlefield cdaactive +anyzone=type:rat:mybattlefield/type:rat:mybattlefield cdaactive auto={2}{B}{discard(*|myhand)}:token(253624) text=Pack Rat's power and toughness are each equal to the number of Rats you control. -- {2}{B}, Discard a card: Put a token onto the battlefield that's a copy of Pack Rat. mana={1}{B} @@ -70694,7 +70694,7 @@ toughness=4 [/card] [card] name=Pallimud -auto=type:land[tapped]:opponentbattlefield/3 cdaactive +anyzone=type:land[tapped]:opponentbattlefield/3 cdaactive text=As Pallimud enters the battlefield, choose an opponent. -- Pallimud's power is equal to the number of tapped lands the chosen player controls. mana={2}{R} type=Creature @@ -71900,7 +71900,7 @@ toughness=6 [/card] [card] name=Pestilence Rats -auto=othertype:rat:battlefield/3 cdaactive +anyzone=othertype:rat:battlefield/3 cdaactive text=Pestilence Rats's power is equal to the number of other Rats on the battlefield. (For example, as long as there are two other Rats on the battlefield, Pestilence Rats's power and toughness are 2/3.) mana={2}{B} type=Creature @@ -73404,7 +73404,7 @@ toughness=1 [/card] [card] name=Plague Rats -auto=allmyname/allmyname cdaactive +anyzone=allmyname/allmyname cdaactive text=Plague Rats's power and toughness are each equal to the number of creatures named Plague Rats on the battlefield. mana={2}{B} type=Creature @@ -74639,7 +74639,7 @@ subtype=Aura [card] name=Primalcrux abilities=trample -auto=type:manag:mybattlefield/type:manag:mybattlefield cdaactive +anyzone=type:manag:mybattlefield/type:manag:mybattlefield cdaactive text=Trample -- Chroma - Primalcrux's power and toughness are each equal to the number of green mana symbols in the mana costs of permanents you control. mana={G}{G}{G}{G}{G}{G} type=Creature @@ -75329,7 +75329,7 @@ type=Enchantment [/card] [card] name=Psychosis Crawler -auto=type:*:myhand/type:*:myhand cdaactive +anyzone=type:*:myhand/type:*:myhand cdaactive auto=@drawof(player):life:-1 opponent text=Psychosis Crawler's power and toughness are each equal to the number of cards in your hand. - Whenever you draw a card, each opponent loses 1 life. mana={5} @@ -78392,7 +78392,7 @@ toughness=2 [card] name=Reckless One abilities=haste -auto=type:goblin:battlefield/type:goblin:battlefield cdaactive +anyzone=type:goblin:battlefield/type:goblin:battlefield cdaactive text=Haste -- Reckless One's power and toughness are each equal to the number of Goblins on the battlefield. mana={3}{R} type=Creature @@ -79781,7 +79781,7 @@ type=Artifact [card] name=Revenant abilities=flying -auto=type:creature:mygraveyard/type:creature:mygraveyard cdaactive +anyzone=type:creature:mygraveyard/type:creature:mygraveyard cdaactive text=Flying -- Revenant's power and toughness are each equal to the number of creature cards in your graveyard. mana={4}{B} type=Creature @@ -81838,7 +81838,7 @@ toughness=3 [/card] [card] name=Rubblehulk -auto=type:land:mybattlefield/type:land:mybattlefield cdaactive +anyzone=type:land:mybattlefield/type:land:mybattlefield cdaactive autohand={1}{R}{G}{discard}:name(bloodrush) target(creature[attacking]) type:land:mybattlefield/type:land:mybattlefield ueot text=Rubblehulk's power and toughness are each equal to the number of lands you control. -- Bloodrush — {1}{R}{G}, Discard Rubblehulk: Target attacking creature gets +X/+X until end of turn, where X is the number of lands you control. mana={4}{R}{G} @@ -82362,7 +82362,7 @@ type=Artifact [card] name=Rusting Golem auto=fading:5 -auto=counter{0%0.1.Fade}/counter{0%0.1.Fade} cdaactive +anyzone=counter{0%0.1.Fade}/counter{0%0.1.Fade} cdaactive text=Fading 5 (This creature enters the battlefield with five fade counters on it. At the beginning of your upkeep, remove a fade counter from it. If you can't, sacrifice it.) -- Rusting Golem's power and toughness are each equal to the number of fade counters on it. mana={4} type=Artifact Creature @@ -84429,7 +84429,7 @@ toughness=1 [/card] [card] name=Scion of the Wild -auto=type:creature:myBattlefield/type:creature:myBattlefield cdaactive +anyzone=type:creature:myBattlefield/type:creature:myBattlefield cdaactive text=Scion of the Wild's power and toughness are each equal to the number of creatures you control. mana={1}{G}{G} type=Creature @@ -86546,7 +86546,7 @@ toughness=3 name=Serpent of the Endless Sea abilities=cantattack auto=aslongas(island|opponentBattlefield) -cantattack -auto=type:island:myBattlefield/type:island:myBattlefield cdaactive +anyzone=type:island:myBattlefield/type:island:myBattlefield cdaactive text=Serpent of the Endless Sea's power and toughness are each equal to the number of Islands you control. -- Serpent of the Endless Sea can't attack unless defending player controls an Island. mana={4}{U} type=Creature @@ -86619,7 +86619,7 @@ toughness=1 [/card] [card] name=Serra Avatar -auto=lifetotal/lifetotal cdaactive +anyzone=lifetotal/lifetotal cdaactive autograveyard=moveTo(ownerlibrary) && shuffle text=Serra Avatar's power and toughness are each equal to your life total. -- When Serra Avatar is put into a graveyard from anywhere, shuffle it into its owner's library. mana={4}{W}{W}{W} @@ -89377,7 +89377,7 @@ toughness=5 [/card] [card] name=Sima Yi, Wei Field Marshal -auto=type:swamp:myBattlefield/4 cdaactive +anyzone=type:swamp:myBattlefield/4 cdaactive text=Sima Yi, Wei Field Marshal's power is equal to the number of Swamps you control. mana={5}{B} type=Legendary Creature @@ -90842,7 +90842,7 @@ toughness=3 [card] name=Skyshroud War Beast abilities=trample -auto=type:land[-basic]:opponentBattlefield/type:land[-basic]:opponentBattlefield cdaactive +anyzone=type:land[-basic]:opponentBattlefield/type:land[-basic]:opponentBattlefield cdaactive text=Trample -- As Skyshroud War Beast enters the battlefield, choose an opponent. -- Skyshroud War Beast's power and toughness are each equal to the number of nonbasic lands the chosen player controls. mana={1}{G} type=Creature @@ -90926,7 +90926,7 @@ toughness=3 [/card] [card] name=Slag Fiend -auto=type:artifact:graveyard/type:artifact:graveyard cdaactive +anyzone=type:artifact:graveyard/type:artifact:graveyard cdaactive text=Slag Fiend's power and toughness are each equal to the number of artifact cards in all graveyards. mana={R} type=Creature @@ -92448,7 +92448,7 @@ toughness=1 [card] name=Soramaro, First to Dream abilities=flying -auto=type:*:myhand/type:*:myhand cdaactive +anyzone=type:*:myhand/type:*:myhand cdaactive auto={4}{H(land|myBattlefield)}:draw:1 text=Flying -- Soramaro, First to Dream's power and toughness are each equal to the number of cards in your hand. -- {4}, Return a land you control to its owner's hand: Draw a card. mana={4}{U}{U} @@ -93035,7 +93035,7 @@ toughness=2 [/card] [card] name=Soulless One -auto=pgbzombie/pgbzombie cdaactive +anyzone=pgbzombie/pgbzombie cdaactive text=Soulless One's power and toughness are each equal to the number of Zombies on the battlefield plus the number of Zombie cards in all graveyards. mana={3}{B} type=Creature @@ -93092,7 +93092,7 @@ type=Instant [card] name=Soulsurge Elemental abilities=first strike -auto=type:creature:myBattlefield/1 cdaactive +anyzone=type:creature:myBattlefield/1 cdaactive text=First strike -- Soulsurge Elemental's power is equal to the number of creatures you control. mana={3}{R} type=Creature @@ -93637,7 +93637,7 @@ toughness=1 [card] name=Spellheart Chimera abilities=flying,trample -auto=pginstantsorcery/3 cdaactive +anyzone=pginstantsorcery/3 cdaactive text=Flying. -- Trample. -- Spellheart Chimera's power is equal to the number of instant and sorcery cards in your graveyard. mana={1}{U}{R} type=Creature @@ -94632,7 +94632,7 @@ color=green [card] name=Splinterfright abilities=trample -auto=type:creature:mygraveyard/type:creature:mygraveyard cdaactive +anyzone=type:creature:mygraveyard/type:creature:mygraveyard cdaactive auto=@each my upkeep:deplete:2 controller text=Trample -- Splinterfright's power and toughness are each equal to the number of creature cards in your graveyard -- At the beginning of your upkeep, put the top two cards of your library into your graveyard. mana={2}{G} @@ -95035,7 +95035,7 @@ type=Enchantment [/card] [card] name=Squelching Leeches -auto=type:swamp:myBattlefield/type:swamp:myBattlefield cdaactive +anyzone=type:swamp:myBattlefield/type:swamp:myBattlefield cdaactive text=Squelching Leeches's power and toughness are each equal to the number of Swamps you control. mana={2}{B}{B} type=Creature @@ -97237,7 +97237,7 @@ toughness=6 [card] name=Sturmgeist abilities=flying -auto=type:*:myhand/type:*:myhand cdaactive +anyzone=type:*:myhand/type:*:myhand cdaactive auto=@combatdamaged(player) from(this):draw:1 controller text=Flying -- Sturmgeist's power and toughness are each equal to the number of cards in your hand. -- Whenever Sturmgeist deals combat damage to a player, draw a card. mana={3}{U}{U} @@ -98406,7 +98406,7 @@ toughness=0 [/card] [card] name=Swarm of Rats -auto=type:rat:mybattlefield/1 cdaactive +anyzone=type:rat:mybattlefield/1 cdaactive text=Swarm of Rats's power is equal to the number of Rats you control. mana={1}{B} type=Creature @@ -98894,7 +98894,7 @@ type=Sorcery [/card] [card] name=Sylvan Yeti -auto=type:*:myhand/4 cdaactive +anyzone=type:*:myhand/4 cdaactive text=Sylvan Yeti's power is equal to the number of cards in your hand. mana={2}{G}{G} type=Creature @@ -99740,7 +99740,7 @@ toughness=7 [/card] [card] name=Tarmogoyf -auto=gravecardtypes/plusonegravecardtypes cdaactive +anyzone=gravecardtypes/plusonegravecardtypes cdaactive text=Tarmogoyf's power is equal to the number of card types among cards in all graveyards and its toughness is equal to that number plus 1. (The card types are artifact, creature, enchantment, instant, land, planeswalker, sorcery, and tribal.) mana={1}{G} type=Creature @@ -100774,7 +100774,7 @@ type=Artifact [card] name=Terravore abilities=trample -auto=type:land:graveyard/type:land:graveyard cdaactive +anyzone=type:land:graveyard/type:land:graveyard cdaactive text=Trample -- Terravore's power and toughness are each equal to the number of land cards in all graveyards. mana={1}{G}{G} type=Creature @@ -102693,7 +102693,7 @@ toughness=5 [card] name=Tidewalker auto=foreach(island|myBattlefield) counter(0/0,1,Time) oneshot -auto=counter{0%0.1.Time}/counter{0%0.1.Time} cdaactive +anyzone=counter{0%0.1.Time}/counter{0%0.1.Time} cdaactive auto=vanishing:0 text=Tidewalker enters the battlefield with a time counter on it for each Island you control. -- Vanishing (At the beginning of your upkeep, remove a time counter from this permanent. When the last is removed, sacrifice it.) -- Tidewalker's power and toughness are each equal to the number of time counters on it. mana={2}{U} @@ -105860,7 +105860,7 @@ toughness=2 [/card] [card] name=Uktabi Wildcats -auto=type:forest:mybattlefield/type:forest:mybattlefield cdaactive +anyzone=type:forest:mybattlefield/type:forest:mybattlefield cdaactive auto={G}{S(forest|myBattlefield)}:regenerate text=Uktabi Wildcats's power and toughness are each equal to the number of Forests you control. -- {G}, Sacrifice a Forest: Regenerate Uktabi Wildcats. mana={4}{G} @@ -105998,7 +105998,7 @@ type=Artifact [/card] [card] name=Umbra Stalker -auto=type:manab:mygraveyard/type:manab:mygraveyard cdaactive +anyzone=type:manab:mygraveyard/type:manab:mygraveyard cdaactive text=Chroma - Umbra Stalker's power and toughness are each equal to the number of black mana symbols in the mana costs of cards in your graveyard. mana={4}{B}{B}{B} type=Creature @@ -109908,7 +109908,7 @@ toughness=2 name=Elemental type=Creature subtype=Elemental -auto=type:creature:mybattlefield/type:creature:mybattlefield cdaactive +anyzone=type:creature:mybattlefield/type:creature:mybattlefield cdaactive text=This creature's power and toughness are each equal to the number of creature cards in its controller's battlefield. power=* toughness=* @@ -112185,7 +112185,7 @@ toughness=3 [/card] [card] name=Wayfaring Temple -auto=type:creature:mybattlefield/type:creature:mybattlefield cdaactive +anyzone=type:creature:mybattlefield/type:creature:mybattlefield cdaactive auto=@combatdamaged(player) from(this) restriction{type(creature[token]|mybattlefield)~morethan~0}:name(populate) clone notatarget(creature[token]|mybattlefield) text=Wayfaring Temple's power and toughness are each equal to the number of creatures you control. -- Whenever Wayfaring Temple deals combat damage to a player, populate. (Put a token onto the battlefield that's a copy of a creature token you control.) mana={1}{G}{W} @@ -113257,7 +113257,7 @@ toughness=4 [card] name=Wilderness Elemental abilities=trample -auto=type:land[-basic]:opponentbattlefield/3 cdaactive +anyzone=type:land[-basic]:opponentbattlefield/3 cdaactive text=Trample -- Wilderness Elemental's power is equal to the number of nonbasic lands your opponents control. mana={1}{R}{G} type=Creature @@ -115354,7 +115354,7 @@ type=Legendary Land [/card] [card] name=Yavimaya Kavu -auto=type:creature[red]:battlefield/type:creature[green]:battlefield cdaactive +anyzone=type:creature[red]:battlefield/type:creature[green]:battlefield cdaactive text=Yavimaya Kavu's power is equal to the number of red creatures on the battlefield. -- Yavimaya Kavu's toughness is equal to the number of green creatures on the battlefield. mana={2}{R}{G} type=Creature @@ -115776,7 +115776,7 @@ toughness=3 [/card] [card] name=Zendikar Incarnate -auto=type:land:mybattlefield/4 cdaactive +anyzone=type:land:mybattlefield/4 cdaactive text=Zendikar Incarnate's power is equal to the number of lands you control. mana={2}{R}{G} type=Creature diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 10e9d30cc..1cc5ecd0a 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -3080,7 +3080,11 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG } else if(s.find("cdaactive") != string::npos) { - return NEW APowerToughnessModifier(observer, id, card, target, wppt,s,true); + MTGAbility * a = NEW APowerToughnessModifier(observer, id, card, target, wppt,s,true); + a->forcedAlive = 1; + a->forceDestroy = -1; + return a; + //return NEW APowerToughnessModifier(observer, id, card, target, wppt,s,true); } else return NEW APowerToughnessModifier(observer, id, card, target, wppt,s,nonstatic); @@ -3751,7 +3755,7 @@ int AbilityFactory::getAbilities(vector * v, Spell * spell, MTGCar if (dest == zones->exile) { magicText = card->magicTexts["exile"]; - card->exileEffects = true; + card->exileEffects = true; break; } if (dest == zones->library) diff --git a/projects/mtg/src/MTGDeck.cpp b/projects/mtg/src/MTGDeck.cpp index 058c1d4c3..738d8289d 100644 --- a/projects/mtg/src/MTGDeck.cpp +++ b/projects/mtg/src/MTGDeck.cpp @@ -93,6 +93,16 @@ int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primi } } } + if (key == "anyzone") + { + if (!primitive) primitive = NEW CardPrimitive(); + primitive->addMagicText(val,"hand"); + primitive->addMagicText(val,"library"); + primitive->addMagicText(val,"graveyard"); + primitive->addMagicText(val,"stack"); + primitive->addMagicText(val,"exile"); + primitive->addMagicText(val); + } break; case 'b': //buyback From e35c9f6087c7b40e1f0426279b9513835b014b1f Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Sat, 7 Nov 2015 09:59:30 +0800 Subject: [PATCH 5/6] AI plays zerocast cards, Update Rules folder! Its basic pay zero for now... Omniscience is possible :) --- projects/mtg/bin/Res/sets/primitives/mtg.txt | 13 ++++ projects/mtg/include/MTGAbility.h | 2 +- projects/mtg/src/AIPlayerBaka.cpp | 66 ++++++++++++++++++-- projects/mtg/src/MTGAbility.cpp | 2 +- projects/mtg/src/MTGRules.cpp | 30 +++++---- 5 files changed, 96 insertions(+), 17 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index e33f7dbf8..bb577a278 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -11580,6 +11580,7 @@ toughness=2 [/card] [card] name=Boneyard Wurm +alias=001100 anyzone=type:creature:mygraveyard/type:creature:mygraveyard cdaactive text=Boneyard Wurm's power and toughness are each equal to the number of creature cards in your graveyard. mana={1}{G} @@ -14097,6 +14098,7 @@ type=Sorcery [/card] [card] name=Cantivore +alias=001100 abilities=vigilance anyzone=type:enchantment:graveyard/type:enchantment:graveyard cdaactive text=Vigilance -- Cantivore's power and toughness are each equal to the number of enchantment cards in all graveyards. @@ -18065,6 +18067,7 @@ type=Instant [/card] [card] name=Cognivore +alias=001100 abilities=flying anyzone=type:instant:graveyard/type:instant:graveyard cdaactive text=Flying -- Cognivore's power and toughness are each equal to the number of instant cards in all graveyards. @@ -24371,6 +24374,7 @@ text=Destroy target artifact with converted mana cost X. It can't be regenerated [/card] [card] name=Detritivore +alias=001100 anyzone=type:land[-basic]:opponentgraveyard/type:land[-basic]:opponentgraveyard cdaactive autoexile=@counterremoved(0/0,1,Time) from(sourcecard) suspended:destroy target(land[-basic]) suspend(0)={X}{3}{R} @@ -56072,6 +56076,7 @@ toughness=5 [/card] [card] name=Lhurgoyf +alias=001100 anyzone=type:creature:graveyard/plusonetype:creature:graveyard cdaactive text=Lhurgoyf's power is equal to the number of creature cards in all graveyards and its toughness is equal to that number plus 1. mana={2}{G}{G} @@ -57452,6 +57457,7 @@ toughness=2 [/card] [card] name=Lord of Extinction +alias=001100 anyzone=type:*:graveyard/type:*:graveyard cdaactive text=Lord of Extinction's power and toughness are each equal to the number of cards in all graveyards. mana={3}{B}{G} @@ -58816,6 +58822,7 @@ toughness=6 [/card] [card] name=Magnivore +alias=001100 abilities=haste anyzone=type:sorcery:graveyard/type:sorcery:graveyard cdaactive text=Haste (This creature can attack the turn it comes under your control.) -- Magnivore's power and toughness are each equal to the number of sorcery cards in all graveyards. @@ -64584,6 +64591,7 @@ toughness=2 [/card] [card] name=Mortivore +alias=001100 auto={B}:regenerate anyzone=type:creature:graveyard/type:creature:graveyard cdaactive text=Mortivore's power and toughness are each equal to the number of creature cards in all graveyards. -- {B}: Regenerate Mortivore. (The next time this creature would be destroyed this turn, it isn't. Instead tap it, remove all damage from it, and remove it from combat.) @@ -79780,6 +79788,7 @@ type=Artifact [/card] [card] name=Revenant +alias=001100 abilities=flying anyzone=type:creature:mygraveyard/type:creature:mygraveyard cdaactive text=Flying -- Revenant's power and toughness are each equal to the number of creature cards in your graveyard. @@ -90926,6 +90935,7 @@ toughness=3 [/card] [card] name=Slag Fiend +alias=001100 anyzone=type:artifact:graveyard/type:artifact:graveyard cdaactive text=Slag Fiend's power and toughness are each equal to the number of artifact cards in all graveyards. mana={R} @@ -94631,6 +94641,7 @@ color=green [/card] [card] name=Splinterfright +alias=001100 abilities=trample anyzone=type:creature:mygraveyard/type:creature:mygraveyard cdaactive auto=@each my upkeep:deplete:2 controller @@ -100773,6 +100784,7 @@ type=Artifact [/card] [card] name=Terravore +alias=001100 abilities=trample anyzone=type:land:graveyard/type:land:graveyard cdaactive text=Trample -- Terravore's power and toughness are each equal to the number of land cards in all graveyards. @@ -105998,6 +106010,7 @@ type=Artifact [/card] [card] name=Umbra Stalker +alias=001100 anyzone=type:manab:mygraveyard/type:manab:mygraveyard cdaactive text=Chroma - Umbra Stalker's power and toughness are each equal to the number of black mana symbols in the mana costs of cards in your graveyard. mana={4}{B}{B}{B} diff --git a/projects/mtg/include/MTGAbility.h b/projects/mtg/include/MTGAbility.h index af8cbbeee..70d6344b9 100644 --- a/projects/mtg/include/MTGAbility.h +++ b/projects/mtg/include/MTGAbility.h @@ -213,7 +213,7 @@ public: COUNTERS = 30, PUT_INTO_PLAY_WITH_KICKER = 31, STANDARD_FIZZLER = 32, - CASTINGRAVEEXILE_COST = 33, + PAYZERO_COST = 33, }; }; diff --git a/projects/mtg/src/AIPlayerBaka.cpp b/projects/mtg/src/AIPlayerBaka.cpp index e0d269e69..634414632 100644 --- a/projects/mtg/src/AIPlayerBaka.cpp +++ b/projects/mtg/src/AIPlayerBaka.cpp @@ -631,10 +631,6 @@ int OrderedAIAction::getEfficiency() { efficiency += 55; } - else if (dynamic_cast(a)) - { - efficiency += 45; - } SAFE_DELETE(transAbility); return efficiency; } @@ -1838,6 +1834,10 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty { shouldPlayPercentage = 90; } + else if (!card->isLand() && card->has(Constants::PAYZERO)) + { + shouldPlayPercentage = 70; + } else { // shouldPlay == baka_effect_bad giving it a 1 for odd ball lottery chance. @@ -1986,6 +1986,10 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty { shouldPlayPercentage = 90; } + else if (!card->isLand() && card->has(Constants::PAYZERO)) + { + shouldPlayPercentage = 70; + } else { // shouldPlay == baka_effect_bad giving it a 1 for odd ball lottery chance. @@ -2133,6 +2137,10 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty { shouldPlayPercentage = 90; } + else if (!card->isLand() && card->has(Constants::PAYZERO)) + { + shouldPlayPercentage = 70; + } else { // shouldPlay == baka_effect_bad giving it a 1 for odd ball lottery chance. @@ -2413,6 +2421,56 @@ int AIPlayerBaka::computeActions() nextCardToPlay = NULL; count++; } + + if(nextCardToPlay == NULL)//check if there is a free card to play, play it.... + {//TODO: add potential mana if we can pay if there is a cost increaser in play + CardDescriptor cd; + if (game->hand->hasAbility(Constants::PAYZERO)) + { + //Attempt to put free cards into play + cd.init(); + cd.SetExclusionColor(Constants::MTG_COLOR_LAND); + MTGCardInstance *freecard = cd.match(game->hand); + int canCastCard = game->playRestrictions->canPutIntoZone(freecard, game->inPlay); + if (freecard && (canCastCard == PlayRestriction::CAN_PLAY) && freecard->has(Constants::PAYZERO) && (freecard->getIncreasedManaCost()->getConvertedCost() < 1)) + { + MTGAbility * castFreeCard = observer->mLayers->actionLayer()->getAbility(MTGAbility::PAYZERO_COST); + AIAction * aa = NEW AIAction(this, castFreeCard, freecard); //TODO putinplay action + clickstream.push(aa); + break; + } + } + if (game->graveyard->hasAbility(Constants::PAYZERO) && game->graveyard->hasAbility(Constants::CANPLAYFROMGRAVEYARD)) + { + //Attempt to put free cards into play + cd.init(); + cd.SetExclusionColor(Constants::MTG_COLOR_LAND); + MTGCardInstance *freecard = cd.match(game->graveyard); + int canCastCard = game->playRestrictions->canPutIntoZone(freecard, game->inPlay); + if (freecard && (canCastCard == PlayRestriction::CAN_PLAY) && freecard->has(Constants::PAYZERO) && freecard->has(Constants::CANPLAYFROMGRAVEYARD) && (freecard->getIncreasedManaCost()->getConvertedCost() < 1) && (freecard->alias != 001100)) + { + MTGAbility * castFreeCard = observer->mLayers->actionLayer()->getAbility(MTGAbility::PAYZERO_COST); + AIAction * aa = NEW AIAction(this, castFreeCard, freecard); //TODO putinplay action + clickstream.push(aa); + break; + } + } + if (game->exile->hasAbility(Constants::PAYZERO) && game->exile->hasAbility(Constants::CANPLAYFROMEXILE)) + { + //Attempt to put free cards into play + cd.init(); + cd.SetExclusionColor(Constants::MTG_COLOR_LAND); + MTGCardInstance *freecard = cd.match(game->exile); + int canCastCard = game->playRestrictions->canPutIntoZone(freecard, game->inPlay); + if (freecard && (canCastCard == PlayRestriction::CAN_PLAY) && freecard->has(Constants::PAYZERO) && freecard->has(Constants::CANPLAYFROMEXILE) && (freecard->getIncreasedManaCost()->getConvertedCost() < 1) && (freecard->alias != 001100)) + { + MTGAbility * castFreeCard = observer->mLayers->actionLayer()->getAbility(MTGAbility::PAYZERO_COST); + AIAction * aa = NEW AIAction(this, castFreeCard, freecard); //TODO putinplay action + clickstream.push(aa); + break; + } + } + }//end } SAFE_DELETE(currentMana); diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 1cc5ecd0a..bcb131764 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -1156,7 +1156,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG observer->addObserver(NEW MTGMorphCostRule(observer, -1)); return NULL; } - found = s.find("playfromgraveyardrule"); + found = s.find("payzerorule"); if(found != string::npos) { observer->addObserver(NEW MTGPayZeroRule(observer, -1)); diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 03b6dc136..d43c870ac 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -489,7 +489,11 @@ int MTGKickerRule::isReactingToClick(MTGCardInstance * card, ManaCost *) } ManaCost * playerMana = player->getManaPool(); ManaCost * withKickerCost= NEW ManaCost(card->model->data->getManaCost()); - withKickerCost->add(withKickerCost->getKicker()); + if(card->getIncreasedManaCost()->getConvertedCost()) + withKickerCost->add(card->getIncreasedManaCost()); + if(card->getReducedManaCost()->getConvertedCost()) + withKickerCost->remove(card->getReducedManaCost()); + withKickerCost->add(card->model->data->getManaCost()->getKicker()); if(!playerMana->canAfford(withKickerCost)) { delete withKickerCost; @@ -508,11 +512,15 @@ int MTGKickerRule::reactToClick(MTGCardInstance * card) Player * player = game->currentlyActing(); ManaCost * withKickerCost= NEW ManaCost(card->model->data->getManaCost());//using pointers here alters the real cost of the card. - if (card->getManaCost()->getKicker()->isMulti) + if(card->getIncreasedManaCost()->getConvertedCost()) + withKickerCost->add(card->getIncreasedManaCost()); + if(card->getReducedManaCost()->getConvertedCost()) + withKickerCost->remove(card->getReducedManaCost()); + if (card->model->data->getManaCost()->getKicker()->isMulti) { while(player->getManaPool()->canAfford(withKickerCost)) { - withKickerCost->add(withKickerCost->getKicker()); + withKickerCost->add(card->model->data->getManaCost()->getKicker()); card->kicked += 1; } card->kicked -= 1; @@ -522,7 +530,7 @@ int MTGKickerRule::reactToClick(MTGCardInstance * card) } else { - withKickerCost->add(withKickerCost->getKicker()); + withKickerCost->add(card->model->data->getManaCost()->getKicker()); card->paymenttype = MTGAbility::PUT_INTO_PLAY_WITH_KICKER; } if (withKickerCost->isExtraPaymentSet()) @@ -638,9 +646,9 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * if(card->has(Constants::CANPLAYFROMGRAVEYARD)) - alternativeName = "Alternate Cast Card From Graveyard"; + alternativeName = "Alternate Cast From Graveyard"; else if(card->has(Constants::CANPLAYFROMEXILE)) - alternativeName = "Alternate Cast Card From Exile"; + alternativeName = "Alternate Cast From Exile"; else if(card->model->data->getManaCost()->getAlternative() && card->model->data->getManaCost()->getAlternative()->alternativeName.size()) alternativeName = card->model->data->getManaCost()->getAlternative()->alternativeName; @@ -1145,7 +1153,7 @@ MTGMorphCostRule * MTGMorphCostRule::clone() const MTGPayZeroRule::MTGPayZeroRule(GameObserver* observer, int _id) : MTGAlternativeCostRule(observer, _id) { - aType = MTGAbility::CASTINGRAVEEXILE_COST; + aType = MTGAbility::PAYZERO_COST; } int MTGPayZeroRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) @@ -1166,11 +1174,11 @@ int MTGPayZeroRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) if ((!card->has(Constants::CANPLAYFROMGRAVEYARD) && player->game->graveyard->hasCard(card))||(!card->has(Constants::CANPLAYFROMEXILE) && player->game->exile->hasCard(card))) return 0; if(card->has(Constants::CANPLAYFROMGRAVEYARD)) - CustomName = "Pay Zero To Cast From Graveyard"; + CustomName = "Zero Cast From Graveyard"; else if(card->has(Constants::CANPLAYFROMEXILE)) - CustomName = "Pay Zero To Cast From Exile"; + CustomName = "Zero Cast From Exile"; else - CustomName = "Pay Zero To Cast"; + CustomName = "Zero Cast From Anywhere"; return MTGAlternativeCostRule::isReactingToClick(card, mana, cost); } @@ -1182,7 +1190,7 @@ int MTGPayZeroRule::reactToClick(MTGCardInstance * card) ManaCost * cost = NEW ManaCost(ManaCost::parseManaCost("{0}",NULL,NULL)); - card->paymenttype = MTGAbility::CASTINGRAVEEXILE_COST; + card->paymenttype = MTGAbility::PAYZERO_COST; return MTGAlternativeCostRule::reactToClick(card, cost, ManaCost::MANA_PAID); } From efdc4071da960a1056a6b382e45aaa003abbfc2b Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Sat, 7 Nov 2015 10:45:54 +0800 Subject: [PATCH 6/6] comment --- projects/mtg/bin/Res/sets/primitives/unsupported.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/projects/mtg/bin/Res/sets/primitives/unsupported.txt b/projects/mtg/bin/Res/sets/primitives/unsupported.txt index 6338488fa..be4eec13f 100644 --- a/projects/mtg/bin/Res/sets/primitives/unsupported.txt +++ b/projects/mtg/bin/Res/sets/primitives/unsupported.txt @@ -12498,6 +12498,7 @@ text=Pyrotechnics deals 4 damage divided as you choose among any number of targe mana={4}{R} type=Sorcery [/card] +#anyzone is basic for now and used for cdaactive [card] name=Qasali Ambusher text=Reach -- If a creature is attacking you and you control a Forest and a Plains, you may cast Qasali Ambusher without paying its mana cost and as though it had flash. @@ -12812,6 +12813,7 @@ mana={2}{U} type=Enchantment subtype=Aura [/card] +#needs suspend ability not suspend activated ability [card] name=Reality Strobe text=Return target permanent to its owner's hand. Exile Reality Strobe with three time counters on it. -- Suspend 3 - {2}{U} (Rather than cast this card from your hand, you may pay {2}{U} and exile it with three time counters on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost.)