AI: logic for X in Sac cost

This commit is contained in:
Hans Mackowiak
2021-01-02 05:15:08 +00:00
committed by Michael Kamensky
parent 6841f3c084
commit 7c9ac66e8a
69 changed files with 283 additions and 320 deletions

View File

@@ -558,17 +558,14 @@ public class AiCostDecision extends CostDecisionMakerBase {
return null; return null;
} }
final String amount = cost.getAmount();
Integer c = cost.convertAmount(); Integer c = cost.convertAmount();
if (c == null) { if (c == null) {
if (ability.getSVar(cost.getAmount()).equals("XChoice")) { final String sVar = ability.getSVar(amount);
if (sVar.equals("XChoice")) {
String logic = ability.getParamOrDefault("AILogic", ""); String logic = ability.getParamOrDefault("AILogic", "");
if ("SacToReduceCost".equals(logic)) { if (!logic.isEmpty() && !logic.equals("Never")) {
// e.g. Torgaar, Famine Incarnate
// TODO: currently returns an empty list, so the AI doesn't sacrifice anything. Trying to make
// the AI decide on creatures to sac makes the AI sacrifice them, but the cost is not reduced and the
// AI pays the full mana cost anyway (despite sacrificing creatures).
return PaymentDecision.card(new CardCollection());
} else if (!logic.isEmpty() && !logic.equals("Never")) {
// If at least some other AI logic is specified, assume that the AI for that API knows how // If at least some other AI logic is specified, assume that the AI for that API knows how
// to define ChosenX and thus honor that value. // to define ChosenX and thus honor that value.
// Cards which have no special logic for this yet but which do work in a simple/suboptimal way // Cards which have no special logic for this yet but which do work in a simple/suboptimal way
@@ -578,8 +575,10 @@ public class AiCostDecision extends CostDecisionMakerBase {
// Other cards are assumed to be flagged AI:RemoveDeck:All for now // Other cards are assumed to be flagged AI:RemoveDeck:All for now
return null; return null;
} }
} else if (sVar.equals("Count$xPaid")) {
c = AbilityUtils.calculateAmount(source, "PayX", ability);
} else { } else {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); c = AbilityUtils.calculateAmount(source, amount, ability);
} }
} }
final AiController aic = ((PlayerControllerAi)player.getController()).getAi(); final AiController aic = ((PlayerControllerAi)player.getController()).getAi();

View File

@@ -90,9 +90,7 @@ public class ComputerUtilCost {
// value later as the AI decides what to do (in checkApiLogic / checkAiLogic) // value later as the AI decides what to do (in checkApiLogic / checkAiLogic)
if (sa.hasSVar(remCounter.getAmount())) { if (sa.hasSVar(remCounter.getAmount())) {
final String sVar = sa.getSVar(remCounter.getAmount()); final String sVar = sa.getSVar(remCounter.getAmount());
if (sVar.equals("XChoice") && !sa.hasSVar("ChosenX")) { if (sVar.equals("Count$xPaid") && sa.hasSVar("PayX")) {
sa.setSVar("ChosenX", String.valueOf(source.getCounters(type)));
} else if (sVar.equals("Count$xPaid") && sa.hasSVar("PayX")) {
sa.setSVar("PayX", Integer.toString(Math.min(Integer.valueOf(sa.getSVar("PayX")), source.getCounters(type)))); sa.setSVar("PayX", Integer.toString(Math.min(Integer.valueOf(sa.getSVar("PayX")), source.getCounters(type))));
} }
} }
@@ -675,6 +673,7 @@ public class ComputerUtilCost {
} }
public static int getMaxXValue(SpellAbility sa, Player ai) { public static int getMaxXValue(SpellAbility sa, Player ai) {
final Card source = sa.getHostCard();
final Cost abCost = sa.getPayCosts(); final Cost abCost = sa.getPayCosts();
if (abCost == null || !abCost.hasXInAnyCostPart()) { if (abCost == null || !abCost.hasXInAnyCostPart()) {
return 0; return 0;
@@ -691,8 +690,42 @@ public class ComputerUtilCost {
if ("X".equals(sa.getTargetRestrictions().getMinTargets())) { if ("X".equals(sa.getTargetRestrictions().getMinTargets())) {
val = ObjectUtils.min(val, CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa).size()); val = ObjectUtils.min(val, CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa).size());
} }
if (sa.hasParam("AIMaxTgtsCount")) {
// Cards that have confusing costs for the AI (e.g. Eliminate the Competition) can have forced max target constraints specified
// TODO: is there a better way to predict things like "sac X" costs without needing a special AI variable?
val = ObjectUtils.min(val, AbilityUtils.calculateAmount(sa.getHostCard(), "Count$" + sa.getParam("AIMaxTgtsCount"), sa));
}
} }
return ObjectUtils.defaultIfNull(ObjectUtils.min(val, abCost.getMaxForNonManaX(sa, ai)), 0); val = ObjectUtils.min(val, abCost.getMaxForNonManaX(sa, ai));
if (val != null && val > 0) {
// filter cost parts for preferences, don't choose X > than possible preferences
for (final CostPart part : abCost.getCostParts()) {
if (part instanceof CostSacrifice) {
if (part.payCostFromSource()) {
continue;
}
if (!part.getAmount().equals("X")) {
continue;
}
final CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), part.getType().split(";"), source.getController(), source, null);
int count = 0;
while (count < val) {
Card prefCard = ComputerUtil.getCardPreference(ai, source, "SacCost", typeList);
if (prefCard == null) {
break;
}
typeList.remove(prefCard);
count++;
}
val = ObjectUtils.min(val, count);
}
}
}
return ObjectUtils.defaultIfNull(val, 0);
} }
} }

View File

@@ -1162,7 +1162,7 @@ public class ComputerUtilMana {
* @param extraMana extraMana * @param extraMana extraMana
* @return ManaCost * @return ManaCost
*/ */
static ManaCostBeingPaid calculateManaCost(final SpellAbility sa, final boolean test, final int extraMana) { public static ManaCostBeingPaid calculateManaCost(final SpellAbility sa, final boolean test, final int extraMana) {
Card card = sa.getHostCard(); Card card = sa.getHostCard();
ZoneType castFromBackup = null; ZoneType castFromBackup = null;
if (test && sa.isSpell()) { if (test && sa.isSpell()) {
@@ -1627,31 +1627,4 @@ public class ComputerUtilMana {
} }
return convoke; return convoke;
} }
public static int determineMaxAffordableX(Player ai, SpellAbility sa) {
if (sa.getPayCosts().getCostMana() == null) {
return -1;
}
int numTgts = 0;
int numX = sa.getPayCosts().getCostMana().getAmountOfX();
if (numX == 0) {
return -1;
}
int testX = 1;
while (testX <= 100) {
if (ComputerUtilMana.canPayManaCost(sa, ai, testX)) {
numTgts++;
} else {
break;
}
testX++;
}
numTgts /= numX;
return numTgts;
}
} }

View File

@@ -103,7 +103,7 @@ public class PlayerControllerAi extends PlayerController {
} }
@Override @Override
public Integer announceRequirements(SpellAbility ability, String announce, boolean allowZero) { public Integer announceRequirements(SpellAbility ability, String announce) {
// For now, these "announcements" are made within the AI classes of the appropriate SA effects // For now, these "announcements" are made within the AI classes of the appropriate SA effects
if (ability.getApi() != null) { if (ability.getApi() != null) {
switch (ability.getApi()) { switch (ability.getApi()) {

View File

@@ -40,6 +40,7 @@ import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.player.PlayerPredicates; import forge.game.player.PlayerPredicates;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityPredicates;
import forge.game.spellability.SpellPermanent; import forge.game.spellability.SpellPermanent;
import forge.game.staticability.StaticAbility; import forge.game.staticability.StaticAbility;
import forge.game.trigger.Trigger; import forge.game.trigger.Trigger;
@@ -1400,7 +1401,7 @@ public class SpecialCardAi {
int x = -1, best = 0; int x = -1, best = 0;
Card single = null; Card single = null;
for (int i = 0; i < loyalty; i++) { for (int i = 0; i < loyalty; i++) {
sa.setSVar("ChosenX", "Number$" + i); sa.setXManaCostPaid(i);
oppType = CardLists.filterControlledBy(game.getCardsIn(origin), ai.getOpponents()); oppType = CardLists.filterControlledBy(game.getCardsIn(origin), ai.getOpponents());
oppType = AbilityUtils.filterListByType(oppType, sa.getParam("ChangeType"), sa); oppType = AbilityUtils.filterListByType(oppType, sa.getParam("ChangeType"), sa);
computerType = AbilityUtils.filterListByType(ai.getCardsIn(origin), sa.getParam("ChangeType"), sa); computerType = AbilityUtils.filterListByType(ai.getCardsIn(origin), sa.getParam("ChangeType"), sa);
@@ -1417,13 +1418,8 @@ public class SpecialCardAi {
} }
// check if +1 would be sufficient // check if +1 would be sufficient
if (single != null) { if (single != null) {
SpellAbility ugin_burn = null; // TODO use better logic to find the right Deal Damage Effect?
for (final SpellAbility s : source.getSpellAbilities()) { SpellAbility ugin_burn = Iterables.find(source.getSpellAbilities(), SpellAbilityPredicates.isApi(ApiType.DealDamage), null);
if (s.getApi() == ApiType.DealDamage) {
ugin_burn = s;
break;
}
}
if (ugin_burn != null) { if (ugin_burn != null) {
// basic logic copied from DamageDealAi::dealDamageChooseTgtC // basic logic copied from DamageDealAi::dealDamageChooseTgtC
if (ugin_burn.canTarget(single)) { if (ugin_burn.canTarget(single)) {
@@ -1434,17 +1430,18 @@ public class SpecialCardAi {
if (can_kill) { if (can_kill) {
return false; return false;
} }
}
// simple check to burn player instead of exiling planeswalker // simple check to burn player instead of exiling planeswalker
if (single.isPlaneswalker() && single.getCurrentLoyalty() <= 3) { if (single.isPlaneswalker() && single.getCurrentLoyalty() <= 3) {
return false; return false;
} }
} }
} }
}
if (x == -1) { if (x == -1) {
return false; return false;
} }
sa.setSVar("ChosenX", "Number$" + x); sa.setXManaCostPaid(x);
sa.setSVar("PayX", String.valueOf(x));
return true; return true;
} }
} }

View File

@@ -845,7 +845,6 @@ public class ChangeZoneAi extends SpellAbilityAi {
} }
final ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination")); final ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination"));
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Game game = ai.getGame(); final Game game = ai.getGame();
final AbilitySub abSub = sa.getSubAbility(); final AbilitySub abSub = sa.getSubAbility();
@@ -859,8 +858,17 @@ public class ChangeZoneAi extends SpellAbilityAi {
} }
sa.resetTargets(); sa.resetTargets();
CardCollection list = CardLists.getValidCards(game.getCardsIn(origin), tgt.getValidTgts(), ai, source, sa); // X controls the minimum targets
list = CardLists.getTargetableCards(list, sa); if ("X".equals(sa.getTargetRestrictions().getMinTargets()) && sa.getSVar("X").equals("Count$xPaid")) {
// Set PayX here to maximum value.
int xPay = ComputerUtilCost.getMaxXValue(sa, ai);
sa.setSVar("PayX", Integer.toString(xPay));
// TODO need to set XManaCostPaid for targets, maybe doesn't need PayX anymore?
sa.setXManaCostPaid(xPay);
// TODO since change of PayX. the shouldCastLessThanMax logic might be faulty
}
CardCollection list = CardLists.getTargetableCards(game.getCardsIn(origin), sa);
// Filter AI-specific targets if provided // Filter AI-specific targets if provided
list = ComputerUtil.filterAITgts(sa, ai, list, true); list = ComputerUtil.filterAITgts(sa, ai, list, true);
@@ -896,7 +904,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
//System.out.println("isPreferredTarget ok " + list); //System.out.println("isPreferredTarget ok " + list);
} }
if (list.size() < tgt.getMinTargets(sa.getHostCard(), sa)) { if (list.size() < sa.getMinTargets()) {
return false; return false;
} }
@@ -921,7 +929,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
} }
// Combat bouncing // Combat bouncing
if (tgt.getMinTargets(sa.getHostCard(), sa) <= 1) { if (sa.getMinTargets() <= 1) {
if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
Combat currCombat = game.getCombat(); Combat currCombat = game.getCombat();
CardCollection attackers = currCombat.getAttackers(); CardCollection attackers = currCombat.getAttackers();
@@ -964,7 +972,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
// if it's blink or bounce, try to save my about to die stuff // if it's blink or bounce, try to save my about to die stuff
final boolean blink = (destination.equals(ZoneType.Exile) && (subApi == ApiType.DelayedTrigger final boolean blink = (destination.equals(ZoneType.Exile) && (subApi == ApiType.DelayedTrigger
|| "DelayedBlink".equals(sa.getParam("AILogic")) || (subApi == ApiType.ChangeZone && subAffected.equals("Remembered")))); || "DelayedBlink".equals(sa.getParam("AILogic")) || (subApi == ApiType.ChangeZone && subAffected.equals("Remembered"))));
if ((destination.equals(ZoneType.Hand) || blink) && (tgt.getMinTargets(sa.getHostCard(), sa) <= 1)) { if ((destination.equals(ZoneType.Hand) || blink) && (sa.getMinTargets() <= 1)) {
// save my about to die stuff // save my about to die stuff
Card tobounce = canBouncePermanent(ai, sa, list); Card tobounce = canBouncePermanent(ai, sa, list);
if (tobounce != null) { if (tobounce != null) {
@@ -974,7 +982,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
sa.getTargets().add(tobounce); sa.getTargets().add(tobounce);
boolean saheeliFelidarCombo = sa.getHostCard().getName().equals("Felidar Guardian") boolean saheeliFelidarCombo = ComputerUtilAbility.getAbilitySourceName(sa).equals("Felidar Guardian")
&& tobounce.getName().equals("Saheeli Rai") && tobounce.getName().equals("Saheeli Rai")
&& CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Felidar Guardian")).size() < && CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Felidar Guardian")).size() <
CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.isType("Creature")).size() + ai.getOpponentsGreatestLifeTotal() + 10; CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.isType("Creature")).size() + ai.getOpponentsGreatestLifeTotal() + 10;
@@ -1107,7 +1115,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
} }
boolean doWithoutTarget = sa.hasParam("Planeswalker") && sa.usesTargeting() boolean doWithoutTarget = sa.hasParam("Planeswalker") && sa.usesTargeting()
&& sa.getTargetRestrictions().getMinTargets(source, sa) == 0 && sa.getMinTargets() == 0
&& sa.getPayCosts().hasSpecificCostType(CostPutCounter.class); && sa.getPayCosts().hasSpecificCostType(CostPutCounter.class);
if (list.isEmpty() && !doWithoutTarget) { if (list.isEmpty() && !doWithoutTarget) {
@@ -1118,12 +1126,12 @@ public class ChangeZoneAi extends SpellAbilityAi {
// the Unless cost (for example, Erratic Portal) // the Unless cost (for example, Erratic Portal)
list.removeAll(getSafeTargetsIfUnlessCostPaid(ai, sa, list)); list.removeAll(getSafeTargetsIfUnlessCostPaid(ai, sa, list));
if (!mandatory && list.size() < tgt.getMinTargets(sa.getHostCard(), sa)) { if (!mandatory && sa.isTargetNumberValid()) {
return false; return false;
} }
// target loop // target loop
while (sa.getTargets().size() < tgt.getMaxTargets(sa.getHostCard(), sa)) { while (sa.canAddMoreTarget()) {
// AI Targeting // AI Targeting
Card choice = null; Card choice = null;
@@ -1152,7 +1160,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
} }
//option to hold removal instead only applies for single targeted removal //option to hold removal instead only applies for single targeted removal
if (!immediately && tgt.getMaxTargets(source, sa) == 1) { if (!immediately && sa.getMaxTargets() == 1) {
if (!ComputerUtilCard.useRemovalNow(sa, choice, 0, destination)) { if (!ComputerUtilCard.useRemovalNow(sa, choice, 0, destination)) {
return false; return false;
} }
@@ -1188,7 +1196,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
} }
} }
if (choice == null) { // can't find anything left if (choice == null) { // can't find anything left
if (sa.getTargets().size() == 0 || sa.getTargets().size() < tgt.getMinTargets(sa.getHostCard(), sa)) { if (sa.getTargets().size() == 0 || !sa.isTargetNumberValid()) {
if (!mandatory) { if (!mandatory) {
sa.resetTargets(); sa.resetTargets();
} }
@@ -1223,7 +1231,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
} }
// honor the Same Creature Type restriction // honor the Same Creature Type restriction
if (tgt.isWithSameCreatureType()) { if (sa.getTargetRestrictions().isWithSameCreatureType()) {
Card firstTarget = sa.getTargetCard(); Card firstTarget = sa.getTargetCard();
if (firstTarget != null && !choice.sharesCreatureTypeWith(firstTarget)) { if (firstTarget != null && !choice.sharesCreatureTypeWith(firstTarget)) {
list.remove(choice); list.remove(choice);

View File

@@ -102,9 +102,10 @@ public class ChooseCardAi extends SpellAbilityAi {
} else if (aiLogic.equals("Ashiok")) { } else if (aiLogic.equals("Ashiok")) {
final int loyalty = host.getCounters(CounterEnumType.LOYALTY) - 1; final int loyalty = host.getCounters(CounterEnumType.LOYALTY) - 1;
for (int i = loyalty; i >= 0; i--) { for (int i = loyalty; i >= 0; i--) {
host.setSVar("ChosenX", "Number$" + i); sa.setSVar("PayX", String.valueOf(i));
sa.setXManaCostPaid(i);
choices = ai.getGame().getCardsIn(choiceZone); choices = ai.getGame().getCardsIn(choiceZone);
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), host.getController(), host); choices = CardLists.getValidCards(choices, sa.getParam("Choices"), host.getController(), host, sa);
if (!choices.isEmpty()) { if (!choices.isEmpty()) {
return true; return true;
} }

View File

@@ -20,7 +20,6 @@ public class ChooseColorAi extends SpellAbilityAi {
@Override @Override
protected boolean canPlayAI(Player ai, SpellAbility sa) { protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Card source = sa.getHostCard();
final Game game = ai.getGame(); final Game game = ai.getGame();
final String sourceName = ComputerUtilAbility.getAbilitySourceName(sa); final String sourceName = ComputerUtilAbility.getAbilitySourceName(sa);
final PhaseHandler ph = game.getPhaseHandler(); final PhaseHandler ph = game.getPhaseHandler();

View File

@@ -45,7 +45,7 @@ public class ChooseTypeAi extends SpellAbilityAi {
return false; return false;
} }
int maxX = ComputerUtilMana.determineMaxAffordableX(aiPlayer, sa); int maxX = ComputerUtilMana.determineLeftoverMana(sa, aiPlayer);
int avgPower = 0; int avgPower = 0;
// predict the opposition // predict the opposition

View File

@@ -137,11 +137,6 @@ public class DestroyAi extends SpellAbilityAi {
} else { } else {
maxTargets = sa.getMaxTargets(); maxTargets = sa.getMaxTargets();
} }
if (sa.hasParam("AIMaxTgtsCount")) {
// Cards that have confusing costs for the AI (e.g. Eliminate the Competition) can have forced max target constraints specified
// TODO: is there a better way to predict things like "sac X" costs without needing a special AI variable?
maxTargets = Math.min(CardFactoryUtil.xCount(sa.getHostCard(), "Count$" + sa.getParam("AIMaxTgtsCount")), maxTargets);
}
if (maxTargets == 0) { if (maxTargets == 0) {
// can't afford X or otherwise target anything // can't afford X or otherwise target anything

View File

@@ -23,8 +23,6 @@ import forge.game.Game;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType; import forge.game.ability.ApiType;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CounterEnumType; import forge.game.card.CounterEnumType;
import forge.game.card.CounterType; import forge.game.card.CounterType;
import forge.game.cost.*; import forge.game.cost.*;
@@ -180,8 +178,7 @@ public class DrawAi extends SpellAbilityAi {
int numHand = ai.getCardsIn(ZoneType.Hand).size(); int numHand = ai.getCardsIn(ZoneType.Hand).size();
if ("Jace, Vryn's Prodigy".equals(sourceName) && ai.getCardsIn(ZoneType.Graveyard).size() > 3) { if ("Jace, Vryn's Prodigy".equals(sourceName) && ai.getCardsIn(ZoneType.Graveyard).size() > 3) {
return CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.PLANESWALKERS, return !ai.isCardInPlay("Jace, Telepath Unbound");
CardPredicates.isType("Jace")).size() <= 0;
} }
if (source.isSpell() && ai.getCardsIn(ZoneType.Hand).contains(source)) { if (source.isSpell() && ai.getCardsIn(ZoneType.Hand).contains(source)) {
numHand--; // remember to count looter card if it is a spell in hand numHand--; // remember to count looter card if it is a spell in hand
@@ -222,6 +219,7 @@ public class DrawAi extends SpellAbilityAi {
final int computerLibrarySize = ai.getCardsIn(ZoneType.Library).size(); final int computerLibrarySize = ai.getCardsIn(ZoneType.Library).size();
final int computerMaxHandSize = ai.getMaxHandSize(); final int computerMaxHandSize = ai.getMaxHandSize();
final SpellAbility gainLife = sa.findSubAbilityByType(ApiType.GainLife);
final SpellAbility loseLife = sa.findSubAbilityByType(ApiType.LoseLife); final SpellAbility loseLife = sa.findSubAbilityByType(ApiType.LoseLife);
final SpellAbility getPoison = sa.findSubAbilityByType(ApiType.Poison); final SpellAbility getPoison = sa.findSubAbilityByType(ApiType.Poison);
@@ -243,7 +241,7 @@ public class DrawAi extends SpellAbilityAi {
if (drawback && !sa.getSVar("PayX").equals("")) { if (drawback && !sa.getSVar("PayX").equals("")) {
numCards = Integer.parseInt(sa.getSVar("PayX")); numCards = Integer.parseInt(sa.getSVar("PayX"));
} else { } else {
numCards = ComputerUtilMana.determineLeftoverMana(sa, ai); numCards = ComputerUtilCost.getMaxXValue(sa, ai);
// try not to overdraw // try not to overdraw
int safeDraw = Math.min(computerMaxHandSize - computerHandSize, computerLibrarySize - 3); int safeDraw = Math.min(computerMaxHandSize - computerHandSize, computerLibrarySize - 3);
if (sa.getHostCard().isInstant() || sa.getHostCard().isSorcery()) { safeDraw++; } // card will be spent if (sa.getHostCard().isInstant() || sa.getHostCard().isSorcery()) { safeDraw++; } // card will be spent
@@ -252,8 +250,7 @@ public class DrawAi extends SpellAbilityAi {
assumeSafeX = true; assumeSafeX = true;
} }
xPaid = true; xPaid = true;
} } else if (sa.getSVar(num).equals("Count$Converge")) {
if (sa.getSVar(num).equals("Count$Converge")) {
numCards = ComputerUtilMana.getConvergeCount(sa, ai); numCards = ComputerUtilMana.getConvergeCount(sa, ai);
} }
} }
@@ -270,14 +267,6 @@ public class DrawAi extends SpellAbilityAi {
while ((ComputerUtil.aiLifeInDanger(ai, false, numCards) && (numCards > 0))) { while ((ComputerUtil.aiLifeInDanger(ai, false, numCards) && (numCards > 0))) {
numCards--; numCards--;
} }
} else if (sa.getPayCosts().hasSpecificCostType(CostSacrifice.class)) {
// [e.g. Krav, the Unredeemed and other cases which say "Sacrifice X creatures: draw X cards]
// TODO: Add special logic to limit/otherwise modify the ChosenX value here
// Skip this ability if nothing is to be chosen for sacrifice
if (numCards <= 0) {
return false;
}
} }
sa.setSVar("ChosenX", Integer.toString(numCards)); sa.setSVar("ChosenX", Integer.toString(numCards));
@@ -347,6 +336,20 @@ public class DrawAi extends SpellAbilityAi {
} }
} }
} }
// that opponent can gain life and also lose life and that life gain is negative
if (gainLife != null && oppA.canGainLife() && oppA.canLoseLife() && ComputerUtil.lifegainNegative(oppA, source)) {
if (gainLife.hasParam("Defined") && "Targeted".equals(gainLife.getParam("Defined"))) {
if (numCards >= oppA.getLife()) {
if (xPaid) {
sa.setSVar("PayX", Integer.toString(oppA.getLife()));
}
sa.getTargets().add(oppA);
return true;
}
}
}
// try to make opponent lose to poison // try to make opponent lose to poison
// currently only Caress of Phyrexia // currently only Caress of Phyrexia
if (getPoison != null && oppA.canReceiveCounters(CounterType.get(CounterEnumType.POISON))) { if (getPoison != null && oppA.canReceiveCounters(CounterType.get(CounterEnumType.POISON))) {

View File

@@ -118,8 +118,7 @@ public class ManaEffectAi extends SpellAbilityAi {
int numCounters = 0; int numCounters = 0;
int manaSurplus = 0; int manaSurplus = 0;
if ("XChoice".equals(host.getSVar("X")) if ("Count$xPaid".equals(host.getSVar("X")) && sa.getPayCosts().hasSpecificCostType(CostRemoveCounter.class)) {
&& sa.getPayCosts().hasSpecificCostType(CostRemoveCounter.class)) {
CounterType ctrType = CounterType.get(CounterEnumType.KI); // Petalmane Baku CounterType ctrType = CounterType.get(CounterEnumType.KI); // Petalmane Baku
for (CostPart part : sa.getPayCosts().getCostParts()) { for (CostPart part : sa.getPayCosts().getCostParts()) {
if (part instanceof CostRemoveCounter) { if (part instanceof CostRemoveCounter) {
@@ -206,7 +205,9 @@ public class ManaEffectAi extends SpellAbilityAi {
// Don't remove more counters than would be needed to cast the more expensive thing we want to cast, // Don't remove more counters than would be needed to cast the more expensive thing we want to cast,
// otherwise the AI grabs too many counters at once. // otherwise the AI grabs too many counters at once.
int maxCtrs = Aggregates.max(castableSpells, CardPredicates.Accessors.fnGetCmc) - manaSurplus; int maxCtrs = Aggregates.max(castableSpells, CardPredicates.Accessors.fnGetCmc) - manaSurplus;
sa.setSVar("ChosenX", "Number$" + Math.min(numCounters, maxCtrs)); int min = Math.min(numCounters, maxCtrs);
sa.setXManaCostPaid(min);
sa.setSVar("PayX", Integer.toString(min));
} }
// TODO: this will probably still waste the card from time to time. Somehow improve detection of castable material. // TODO: this will probably still waste the card from time to time. Somehow improve detection of castable material.

View File

@@ -102,7 +102,7 @@ public class PermanentAi extends SpellAbilityAi {
ManaCost mana = sa.getPayCosts().getTotalMana(); ManaCost mana = sa.getPayCosts().getTotalMana();
if (mana.countX() > 0) { if (mana.countX() > 0) {
// Set PayX here to maximum value. // Set PayX here to maximum value.
final int xPay = ComputerUtilMana.determineLeftoverMana(sa, ai); final int xPay = ComputerUtilCost.getMaxXValue(sa, ai);
final Card source = sa.getHostCard(); final Card source = sa.getHostCard();
if (source.hasConverge()) { if (source.hasConverge()) {
card.setSVar("PayX", Integer.toString(0)); card.setSVar("PayX", Integer.toString(0));
@@ -134,6 +134,20 @@ public class PermanentAi extends SpellAbilityAi {
} }
} }
if ("SacToReduceCost".equals(sa.getParam("AILogic"))) {
// reset X to better calculate
sa.setXManaCostPaid(0);
ManaCostBeingPaid paidCost = ComputerUtilMana.calculateManaCost(sa, true, 0);
int generic = paidCost.getGenericManaAmount();
// Set PayX here to maximum value.
int xPay = ComputerUtilCost.getMaxXValue(sa, ai);
// currently cards with SacToReduceCost reduce by 2 generic
xPay = Math.min(xPay, generic / 2);
card.setSVar("PayX", Integer.toString(xPay));
sa.setXManaCostPaid(xPay);
}
if (sa.hasParam("Announce") && sa.getParam("Announce").startsWith("Multikicker")) { if (sa.hasParam("Announce") && sa.getParam("Announce").startsWith("Multikicker")) {
// String announce = sa.getParam("Announce"); // String announce = sa.getParam("Announce");
ManaCost mkCost = sa.getMultiKickerManaCost(); ManaCost mkCost = sa.getMultiKickerManaCost();

View File

@@ -115,7 +115,7 @@ public class ScryAi extends SpellAbilityAi {
} }
// has spell that can be cast if one counter is removed // has spell that can be cast if one counter is removed
if (!CardLists.filter(hand, CardPredicates.hasCMC(counterNum)).isEmpty()) { if (!CardLists.filter(hand, CardPredicates.hasCMC(counterNum)).isEmpty()) {
sa.setSVar("ChosenX", "Number$1"); sa.setSVar("PayX", "1");
return true; return true;
} }
} }
@@ -142,10 +142,10 @@ public class ScryAi extends SpellAbilityAi {
if (maxToRemove <= 0) { if (maxToRemove <= 0) {
return false; return false;
} }
sa.setSVar("ChosenX", "Number$" + maxToRemove); sa.setSVar("PayX", String.valueOf(maxToRemove));
} else { } else {
// no Instant or Sorceries anymore, just scry // no Instant or Sorceries anymore, just scry
sa.setSVar("ChosenX", "Number$" + Math.min(counterNum, libsize)); sa.setSVar("PayX", String.valueOf(Math.min(counterNum, libsize)));
} }
} }
return true; return true;

View File

@@ -28,7 +28,7 @@ public class BidLifeEffect extends SpellAbilityEffect {
if (sa.hasParam("StartBidding")) { if (sa.hasParam("StartBidding")) {
String start = sa.getParam("StartBidding"); String start = sa.getParam("StartBidding");
if ("Any".equals(start)) { if ("Any".equals(start)) {
startBidding = activator.getController().announceRequirements(sa, Localizer.getInstance().getMessage("lblChooseStartingBid"), true); startBidding = activator.getController().announceRequirements(sa, Localizer.getInstance().getMessage("lblChooseStartingBid"));
} else { } else {
startBidding = AbilityUtils.calculateAmount(host, start, sa); startBidding = AbilityUtils.calculateAmount(host, start, sa);
} }

View File

@@ -60,7 +60,7 @@ public class ChooseNumberEffect extends SpellAbilityEffect {
} else { } else {
String title = sa.hasParam("ListTitle") ? sa.getParam("ListTitle") : Localizer.getInstance().getMessage("lblChooseNumber"); String title = sa.hasParam("ListTitle") ? sa.getParam("ListTitle") : Localizer.getInstance().getMessage("lblChooseNumber");
if (anyNumber) { if (anyNumber) {
Integer value = p.getController().announceRequirements(sa, title, true); Integer value = p.getController().announceRequirements(sa, title);
chosen = (value == null ? 0 : value); chosen = (value == null ? 0 : value);
} else { } else {
chosen = p.getController().chooseNumber(sa, title, min, max); chosen = p.getController().chooseNumber(sa, title, min, max);

View File

@@ -124,7 +124,7 @@ public class Cost implements Serializable {
Collections.sort(this.costParts, new Comparator<CostPart>() { Collections.sort(this.costParts, new Comparator<CostPart>() {
@Override @Override
public int compare(CostPart o1, CostPart o2) { public int compare(CostPart o1, CostPart o2) {
return o1.paymentOrder() - o2.paymentOrder(); return ObjectUtils.compare(o1.paymentOrder(), o2.paymentOrder());
} }
}); });
} }
@@ -254,34 +254,15 @@ public class Cost implements Serializable {
} }
if (parsedMana == null && manaParts.length() > 0) { if (parsedMana == null && (manaParts.length() > 0 || xCantBe0)) {
parsedMana = new CostPartMana(new ManaCost(new ManaCostParser(manaParts.toString())), xCantBe0 ? "XCantBe0" : null); parsedMana = new CostPartMana(new ManaCost(new ManaCostParser(manaParts.toString())), xCantBe0 ? "XCantBe0" : null);
} }
if (parsedMana != null) { if (parsedMana != null) {
if(parsedMana.shouldPayLast()) // back from the brink pays mana after 'exile' part is paid costParts.add(parsedMana);
this.costParts.add(parsedMana);
else
this.costParts.add(0, parsedMana);
}
// inspect parts to set Sac, {T} and {Q} flags
for (int iCp = 0; iCp < costParts.size(); iCp++) {
CostPart cp = costParts.get(iCp);
// untap cost has to be last so that a card can't use e.g. its own mana ability while paying for a part of its own mana cost
// (e.g. Zhur-Taa Druid equipped with Umbral Mantle, paying the mana cost of {3}, {Q} )
if (cp instanceof CostUntap) {
costParts.remove(iCp);
costParts.add(cp);
}
// tap cost has to be first so that a card can't use e.g. its own mana ability while paying for a part of its own mana cost
// (e.g. Ally Encampment with the cost of 1, {T} )
if (cp instanceof CostTap) {
costParts.remove(iCp);
costParts.add(0, cp);
}
} }
// technically the user might pay the costs in any order
// but needs to activate mana ability first
sort(); sort();
} }

View File

@@ -17,6 +17,10 @@
*/ */
package forge.game.cost; package forge.game.cost;
import org.apache.commons.lang3.ObjectUtils;
import com.google.common.collect.Iterables;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollectionView; import forge.game.card.CardCollectionView;
@@ -53,6 +57,16 @@ public class CostSacrifice extends CostPartWithList {
@Override @Override
public int paymentOrder() { return 15; } public int paymentOrder() { return 15; }
@Override
public Integer getMaxAmountX(SpellAbility ability, Player payer) {
final Card source = ability.getHostCard();
CardCollectionView typeList = payer.getCardsIn(ZoneType.Battlefield);
typeList = CardLists.getValidCards(typeList, getType().split(";"), payer, source, ability);
typeList = CardLists.filter(typeList, CardPredicates.canBeSacrificedBy(ability));
return typeList.size();
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
@@ -63,17 +77,11 @@ public class CostSacrifice extends CostPartWithList {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("Sacrifice "); sb.append("Sacrifice ");
final Integer i = this.convertAmount(); if (payCostFromSource()) {
sb.append(getType());
if (this.payCostFromSource()) {
sb.append(this.getType());
} else { } else {
final String desc = this.getTypeDescription() == null ? this.getType() : this.getTypeDescription(); final String desc = ObjectUtils.firstNonNull(getTypeDescription(), getType());
if (i != null) { sb.append(Cost.convertAmountTypeToWords(convertAmount(), getAmount(), desc));
sb.append(Cost.convertIntAndTypeToWords(i, desc));
} else {
sb.append(Cost.convertAmountTypeToWords(this.getAmount(), desc));
}
} }
return sb.toString(); return sb.toString();
} }
@@ -90,21 +98,20 @@ public class CostSacrifice extends CostPartWithList {
final Card source = ability.getHostCard(); final Card source = ability.getHostCard();
// You can always sac all // You can always sac all
if (!this.payCostFromSource()) { if (!payCostFromSource()) {
// If the sacrificed type is dependant on an annoucement, can't necesarily rule out the CanPlay call if ("All".equalsIgnoreCase(getAmount())) {
boolean needsAnnoucement = ability.hasParam("Announce") && this.getType().contains(ability.getParam("Announce"));
CardCollectionView typeList = activator.getCardsIn(ZoneType.Battlefield); CardCollectionView typeList = activator.getCardsIn(ZoneType.Battlefield);
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source, ability); typeList = CardLists.getValidCards(typeList, getType().split(";"), activator, source, ability);
// it needs to check if everything can be sacrificed
return Iterables.all(typeList, CardPredicates.canBeSacrificedBy(ability));
}
Integer amount = this.convertAmount(); Integer amount = this.convertAmount();
if (amount == null) { if (amount == null) {
amount = AbilityUtils.calculateAmount(source, getAmount(), ability); amount = AbilityUtils.calculateAmount(source, getAmount(), ability);
} }
typeList = CardLists.filter(typeList, CardPredicates.canBeSacrificedBy(ability)); return getMaxAmountX(ability, activator) >= amount;
return needsAnnoucement || (amount == null) || (typeList.size() >= amount);
// If amount is null, it's either "ALL" or "X" // If amount is null, it's either "ALL" or "X"
// if X is defined, it needs to be calculated and checked, if X is // if X is defined, it needs to be calculated and checked, if X is
// choice, it can be Paid even if it's 0 // choice, it can be Paid even if it's 0

View File

@@ -110,7 +110,7 @@ public abstract class PlayerController {
public abstract Map<Card, Integer> assignCombatDamage(Card attacker, CardCollectionView blockers, int damageDealt, GameEntity defender, boolean overrideOrder); public abstract Map<Card, Integer> assignCombatDamage(Card attacker, CardCollectionView blockers, int damageDealt, GameEntity defender, boolean overrideOrder);
public abstract Integer announceRequirements(SpellAbility ability, String announce, boolean allowZero); public abstract Integer announceRequirements(SpellAbility ability, String announce);
public abstract CardCollectionView choosePermanentsToSacrifice(SpellAbility sa, int min, int max, CardCollectionView validTargets, String message); public abstract CardCollectionView choosePermanentsToSacrifice(SpellAbility sa, int min, int max, CardCollectionView validTargets, String message);
public abstract CardCollectionView choosePermanentsToDestroy(SpellAbility sa, int min, int max, CardCollectionView validTargets, String message); public abstract CardCollectionView choosePermanentsToDestroy(SpellAbility sa, int min, int max, CardCollectionView validTargets, String message);
public abstract TargetChoices chooseNewTargetsFor(SpellAbility ability); public abstract TargetChoices chooseNewTargetsFor(SpellAbility ability);

View File

@@ -127,7 +127,7 @@ public class PlayerControllerForTests extends PlayerController {
} }
@Override @Override
public Integer announceRequirements(SpellAbility ability, String announce, boolean allowZero) { public Integer announceRequirements(SpellAbility ability, String announce) {
throw new IllegalStateException("Erring on the side of caution here..."); throw new IllegalStateException("Erring on the side of caution here...");
} }

View File

@@ -3,11 +3,11 @@ ManaCost:1 U B
Types:Legendary Planeswalker Ashiok Types:Legendary Planeswalker Ashiok
Loyalty:3 Loyalty:3
A:AB$ Dig | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | ValidTgts$ Opponent | DigNum$ 3 | ChangeNum$ All | DestinationZone$ Exile | RememberChanged$ True | SpellDescription$ Exile the top three cards of target opponent's library. A:AB$ Dig | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | ValidTgts$ Opponent | DigNum$ 3 | ChangeNum$ All | DestinationZone$ Exile | RememberChanged$ True | SpellDescription$ Exile the top three cards of target opponent's library.
A:AB$ ChooseCard | Cost$ SubCounter<X/LOYALTY> | References$ X | Choices$ Creature.cmcEQChosenX+IsRemembered+ExiledWithSource | ChoiceZone$ Exile | Planeswalker$ True | SubAbility$ DBChangeZone | AILogic$ Ashiok | SpellDescription$ Put a creature card with converted mana cost X exiled with CARDNAME onto the battlefield under your control. That creature is a Nightmare in addition to its other types. A:AB$ ChooseCard | Cost$ SubCounter<X/LOYALTY> | References$ X | Choices$ Creature.cmcEQX+IsRemembered+ExiledWithSource | ChoiceZone$ Exile | Planeswalker$ True | SubAbility$ DBChangeZone | AILogic$ Ashiok | SpellDescription$ Put a creature card with converted mana cost X exiled with CARDNAME onto the battlefield under your control. That creature is a Nightmare in addition to its other types.
SVar:DBChangeZone:DB$ ChangeZone | Defined$ ChosenCard | Origin$ Exile | Destination$ Battlefield | ChangeType$ Creature.cmcEQChosenX+IsRemembered+ExiledWithSource | ChangeNum$ 1 | GainControl$ True | SubAbility$ DBAnimate SVar:DBChangeZone:DB$ ChangeZone | Defined$ ChosenCard | Origin$ Exile | Destination$ Battlefield | ChangeType$ Creature.cmcEQX+IsRemembered+ExiledWithSource | ChangeNum$ 1 | GainControl$ True | SubAbility$ DBAnimate
SVar:DBAnimate:DB$ Animate | Defined$ ChosenCard | Types$ Nightmare | Permanent$ True | SubAbility$ DBCleanMinus SVar:DBAnimate:DB$ Animate | Defined$ ChosenCard | Types$ Nightmare | Permanent$ True | SubAbility$ DBCleanMinus
SVar:DBCleanMinus:DB$ Cleanup | ForgetDefined$ ChosenCard | ClearChosenCard$ True SVar:DBCleanMinus:DB$ Cleanup | ForgetDefined$ ChosenCard | ClearChosenCard$ True
SVar:X:XChoice SVar:X:Count$xPaid
A:AB$ ChangeZoneAll | Cost$ SubCounter<10/LOYALTY> | ChangeType$ Card.OppCtrl | Origin$ Graveyard,Hand | Destination$ Exile | RememberChanged$ True | Planeswalker$ True | Ultimate$ True | SpellDescription$ Exile all cards from all opponents' hands and graveyards. A:AB$ ChangeZoneAll | Cost$ SubCounter<10/LOYALTY> | ChangeType$ Card.OppCtrl | Origin$ Graveyard,Hand | Destination$ Exile | RememberChanged$ True | Planeswalker$ True | Ultimate$ True | SpellDescription$ Exile all cards from all opponents' hands and graveyards.
T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered+ExiledWithSource | Execute$ DBForget T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered+ExiledWithSource | Execute$ DBForget
SVar:DBForget:DB$ Pump | ForgetObjects$ TriggeredCard SVar:DBForget:DB$ Pump | ForgetObjects$ TriggeredCard

View File

@@ -3,9 +3,7 @@ ManaCost:4
Types:Artifact Types:Artifact
A:AB$ PutCounter | Cost$ 2 T | CounterType$ CHARGE | CounterNum$ 1 | SpellDescription$ Put a charge counter on CARDNAME. A:AB$ PutCounter | Cost$ 2 T | CounterType$ CHARGE | CounterNum$ 1 | SpellDescription$ Put a charge counter on CARDNAME.
A:AB$ Mana | Cost$ T SubCounter<X/CHARGE> | References$ X,Y | Produced$ B | Amount$ Y | CostDesc$ {T}, Remove any number of charge counters from CARDNAME: | AILogic$ ManaRitualBattery.1 | AINoRecursiveCheck$ True | SpellDescription$ Add {B}, then add an additional {B} for each charge counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/CHARGE> | References$ X,Y | Produced$ B | Amount$ Y | CostDesc$ {T}, Remove any number of charge counters from CARDNAME: | AILogic$ ManaRitualBattery.1 | AINoRecursiveCheck$ True | SpellDescription$ Add {B}, then add an additional {B} for each charge counter removed this way.
SVar:Y:Number$1/Plus.ChosenX SVar:Y:SVar$X/Plus.1
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/black_mana_battery.jpg
Oracle:{2}, {T}: Put a charge counter on Black Mana Battery.\n{T}, Remove any number of charge counters from Black Mana Battery: Add {B}, then add an additional {B} for each charge counter removed this way. Oracle:{2}, {T}: Put a charge counter on Black Mana Battery.\n{T}, Remove any number of charge counters from Black Mana Battery: Add {B}, then add an additional {B} for each charge counter removed this way.

View File

@@ -3,9 +3,7 @@ ManaCost:4
Types:Artifact Types:Artifact
A:AB$ PutCounter | Cost$ 2 T | CounterType$ CHARGE | CounterNum$ 1 | SpellDescription$ Put a charge counter on CARDNAME. A:AB$ PutCounter | Cost$ 2 T | CounterType$ CHARGE | CounterNum$ 1 | SpellDescription$ Put a charge counter on CARDNAME.
A:AB$ Mana | Cost$ T SubCounter<X/CHARGE> | Produced$ U | Amount$ Y | CostDesc$ {T}, Remove any number of charge counters from CARDNAME: | References$ X,Y | AILogic$ ManaRitualBattery.1 | AINoRecursiveCheck$ True | SpellDescription$ Add {U}, then add an additional {U} for each charge counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/CHARGE> | Produced$ U | Amount$ Y | CostDesc$ {T}, Remove any number of charge counters from CARDNAME: | References$ X,Y | AILogic$ ManaRitualBattery.1 | AINoRecursiveCheck$ True | SpellDescription$ Add {U}, then add an additional {U} for each charge counter removed this way.
SVar:Y:Number$1/Plus.ChosenX SVar:Y:SVar$X/Plus.1
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/blue_mana_battery.jpg
Oracle:{2}, {T}: Put a charge counter on Blue Mana Battery.\n{T}, Remove any number of charge counters from Blue Mana Battery: Add {U}, then add an additional {U} for each charge counter removed this way. Oracle:{2}, {T}: Put a charge counter on Blue Mana Battery.\n{T}, Remove any number of charge counters from Blue Mana Battery: Add {U}, then add an additional {U} for each charge counter removed this way.

View File

@@ -2,7 +2,7 @@ Name:Bosh, Iron Golem Avatar
ManaCost:no cost ManaCost:no cost
Types:Vanguard Types:Vanguard
HandLifeModifier:+0/-2 HandLifeModifier:+0/-2
A:AB$ DealDamage | ActivationZone$ Command | Announce$ X | Cost$ X Sac<1/Artifact.cmcEQX/artifact with converted mana cost X> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | References$ X | SpellDescription$ CARDNAME deals X damage to any target. A:AB$ DealDamage | ActivationZone$ Command | Cost$ X Sac<1/Artifact.cmcEQX/artifact with converted mana cost X> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | References$ X | SpellDescription$ CARDNAME deals X damage to any target.
SVar:X:Count$xPaid SVar:X:Count$xPaid
SVar:Picture:https://downloads.cardforge.org/images/cards/VAN/Bosh, Iron Golem Avatar.full.jpg SVar:Picture:https://downloads.cardforge.org/images/cards/VAN/Bosh, Iron Golem Avatar.full.jpg
AI:RemoveDeck:All AI:RemoveDeck:All

View File

@@ -5,9 +5,7 @@ K:CARDNAME enters the battlefield tapped.
K:You may choose not to untap CARDNAME during your untap step. K:You may choose not to untap CARDNAME during your untap step.
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | IsPresent$ Card.Self+tapped | Execute$ TrigStore | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is tapped, put a storage counter on it. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | IsPresent$ Card.Self+tapped | Execute$ TrigStore | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is tapped, put a storage counter on it.
SVar:TrigStore:DB$PutCounter | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 SVar:TrigStore:DB$PutCounter | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1
A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ B | Amount$ ChosenX | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | SpellDescription$ Add {B} for each storage counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ B | Amount$ X | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | SpellDescription$ Add {B} for each storage counter removed this way.
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/bottomless_vault.jpg
Oracle:Bottomless Vault enters the battlefield tapped.\nYou may choose not to untap Bottomless Vault during your untap step.\nAt the beginning of your upkeep, if Bottomless Vault is tapped, put a storage counter on it.\n{T}, Remove any number of storage counters from Bottomless Vault: Add {B} for each storage counter removed this way. Oracle:Bottomless Vault enters the battlefield tapped.\nYou may choose not to untap Bottomless Vault during your untap step.\nAt the beginning of your upkeep, if Bottomless Vault is tapped, put a storage counter on it.\n{T}, Remove any number of storage counters from Bottomless Vault: Add {B} for each storage counter removed this way.

View File

@@ -3,8 +3,7 @@ ManaCost:2
Types:Artifact Types:Artifact
A:AB$ PutCounter | Cost$ 1 T | CounterType$ CHARGE | CounterNum$ 1 | SubAbility$ DBCast | SpellDescription$ Put a charge counter on Brain in a Jar, then you may cast an instant or sorcery card with converted mana cost equal to the number of charge counters on Brain in a Jar from your hand without paying its mana cost. A:AB$ PutCounter | Cost$ 1 T | CounterType$ CHARGE | CounterNum$ 1 | SubAbility$ DBCast | SpellDescription$ Put a charge counter on Brain in a Jar, then you may cast an instant or sorcery card with converted mana cost equal to the number of charge counters on Brain in a Jar from your hand without paying its mana cost.
SVar:DBCast:DB$ Play | ValidZone$ Hand | Valid$ Instant.YouOwn+cmcEQY,Sorcery.YouOwn+cmcEQY | Controller$ You | WithoutManaCost$ True | Optional$ True | Amount$ 1 | References$ Y SVar:DBCast:DB$ Play | ValidZone$ Hand | Valid$ Instant.YouOwn+cmcEQY,Sorcery.YouOwn+cmcEQY | Controller$ You | WithoutManaCost$ True | Optional$ True | Amount$ 1 | References$ Y
A:AB$ Scry | Cost$ 3 T SubCounter<X/CHARGE> | ScryNum$ ChosenX | References$ X | AILogic$ BrainJar | SpellDescription$ Scry X. A:AB$ Scry | Cost$ 3 T SubCounter<X/CHARGE> | ScryNum$ X | References$ X | AILogic$ BrainJar | SpellDescription$ Scry X.
SVar:X:XChoice SVar:X:Count$xPaid
SVar:Y:Count$CardCounters.CHARGE SVar:Y:Count$CardCounters.CHARGE
SVar:Picture:http://www.wizards.com/global/images/magic/general/brain_in_a_jar.jpg
Oracle:{1}, {T}: Put a charge counter on Brain in a Jar, then you may cast an instant or sorcery card with converted mana cost equal to the number of charge counters on Brain in a Jar from your hand without paying its mana cost.\n{3}, {T}, Remove X charge counters from Brain in a Jar: Scry X. Oracle:{1}, {T}: Put a charge counter on Brain in a Jar, then you may cast an instant or sorcery card with converted mana cost equal to the number of charge counters on Brain in a Jar from your hand without paying its mana cost.\n{3}, {T}, Remove X charge counters from Brain in a Jar: Scry X.

View File

@@ -3,8 +3,7 @@ ManaCost:no cost
Types:Land Types:Land
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME. A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME.
A:AB$ Mana | Cost$ 1 SubCounter<X/STORAGE> | Produced$ Combo W U | Amount$ ChosenX | CostDesc$ {1}, Remove X storage counters from CARDNAME: | References$ X | SpellDescription$ Add X mana in any combination of {W} and/or {U}. A:AB$ Mana | Cost$ 1 SubCounter<X/STORAGE> | Produced$ Combo W U | Amount$ X | CostDesc$ {1}, Remove X storage counters from CARDNAME: | References$ X | SpellDescription$ Add X mana in any combination of {W} and/or {U}.
SVar:X:XChoice SVar:X:Count$xPaid
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/calciform_pools.jpg
Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Calciform Pools.\n{1}, Remove X storage counters from Calciform Pools: Add X mana in any combination of {W} and/or {U}. Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Calciform Pools.\n{1}, Remove X storage counters from Calciform Pools: Add X mana in any combination of {W} and/or {U}.

View File

@@ -2,8 +2,9 @@ Name:Champion of Stray Souls
ManaCost:4 B B ManaCost:4 B B
Types:Creature Skeleton Warrior Types:Creature Skeleton Warrior
PT:4/4 PT:4/4
# TODO: The AI will never activate this ability since it can't properly pay the cost. Consider updating. A:AB$ ChangeZone | Cost$ 3 B B T Sac<X/Creature.Other/other creature(s)> | CostDesc$ {3}{B}{B}, {T}, Sacrifice X other creatures: | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouOwn | TgtPrompt$ Select X target creature cards from your graveyard | TargetMin$ X | TargetMax$ X | References$ X | AIMinTgts$ 3 | SpellDescription$ Return X target creatures from your graveyard to the battlefield.
A:AB$ ChangeZone | Announce$ X | Cost$ 3 B B T Sac<X/Creature.Other/other creature(s)> | CostDesc$ {3}{B}{B}, {T}, Sacrifice X other creatures: | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouOwn | TgtPrompt$ Select X target creature cards from your graveyard | TargetMin$ X | TargetMax$ X | References$ X | AILogic$ Never | SpellDescription$ Return X target creatures from your graveyard to the battlefield.
A:AB$ ChangeZone | Cost$ 5 B B | Origin$ Graveyard | Destination$ Library | ActivationZone$ Graveyard | Defined$ Self | SpellDescription$ Put CARDNAME on top of your library from your graveyard. A:AB$ ChangeZone | Cost$ 5 B B | Origin$ Graveyard | Destination$ Library | ActivationZone$ Graveyard | Defined$ Self | SpellDescription$ Put CARDNAME on top of your library from your graveyard.
SVar:X:Count$xPaid
SVar:AIPreference:SacCost$Creature.token,Creature.cmcLE3
AI:RemoveDeck:All AI:RemoveDeck:All
Oracle:{3}{B}{B}, {T}, Sacrifice X other creatures: Return X target creature cards from your graveyard to the battlefield.\n{5}{B}{B}: Put Champion of Stray Souls on top of your library from your graveyard. Oracle:{3}{B}{B}, {T}, Sacrifice X other creatures: Return X target creature cards from your graveyard to the battlefield.\n{5}{B}{B}: Put Champion of Stray Souls on top of your library from your graveyard.

View File

@@ -7,6 +7,6 @@ A:AB$ Effect | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | EffectOwner$ P
SVar:BOTTrig:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Execute$ ChandraDmg | TriggerDescription$ At the beginning of your upkeep, this emblem deals 1 damage to you. SVar:BOTTrig:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Execute$ ChandraDmg | TriggerDescription$ At the beginning of your upkeep, this emblem deals 1 damage to you.
SVar:ChandraDmg:DB$ DealDamage | Defined$ TriggeredPlayer | NumDmg$ 1 SVar:ChandraDmg:DB$ DealDamage | Defined$ TriggeredPlayer | NumDmg$ 1
A:AB$ DamageAll | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | ValidCards$ Creature.nonElemental | NumDmg$ 3 | SpellDescription$ CARDNAME deals 3 damage to each non-Elemental creature. A:AB$ DamageAll | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | ValidCards$ Creature.nonElemental | NumDmg$ 3 | SpellDescription$ CARDNAME deals 3 damage to each non-Elemental creature.
A:AB$ DealDamage | Cost$ SubCounter<X/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Creature,Planeswalker | NumDmg$ ChosenX | References$ X | ReplaceDyingDefined$ Targeted | SpellDescription$ CARDNAME deals X damage to target creature or planeswalker. If a permanent dealt damage this way would die this turn, exile it instead. A:AB$ DealDamage | Cost$ SubCounter<X/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Creature,Planeswalker | NumDmg$ X | References$ X | ReplaceDyingDefined$ Targeted | SpellDescription$ CARDNAME deals X damage to target creature or planeswalker. If a permanent dealt damage this way would die this turn, exile it instead.
SVar:X:XChoice SVar:X:Count$xPaid
Oracle:This spell can't be countered.\n[+2]: Each opponent gets an emblem with "At the beginning of your upkeep, this emblem deals 1 damage to you."\n[-3]: Chandra, Awakened Inferno deals 3 damage to each non-Elemental creature.\n[-X]: Chandra, Awakened Inferno deals X damage to target creature or planeswalker. If a permanent dealt damage this way would die this turn, exile it instead. Oracle:This spell can't be countered.\n[+2]: Each opponent gets an emblem with "At the beginning of your upkeep, this emblem deals 1 damage to you."\n[-3]: Chandra, Awakened Inferno deals 3 damage to each non-Elemental creature.\n[-X]: Chandra, Awakened Inferno deals X damage to target creature or planeswalker. If a permanent dealt damage this way would die this turn, exile it instead.

View File

@@ -7,9 +7,8 @@ A:AB$ Discard | Cost$ AddCounter<0/LOYALTY> | Planeswalker$ True | Defined$ You
SVar:DBDraw:DB$ Draw | NumCards$ Y | Defined$ You | SubAbility$ DBCleanup | SpellDescription$ Draw that many cards | References$ Y SVar:DBDraw:DB$ Draw | NumCards$ Y | Defined$ You | SubAbility$ DBCleanup | SpellDescription$ Draw that many cards | References$ Y
SVar:Y:Remembered$Amount.Plus.1 SVar:Y:Remembered$Amount.Plus.1
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
A:AB$ DamageAll | Cost$ SubCounter<X/LOYALTY> | NumDmg$ ChosenX | References$ X | ValidCards$ Creature | Planeswalker$ True | Ultimate$ True | ValidDescription$ each creature. | SpellDescription$ CARDNAME deals X damage to each creature. A:AB$ DamageAll | Cost$ SubCounter<X/LOYALTY> | NumDmg$ X | References$ X | ValidCards$ Creature | Planeswalker$ True | Ultimate$ True | ValidDescription$ each creature. | SpellDescription$ CARDNAME deals X damage to each creature.
SVar:X:XChoice SVar:X:Count$xPaid
DeckHas:Ability$Token DeckHas:Ability$Token
SVar:PlayMain1:ALWAYS SVar:PlayMain1:ALWAYS
SVar:Picture:http://www.wizards.com/global/images/magic/general/chandra_flamecaller.jpg
Oracle:[+1]: Create two 3/1 red Elemental creature tokens with haste. Exile them at the beginning of the next end step.\n[0]: Discard all the cards in your hand, then draw that many cards plus one.\n[X]: Chandra, Flamecaller deals X damage to each creature. Oracle:[+1]: Create two 3/1 red Elemental creature tokens with haste. Exile them at the beginning of the next end step.\n[0]: Discard all the cards in your hand, then draw that many cards plus one.\n[X]: Chandra, Flamecaller deals X damage to each creature.

View File

@@ -3,10 +3,9 @@ ManaCost:3 R R
Types:Legendary Planeswalker Chandra Types:Legendary Planeswalker Chandra
Loyalty:6 Loyalty:6
A:AB$ DealDamage | Cost$ AddCounter<1/LOYALTY> | ValidTgts$ Player,Planeswalker | TgtPrompt$ Select target player or planeswalker | NumDmg$ 1 | Planeswalker$ True | SpellDescription$ CARDNAME deals 1 damage to target player or planeswalker. A:AB$ DealDamage | Cost$ AddCounter<1/LOYALTY> | ValidTgts$ Player,Planeswalker | TgtPrompt$ Select target player or planeswalker | NumDmg$ 1 | Planeswalker$ True | SpellDescription$ CARDNAME deals 1 damage to target player or planeswalker.
A:AB$ DealDamage | Cost$ SubCounter<X/LOYALTY> | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ ChosenX | Planeswalker$ True | References$ X | SpellDescription$ CARDNAME deals X damage to target creature. A:AB$ DealDamage | Cost$ SubCounter<X/LOYALTY> | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ X | Planeswalker$ True | References$ X | SpellDescription$ CARDNAME deals X damage to target creature.
A:AB$ DealDamage | Cost$ SubCounter<8/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Player,Planeswalker | TgtPrompt$ Select a player or planeswalker | NumDmg$ 10 | SubAbility$ DmgAll | DamageMap$ True | SpellDescription$ CARDNAME deals 10 damage to target player or planeswalker and each creature that player or that planeswalker's controller controls. A:AB$ DealDamage | Cost$ SubCounter<8/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Player,Planeswalker | TgtPrompt$ Select a player or planeswalker | NumDmg$ 10 | SubAbility$ DmgAll | DamageMap$ True | SpellDescription$ CARDNAME deals 10 damage to target player or planeswalker and each creature that player or that planeswalker's controller controls.
SVar:DmgAll:DB$ DamageAll | NumDmg$ 10 | ValidCards$ Creature.ControlledBy TargetedOrController | SubAbility$ DBDamageResolve SVar:DmgAll:DB$ DamageAll | NumDmg$ 10 | ValidCards$ Creature.ControlledBy TargetedOrController | SubAbility$ DBDamageResolve
SVar:DBDamageResolve:DB$ DamageResolve SVar:DBDamageResolve:DB$ DamageResolve
SVar:X:XChoice SVar:X:Count$xPaid
SVar:Picture:http://resources.wizards.com/magic/cards/lrw/en/card140176.jpg
Oracle:[+1]: Chandra Nalaar deals 1 damage to target player or planeswalker.\n[-X]: Chandra Nalaar deals X damage to target creature.\n[-8]: Chandra Nalaar deals 10 damage to target player or planeswalker and each creature that player or that planeswalker's controller controls. Oracle:[+1]: Chandra Nalaar deals 1 damage to target player or planeswalker.\n[-X]: Chandra Nalaar deals X damage to target creature.\n[-8]: Chandra Nalaar deals 10 damage to target player or planeswalker and each creature that player or that planeswalker's controller controls.

View File

@@ -1,7 +1,7 @@
Name:Channeled Force Name:Channeled Force
ManaCost:2 U R ManaCost:2 U R
Types:Instant Types:Instant
A:SP$ Draw | Cost$ 2 U R Discard<X/Card/card> | CostDesc$ As an additional cost to cast this spell, discard X cards. | NumCards$ ChosenX | ValidTgts$ Player | TgtPrompt$ Choose a player | References$ X | SubAbility$ DBDamage | SpellDescription$ Target player draws X cards. CARDNAME deals X damage to up to one target creature or planeswalker. A:SP$ Draw | Cost$ 2 U R Discard<X/Card/card> | CostDesc$ As an additional cost to cast this spell, discard X cards. | NumCards$ X | ValidTgts$ Player | TgtPrompt$ Choose a player | References$ X | SubAbility$ DBDamage | SpellDescription$ Target player draws X cards. CARDNAME deals X damage to up to one target creature or planeswalker.
SVar:DBDamage:DB$ DealDamage | ValidTgts$ Creature,Planeswalker | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select target creature or planeswalker. | NumDmg$ ChosenX | References$ X SVar:DBDamage:DB$ DealDamage | ValidTgts$ Creature,Planeswalker | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select target creature or planeswalker. | NumDmg$ X | References$ X
SVar:X:XChoice SVar:X:Count$xPaid
Oracle:As an additional cost to cast this spell, discard X cards.\nTarget player draws X cards. Channeled Force deals X damage to up to one target creature or planeswalker. Oracle:As an additional cost to cast this spell, discard X cards.\nTarget player draws X cards. Channeled Force deals X damage to up to one target creature or planeswalker.

View File

@@ -3,8 +3,7 @@ ManaCost:no cost
Types:Land Types:Land
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME. A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME.
A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ Combo W U B R G | Amount$ ChosenX | RestrictValid$ Card.Dragon,Activated.Dragon | CostDesc$ {T}, Remove X storage counters from CARDNAME: | References$ X | SpellDescription$ Add X mana in any combination of colors. Spend this mana only to cast Dragon spells or activate abilities of Dragons. A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ Combo W U B R G | Amount$ X | RestrictValid$ Card.Dragon,Activated.Dragon | CostDesc$ {T}, Remove X storage counters from CARDNAME: | References$ X | SpellDescription$ Add X mana in any combination of colors. Spend this mana only to cast Dragon spells or activate abilities of Dragons.
SVar:X:XChoice SVar:X:Count$xPaid
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/crucible_of_the_spirit_dragon.jpg
Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Crucible of the Spirit Dragon.\n{T}, Remove X storage counters from Crucible of the Spirit Dragon: Add X mana in any combination of colors. Spend this mana only to cast Dragon spells or activate abilities of Dragons. Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Crucible of the Spirit Dragon.\n{T}, Remove X storage counters from Crucible of the Spirit Dragon: Add X mana in any combination of colors. Spend this mana only to cast Dragon spells or activate abilities of Dragons.

View File

@@ -3,8 +3,7 @@ ManaCost:B
Types:Creature Human Assassin Types:Creature Human Assassin
PT:1/1 PT:1/1
A:AB$ PutCounter | Cost$ B T PayLife<1> | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | SpellDescription$ Put a +1/+1 counter on CARDNAME. A:AB$ PutCounter | Cost$ B T PayLife<1> | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | SpellDescription$ Put a +1/+1 counter on CARDNAME.
A:AB$ DealDamage | Cost$ 2 B T SubCounter<X/P1P1> | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ ChosenX | References$ X | SpellDescription$ CARDNAME deals X damage to target creature. A:AB$ DealDamage | Cost$ 2 B T SubCounter<X/P1P1> | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ X | References$ X | SpellDescription$ CARDNAME deals X damage to target creature.
SVar:X:XChoice SVar:X:Count$xPaid
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/cruel_sadist.jpg
Oracle:{B}, {T}, Pay 1 life: Put a +1/+1 counter on Cruel Sadist.\n{2}{B}, {T}, Remove X +1/+1 counters from Cruel Sadist: It deals X damage to target creature. Oracle:{B}, {T}, Pay 1 life: Put a +1/+1 counter on Cruel Sadist.\n{2}{B}, {T}, Remove X +1/+1 counters from Cruel Sadist: It deals X damage to target creature.

View File

@@ -2,10 +2,10 @@ Name:Dargo, the Shipwrecker
ManaCost:6 R ManaCost:6 R
Types:Legendary Creature Giant Pirate Types:Legendary Creature Giant Pirate
PT:7/5 PT:7/5
A:SP$ PermanentCreature | Announce$ X | Cost$ 6 R Sac<X/Artifact;Creature/artifacts or creatures> | AILogic$ SacToReduceCost | References$ X,Y | CostDesc$ As an additional cost to cast this spell, you may sacrifice any number of artifacts and/or creatures. | SpellDescription$ A:SP$ PermanentCreature | Cost$ 6 R Sac<X/Artifact;Creature/artifacts or creatures> | AILogic$ SacToReduceCost | References$ X,Y | CostDesc$ As an additional cost to cast this spell, you may sacrifice any number of artifacts and/or creatures. | SpellDescription$
S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ Y | EffectZone$ All | References$ Y | Description$ This spell costs {2} less to cast for each permanent sacrificed this way and {2} less to cast for each other artifact or creature you've sacrificed this turn. S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ Y | EffectZone$ All | References$ Y | Relative$ True | Description$ This spell costs {2} less to cast for each permanent sacrificed this way and {2} less to cast for each other artifact or creature you've sacrificed this turn.
S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ Z | EffectZone$ All | References$ Z | Secondary$ True | Description$ This spell costs {2} less to cast for each permanent sacrificed this way and {2} less to cast for each other artifact or creature you've sacrificed this turn. S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ Z | EffectZone$ All | References$ Z | Secondary$ True | Description$ This spell costs {2} less to cast for each permanent sacrificed this way and {2} less to cast for each other artifact or creature you've sacrificed this turn.
SVar:X:XChoice SVar:X:Count$xPaid
SVar:Y:SVar$X/Times.2 SVar:Y:SVar$X/Times.2
SVar:Z:Count$SacrificedThisTurn Artifact,Creature/Times.2 SVar:Z:Count$SacrificedThisTurn Artifact,Creature/Times.2
SVar:AIPreference:SacCost$Creature.token,Creature.cmcLE2 SVar:AIPreference:SacCost$Creature.token,Creature.cmcLE2

View File

@@ -3,8 +3,7 @@ ManaCost:no cost
Types:Land Types:Land
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME. A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME.
A:AB$ Mana | Cost$ 1 SubCounter<X/STORAGE> | Produced$ Combo U B | Amount$ ChosenX | CostDesc$ {1}, Remove X storage counters from CARDNAME: | References$ X | SpellDescription$ Add X mana in any combination of {U} and/or {B}. A:AB$ Mana | Cost$ 1 SubCounter<X/STORAGE> | Produced$ Combo U B | Amount$ X | CostDesc$ {1}, Remove X storage counters from CARDNAME: | References$ X | SpellDescription$ Add X mana in any combination of {U} and/or {B}.
SVar:X:XChoice SVar:X:Count$xPaid
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/dreadship_reef.jpg
Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Dreadship Reef.\n{1}, Remove X storage counters from Dreadship Reef: Add X mana in any combination of {U} and/or {B}. Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Dreadship Reef.\n{1}, Remove X storage counters from Dreadship Reef: Add X mana in any combination of {U} and/or {B}.

View File

@@ -5,9 +5,7 @@ K:CARDNAME enters the battlefield tapped.
K:You may choose not to untap CARDNAME during your untap step. K:You may choose not to untap CARDNAME during your untap step.
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | IsPresent$ Card.Self+tapped | Execute$ TrigStore | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is tapped, put a storage counter on it. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | IsPresent$ Card.Self+tapped | Execute$ TrigStore | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is tapped, put a storage counter on it.
SVar:TrigStore:DB$PutCounter | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 SVar:TrigStore:DB$PutCounter | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1
A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ R | Amount$ ChosenX | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | SpellDescription$ Add {R} for each storage counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ R | Amount$ X | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | SpellDescription$ Add {R} for each storage counter removed this way.
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/dwarven_hold.jpg
Oracle:Dwarven Hold enters the battlefield tapped.\nYou may choose not to untap Dwarven Hold during your untap step.\nAt the beginning of your upkeep, if Dwarven Hold is tapped, put a storage counter on it.\n{T}, Remove any number of storage counters from Dwarven Hold: Add {R} for each storage counter removed this way. Oracle:Dwarven Hold enters the battlefield tapped.\nYou may choose not to untap Dwarven Hold during your untap step.\nAt the beginning of your upkeep, if Dwarven Hold is tapped, put a storage counter on it.\n{T}, Remove any number of storage counters from Dwarven Hold: Add {R} for each storage counter removed this way.

View File

@@ -1,6 +1,7 @@
Name:Eliminate the Competition Name:Eliminate the Competition
ManaCost:4 B ManaCost:4 B
Types:Sorcery Types:Sorcery
A:SP$ Destroy | Announce$ X | Cost$ 4 B Sac<X/Creature/creature(s)> | CostDesc$ As an additional cost to cast this spell, sacrifice X creatures. | TargetMin$ X | TargetMax$ X | ValidTgts$ Creature | References$ X | TgtPrompt$ Select X target creatures | AIMaxTgtsCount$ Valid Creature.YouCtrl+cmcLE2 | SpellDescription$ Destroy X target creatures. A:SP$ Destroy | Cost$ 4 B Sac<X/Creature/creature(s)> | CostDesc$ As an additional cost to cast this spell, sacrifice X creatures. | TargetMin$ X | TargetMax$ X | ValidTgts$ Creature | References$ X | TgtPrompt$ Select X target creatures | AIMaxTgtsCount$ Valid Creature.YouCtrl+cmcLE2 | SpellDescription$ Destroy X target creatures.
SVar:X:Count$xPaid
SVar:AIPreference:SacCost$Creature.token,Creature.cmcLE2 SVar:AIPreference:SacCost$Creature.token,Creature.cmcLE2
Oracle:As an additional cost to cast this spell, sacrifice X creatures.\nDestroy X target creatures. Oracle:As an additional cost to cast this spell, sacrifice X creatures.\nDestroy X target creatures.

View File

@@ -2,11 +2,10 @@ Name:Emrakul's Evangel
ManaCost:2 G ManaCost:2 G
Types:Creature Human Horror Types:Creature Human Horror
PT:3/2 PT:3/2
A:AB$ Token | Cost$ T Sac<X/Creature.Other+nonEldrazi/other non-Eldrazi creatures> Sac<1/CARDNAME> | Announce$ X | TokenAmount$ Y | TokenScript$ c_3_2_eldrazi_horror | TokenOwner$ You | LegacyImage$ c 3 2 eldrazi horror emn | References$ Y | SpellDescription$ Create a 3/2 colorless Eldrazi Horror creature token for each creature sacrificed this way. | CostDesc$ {T}, Sacrifice CARDNAME and any number of other non-Eldrazi creatures: A:AB$ Token | Cost$ T Sac<X/Creature.Other+nonEldrazi/other non-Eldrazi creatures> Sac<1/CARDNAME> | TokenAmount$ Y | TokenScript$ c_3_2_eldrazi_horror | TokenOwner$ You | LegacyImage$ c 3 2 eldrazi horror emn | References$ Y | SpellDescription$ Create a 3/2 colorless Eldrazi Horror creature token for each creature sacrificed this way. | CostDesc$ {T}, Sacrifice CARDNAME and any number of other non-Eldrazi creatures:
SVar:Y:Sacrificed$Valid Creature SVar:Y:Sacrificed$Valid Creature
SVar:X:XChoice SVar:X:Count$xPaid
DeckHints:Ability$Token & Type$Eldrazi|Horror DeckHints:Ability$Token & Type$Eldrazi|Horror
DeckHas:Ability$Token DeckHas:Ability$Token & Ability$Sacrifice
SVar:AIPreference:SacCost$Creature.token SVar:AIPreference:SacCost$Creature.token
SVar:Picture:http://www.wizards.com/global/images/magic/general/emrakuls_evangel.jpg
Oracle:{T}, Sacrifice Emrakul's Evangel and any number of other non-Eldrazi creatures: Create a 3/2 colorless Eldrazi Horror creature token for each creature sacrificed this way. Oracle:{T}, Sacrifice Emrakul's Evangel and any number of other non-Eldrazi creatures: Create a 3/2 colorless Eldrazi Horror creature token for each creature sacrificed this way.

View File

@@ -3,8 +3,6 @@ ManaCost:no cost
Types:Land Types:Land
K:CARDNAME enters the battlefield tapped. K:CARDNAME enters the battlefield tapped.
A:AB$ PutCounter | Cost$ T | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME. A:AB$ PutCounter | Cost$ T | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME.
A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ W | Amount$ ChosenX | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | AINoRecursiveCheck$ True | SpellDescription$ Add {W} for each storage counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ W | Amount$ X | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | AINoRecursiveCheck$ True | SpellDescription$ Add {W} for each storage counter removed this way.
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
SVar:Picture:http://www.wizards.com/global/images/magic/general/fountain_of_cho.jpg
Oracle:Fountain of Cho enters the battlefield tapped.\n{T}: Put a storage counter on Fountain of Cho.\n{T}, Remove any number of storage counters from Fountain of Cho: Add {W} for each storage counter removed this way. Oracle:Fountain of Cho enters the battlefield tapped.\n{T}: Put a storage counter on Fountain of Cho.\n{T}, Remove any number of storage counters from Fountain of Cho: Add {W} for each storage counter removed this way.

View File

@@ -3,8 +3,7 @@ ManaCost:no cost
Types:Land Types:Land
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME. A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME.
A:AB$ Mana | Cost$ 1 SubCounter<X/STORAGE> | Produced$ Combo R G | Amount$ ChosenX | CostDesc$ {1}, Remove X storage counters from CARDNAME: | References$ X | SpellDescription$ Add X mana in any combination of {R} and/or {G}. A:AB$ Mana | Cost$ 1 SubCounter<X/STORAGE> | Produced$ Combo R G | Amount$ X | CostDesc$ {1}, Remove X storage counters from CARDNAME: | References$ X | SpellDescription$ Add X mana in any combination of {R} and/or {G}.
SVar:X:XChoice SVar:X:Count$xPaid
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/fungal_reaches.jpg
Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Fungal Reaches.\n{1}, Remove X storage counters from Fungal Reaches: Add X mana in any combination of {R} and/or {G}. Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Fungal Reaches.\n{1}, Remove X storage counters from Fungal Reaches: Add X mana in any combination of {R} and/or {G}.

View File

@@ -3,9 +3,7 @@ ManaCost:4
Types:Artifact Types:Artifact
A:AB$ PutCounter | Cost$ 2 T | CounterType$ CHARGE | CounterNum$ 1 | SpellDescription$ Put a charge counter on CARDNAME. A:AB$ PutCounter | Cost$ 2 T | CounterType$ CHARGE | CounterNum$ 1 | SpellDescription$ Put a charge counter on CARDNAME.
A:AB$ Mana | Cost$ T SubCounter<X/CHARGE> | Produced$ G | Amount$ Y | CostDesc$ {T}, Remove any number of charge counters from CARDNAME: | References$ X,Y | AILogic$ ManaRitualBattery.1 | AINoRecursiveCheck$ True | SpellDescription$ Add {G}, then add an additional {G} for each charge counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/CHARGE> | Produced$ G | Amount$ Y | CostDesc$ {T}, Remove any number of charge counters from CARDNAME: | References$ X,Y | AILogic$ ManaRitualBattery.1 | AINoRecursiveCheck$ True | SpellDescription$ Add {G}, then add an additional {G} for each charge counter removed this way.
SVar:Y:Number$1/Plus.ChosenX SVar:Y:SVar$X/Plus.1
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/green_mana_battery.jpg
Oracle:{2}, {T}: Put a charge counter on Green Mana Battery.\n{T}, Remove any number of charge counters from Green Mana Battery: Add {G}, then add an additional {G} for each charge counter removed this way. Oracle:{2}, {T}: Put a charge counter on Green Mana Battery.\n{T}, Remove any number of charge counters from Green Mana Battery: Add {G}, then add an additional {G} for each charge counter removed this way.

View File

@@ -5,9 +5,7 @@ K:CARDNAME enters the battlefield tapped.
K:You may choose not to untap CARDNAME during your untap step. K:You may choose not to untap CARDNAME during your untap step.
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | IsPresent$ Card.Self+tapped | Execute$ TrigStore | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is tapped, put a storage counter on it. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | IsPresent$ Card.Self+tapped | Execute$ TrigStore | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is tapped, put a storage counter on it.
SVar:TrigStore:DB$PutCounter | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 SVar:TrigStore:DB$PutCounter | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1
A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ G | Amount$ ChosenX | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | SpellDescription$ Add {G} for each storage counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ G | Amount$ X | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | SpellDescription$ Add {G} for each storage counter removed this way.
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/hollow_trees.jpg
Oracle:Hollow Trees enters the battlefield tapped.\nYou may choose not to untap Hollow Trees during your untap step.\nAt the beginning of your upkeep, if Hollow Trees is tapped, put a storage counter on it.\n{T}, Remove any number of storage counters from Hollow Trees: Add {G} for each storage counter removed this way. Oracle:Hollow Trees enters the battlefield tapped.\nYou may choose not to untap Hollow Trees during your untap step.\nAt the beginning of your upkeep, if Hollow Trees is tapped, put a storage counter on it.\n{T}, Remove any number of storage counters from Hollow Trees: Add {G} for each storage counter removed this way.

View File

@@ -5,9 +5,7 @@ K:CARDNAME enters the battlefield tapped.
K:You may choose not to untap CARDNAME during your untap step. K:You may choose not to untap CARDNAME during your untap step.
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | IsPresent$ Card.Self+tapped | Execute$ TrigStore | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is tapped, put a storage counter on it. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | IsPresent$ Card.Self+tapped | Execute$ TrigStore | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is tapped, put a storage counter on it.
SVar:TrigStore:DB$PutCounter | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 SVar:TrigStore:DB$PutCounter | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1
A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ W | Amount$ ChosenX | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | SpellDescription$ Add {W} for each storage counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ W | Amount$ X | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | SpellDescription$ Add {W} for each storage counter removed this way.
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/icatian_store.jpg
Oracle:Icatian Store enters the battlefield tapped.\nYou may choose not to untap Icatian Store during your untap step.\nAt the beginning of your upkeep, if Icatian Store is tapped, put a storage counter on it.\n{T}, Remove any number of storage counters from Icatian Store: Add {W} for each storage counter removed this way. Oracle:Icatian Store enters the battlefield tapped.\nYou may choose not to untap Icatian Store during your untap step.\nAt the beginning of your upkeep, if Icatian Store is tapped, put a storage counter on it.\n{T}, Remove any number of storage counters from Icatian Store: Add {W} for each storage counter removed this way.

View File

@@ -2,12 +2,10 @@ Name:Infused Arrows
ManaCost:4 ManaCost:4
Types:Artifact Types:Artifact
K:Sunburst K:Sunburst
#ChosenX SVar created by Cost payment A:AB$ Pump | Cost$ T SubCounter<X/CHARGE> | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ -X | NumDef$ -X | References$ X | SpellDescription$ Target creature gets -X/-X until end of turn.
A:AB$ Pump | Cost$ T SubCounter<X/CHARGE> | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ -ChosenX | NumDef$ -ChosenX | References$ X | SpellDescription$ Target creature gets -X/-X until end of turn. SVar:X:Count$xPaid
SVar:X:XChoice
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:NeedsToPlayVar:Z GE1 SVar:NeedsToPlayVar:Z GE1
SVar:Z:Count$UniqueManaColorsProduced.ByUntappedSources SVar:Z:Count$UniqueManaColorsProduced.ByUntappedSources
DeckHints:Ability$Proliferate DeckHints:Ability$Proliferate
SVar:Picture:http://www.wizards.com/global/images/magic/general/infused_arrows.jpg
Oracle:Sunburst (This enters the battlefield with a charge counter on it for each color of mana spent to cast it.)\n{T}, Remove X charge counters from Infused Arrows: Target creature gets -X/-X until end of turn. Oracle:Sunburst (This enters the battlefield with a charge counter on it for each color of mana spent to cast it.)\n{T}, Remove X charge counters from Infused Arrows: Target creature gets -X/-X until end of turn.

View File

@@ -8,8 +8,8 @@ A:AB$ Effect | Cost$ AddCounter<0/LOYALTY> | Planeswalker$ True | Duration$ Unti
SVar:TripleCombatDamage:Event$ DamageDone | ValidSource$ Creature.IsRemembered | CombatDamage$ True | ValidTarget$ Player.Opponent | ReplaceWith$ DmgTriple | Description$ Choose target creature. Until your next turn, if that creature would deal combat damage to one of your opponents, it deals triple that damage to that player instead. SVar:TripleCombatDamage:Event$ DamageDone | ValidSource$ Creature.IsRemembered | CombatDamage$ True | ValidTarget$ Player.Opponent | ReplaceWith$ DmgTriple | Description$ Choose target creature. Until your next turn, if that creature would deal combat damage to one of your opponents, it deals triple that damage to that player instead.
SVar:DmgTriple:DB$ ReplaceEffect | VarName$ DamageAmount | VarValue$ Z | References$ Z SVar:DmgTriple:DB$ ReplaceEffect | VarName$ DamageAmount | VarValue$ Z | References$ Z
SVar:Z:ReplaceCount$DamageAmount/Thrice SVar:Z:ReplaceCount$DamageAmount/Thrice
A:AB$ DealDamage | Cost$ SubCounter<X/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Choose up to three targets | TargetMin$ 0 | TargetMax$ 3 | NumDmg$ ChosenX | References$ X | SpellDescription$ CARDNAME deals X damage to each of up to three targets. A:AB$ DealDamage | Cost$ SubCounter<X/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Choose up to three targets | TargetMin$ 0 | TargetMax$ 3 | NumDmg$ X | References$ X | SpellDescription$ CARDNAME deals X damage to each of up to three targets.
SVar:X:XChoice SVar:X:Count$xPaid
AI:RemoveDeck:NonCommander AI:RemoveDeck:NonCommander
Text:CARDNAME can be your commander. Text:CARDNAME can be your commander.
K:Partner K:Partner

View File

@@ -5,10 +5,9 @@ PT:3/3
K:Partner:Regna, the Redeemer:Regna K:Partner:Regna, the Redeemer:Regna
# TODO: AILogic$ DoSacrifice is a placeholder which signals AiCostDecision that the API knows how to properly determine # TODO: AILogic$ DoSacrifice is a placeholder which signals AiCostDecision that the API knows how to properly determine
# the number of creatures to sacrifice. Currently DrawAi doesn't handle it too optimally and this can be improved. # the number of creatures to sacrifice. Currently DrawAi doesn't handle it too optimally and this can be improved.
A:AB$Draw | Cost$ B Sac<X/Creature/creatures> | NumCards$ ChosenX | ValidTgts$ Player | TgtPrompt$ Choose a player | References$ X | SubAbility$ DBGainLife | AILogic$ DoSacrifice | SpellDescription$ Target player draws X cards and gains X life. Put X +1/+1 counters on CARDNAME. A:AB$ Draw | Cost$ B Sac<X/Creature/creatures> | NumCards$ X | ValidTgts$ Player | TgtPrompt$ Choose a player | References$ X | SubAbility$ DBGainLife | AILogic$ DoSacrifice | SpellDescription$ Target player draws X cards and gains X life. Put X +1/+1 counters on CARDNAME.
SVar:DBGainLife:DB$GainLife | Defined$ Targeted | LifeAmount$ ChosenX | SubAbility$ DBPutCounter SVar:DBGainLife:DB$ GainLife | Defined$ Targeted | LifeAmount$ X | SubAbility$ DBPutCounter | References$ X
SVar:DBPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ ChosenX SVar:DBPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ X | References$ X
SVar:X:XChoice SVar:X:Count$xPaid
DeckHints:Name$Regna, the Redeemer DeckHints:Name$Regna, the Redeemer
SVar:Picture:http://www.wizards.com/global/images/magic/general/krav_the_unredeemed.jpg
Oracle:Partner with Regna, the Redeemer (When this creature enters the battlefield, target player may put Regna into their hand from their library, then shuffle.)\n{B}, Sacrifice X creatures: Target player draws X cards and gains X life. Put X +1/+1 counters on Krav, the Unredeemed. Oracle:Partner with Regna, the Redeemer (When this creature enters the battlefield, target player may put Regna into their hand from their library, then shuffle.)\n{B}, Sacrifice X creatures: Target player draws X cards and gains X life. Put X +1/+1 counters on Krav, the Unredeemed.

View File

@@ -3,7 +3,6 @@ ManaCost:no cost
Types:Land Types:Land
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME. A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME.
A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ C | Amount$ ChosenX | CostDesc$ {T}, Remove X storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | AINoRecursiveCheck$ True | SpellDescription$ Add {C} equal to the amount of counters removed. A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ C | Amount$ X | CostDesc$ {T}, Remove X storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | AINoRecursiveCheck$ True | SpellDescription$ Add {C} equal to the amount of counters removed.
SVar:X:XChoice SVar:X:Count$xPaid
SVar:Picture:http://www.wizards.com/global/images/magic/general/mage_ring_network.jpg
Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Mage-Ring Network.\n{T}, Remove X storage counters from Mage-Ring Network: Add {C} equal to the amount of counters removed. Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Mage-Ring Network.\n{T}, Remove X storage counters from Mage-Ring Network: Add {C} equal to the amount of counters removed.

View File

@@ -4,11 +4,10 @@ Types:Legendary Creature Elemental Beast
PT:0/0 PT:0/0
K:etbCounter:P1P1:Y:no Condition:CARDNAME enters the battlefield with a number of +1/+1 counters on it equal to the amount of mana spent to cast it. K:etbCounter:P1P1:Y:no Condition:CARDNAME enters the battlefield with a number of +1/+1 counters on it equal to the amount of mana spent to cast it.
SVar:Y:Count$CastTotalManaSpent SVar:Y:Count$CastTotalManaSpent
A:AB$ Charm | Cost$ X SubCounter<X/P1P1> | Announce$ X | XCantBe0$ True | Choices$ MarathCounters,MarathDmg,MarathToken | Defined$ You A:AB$ Charm | Cost$ XCantBe0 X SubCounter<X/P1P1> | Announce$ X | Choices$ MarathCounters,MarathDmg,MarathToken | Defined$ You
SVar:MarathCounters:DB$ PutCounter | ValidTgts$ Creature | CounterType$ P1P1 | CounterNum$ Z | References$ Z | SpellDescription$ Put X +1/+1 counters on target creature. X can't be 0. SVar:MarathCounters:DB$ PutCounter | ValidTgts$ Creature | CounterType$ P1P1 | CounterNum$ Z | References$ Z | SpellDescription$ Put X +1/+1 counters on target creature. X can't be 0.
SVar:MarathDmg:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ Z | References$ Z | SpellDescription$ CARDNAME deals X damage to any target. X can't be 0. SVar:MarathDmg:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ Z | References$ Z | SpellDescription$ CARDNAME deals X damage to any target. X can't be 0.
SVar:MarathToken:DB$ Token | TokenAmount$ 1 | TokenScript$ g_x_x_elemental | TokenOwner$ You | TokenPower$ Z | TokenToughness$ Z | References$ Z | LegacyImage$ g x x elemental c13 | SpellDescription$ Create an X/X green Elemental creature token. X can't be 0. SVar:MarathToken:DB$ Token | TokenAmount$ 1 | TokenScript$ g_x_x_elemental | TokenOwner$ You | TokenPower$ Z | TokenToughness$ Z | References$ Z | LegacyImage$ g x x elemental c13 | SpellDescription$ Create an X/X green Elemental creature token. X can't be 0.
SVar:Z:SVar$CostCountersRemoved SVar:Z:SVar$CostCountersRemoved
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/marath_will_of_the_wild.jpg
Oracle:Marath, Will of the Wild enters the battlefield with a number of +1/+1 counters on it equal to the amount of mana spent to cast it.\n{X}, Remove X +1/+1 counters from Marath: Choose one —\n• Put X +1/+1 counters on target creature. X can't be 0.\n• Marath deals X damage to any target. X can't be 0.\n• Create an X/X green Elemental creature token. X can't be 0. Oracle:Marath, Will of the Wild enters the battlefield with a number of +1/+1 counters on it equal to the amount of mana spent to cast it.\n{X}, Remove X +1/+1 counters from Marath: Choose one —\n• Put X +1/+1 counters on target creature. X can't be 0.\n• Marath deals X damage to any target. X can't be 0.\n• Create an X/X green Elemental creature token. X can't be 0.

View File

@@ -3,8 +3,6 @@ ManaCost:no cost
Types:Land Types:Land
K:CARDNAME enters the battlefield tapped. K:CARDNAME enters the battlefield tapped.
A:AB$ PutCounter | Cost$ T | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME. A:AB$ PutCounter | Cost$ T | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME.
A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ R | Amount$ ChosenX | References$ X | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | AILogic$ ManaRitualBattery | AINoRecursiveCheck$ True | SpellDescription$ Add {R} for each storage counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ R | Amount$ X | References$ X | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | AILogic$ ManaRitualBattery | AINoRecursiveCheck$ True | SpellDescription$ Add {R} for each storage counter removed this way.
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
SVar:Picture:http://www.wizards.com/global/images/magic/general/mercadian_bazaar.jpg
Oracle:Mercadian Bazaar enters the battlefield tapped.\n{T}: Put a storage counter on Mercadian Bazaar.\n{T}, Remove any number of storage counters from Mercadian Bazaar: Add {R} for each storage counter removed this way. Oracle:Mercadian Bazaar enters the battlefield tapped.\n{T}: Put a storage counter on Mercadian Bazaar.\n{T}, Remove any number of storage counters from Mercadian Bazaar: Add {R} for each storage counter removed this way.

View File

@@ -2,8 +2,7 @@ Name:Mercadian Lift
ManaCost:2 ManaCost:2
Types:Artifact Types:Artifact
A:AB$ PutCounter | Cost$ 1 T | CounterType$ WINCH | CounterNum$ 1 | SpellDescription$ Put a winch counter on CARDNAME. A:AB$ PutCounter | Cost$ 1 T | CounterType$ WINCH | CounterNum$ 1 | SpellDescription$ Put a winch counter on CARDNAME.
A:AB$ ChangeZone | Cost$ T SubCounter<X/WINCH> | ChangeNum$ 1 | ChangeType$ Creature.cmcEQChosenX | Origin$ Hand | Destination$ Battlefield | References$ X | Optional$ True | SpellDescription$ You may put a creature card with converted mana cost X from your hand onto the battlefield. A:AB$ ChangeZone | Cost$ T SubCounter<X/WINCH> | ChangeNum$ 1 | ChangeType$ Creature.cmcEQX | Origin$ Hand | Destination$ Battlefield | References$ X | Optional$ True | SpellDescription$ You may put a creature card with converted mana cost X from your hand onto the battlefield.
SVar:X:XChoice SVar:X:Count$xPaid
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/mercadian_lift.jpg
Oracle:{1}, {T}: Put a winch counter on Mercadian Lift.\n{T}, Remove X winch counters from Mercadian Lift: You may put a creature card with converted mana cost X from your hand onto the battlefield. Oracle:{1}, {T}: Put a winch counter on Mercadian Lift.\n{T}, Remove X winch counters from Mercadian Lift: You may put a creature card with converted mana cost X from your hand onto the battlefield.

View File

@@ -3,8 +3,7 @@ ManaCost:no cost
Types:Land Types:Land
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME. A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME.
A:AB$ Mana | Cost$ 1 SubCounter<X/STORAGE> | Produced$ Combo B R | Amount$ ChosenX | CostDesc$ {1}, Remove X storage counters from CARDNAME: | References$ X | SpellDescription$ Add X mana in any combination of {B} and/or {R}. A:AB$ Mana | Cost$ 1 SubCounter<X/STORAGE> | Produced$ Combo B R | Amount$ X | CostDesc$ {1}, Remove X storage counters from CARDNAME: | References$ X | SpellDescription$ Add X mana in any combination of {B} and/or {R}.
SVar:X:XChoice SVar:X:Count$xPaid
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/molten_slagheap.jpg
Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Molten Slagheap.\n{1}, Remove X storage counters from Molten Slagheap: Add X mana in any combination of {B} and/or {R}. Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Molten Slagheap.\n{1}, Remove X storage counters from Molten Slagheap: Add X mana in any combination of {B} and/or {R}.

View File

@@ -4,6 +4,6 @@ Types:Legendary Planeswalker Nahiri
Loyalty:6 Loyalty:6
S:Mode$ Continuous | Affected$ Creature.YouCtrl | EffectZone$ Battlefield | AddKeyword$ First Strike | Condition$ PlayerTurn | Description$ As long as it's your turn, creatures you control have first strike and equip abilities you activate cost {1} less to activate. S:Mode$ Continuous | Affected$ Creature.YouCtrl | EffectZone$ Battlefield | AddKeyword$ First Strike | Condition$ PlayerTurn | Description$ As long as it's your turn, creatures you control have first strike and equip abilities you activate cost {1} less to activate.
S:Mode$ ReduceCost | ValidCard$ Card | ValidSpell$ Activated.Equip | Activator$ You | Amount$ 1 | Condition$ PlayerTurn | Secondary$ True | Description$ Equip abilities you activate cost {1} less to activate. S:Mode$ ReduceCost | ValidCard$ Card | ValidSpell$ Activated.Equip | Activator$ You | Amount$ 1 | Condition$ PlayerTurn | Secondary$ True | Description$ Equip abilities you activate cost {1} less to activate.
A:AB$ DealDamage | Cost$ SubCounter<X/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature.tapped | TgtPrompt$ Select target tapped creature | NumDmg$ ChosenX | References$ X | SpellDescription$ CARDNAME deals X damage to target tapped creature. A:AB$ DealDamage | Cost$ SubCounter<X/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature.tapped | TgtPrompt$ Select target tapped creature | NumDmg$ X | References$ X | SpellDescription$ CARDNAME deals X damage to target tapped creature.
SVar:X:XChoice SVar:X:Count$xPaid
Oracle:As long as it's your turn, creatures you control have first strike and equip abilities you activate cost {1} less to activate.\n-X: Nahiri, Storm of Stone deals X damage to target tapped creature. Oracle:As long as it's your turn, creatures you control have first strike and equip abilities you activate cost {1} less to activate.\n-X: Nahiri, Storm of Stone deals X damage to target tapped creature.

View File

@@ -3,9 +3,8 @@ ManaCost:2 B B
Types:Enchantment Types:Enchantment
T:Mode$ DamageDone | ValidSource$ Card.YouCtrl,Emblem.YouCtrl | ValidTarget$ Player.Other | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever a source you control deals damage to another player, put that many theft counters on CARDNAME. T:Mode$ DamageDone | ValidSource$ Card.YouCtrl,Emblem.YouCtrl | ValidTarget$ Player.Other | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever a source you control deals damage to another player, put that many theft counters on CARDNAME.
SVar:TrigPutCounter:DB$ PutCounter | CounterType$ THEFT | CounterNum$ Y | References$ Y SVar:TrigPutCounter:DB$ PutCounter | CounterType$ THEFT | CounterNum$ Y | References$ Y
A:AB$ ChangeZone | Cost$ 2 B B SubCounter<X/THEFT> | Origin$ Library | Destination$ Hand | ChangeType$ Card.nonLand+YouCtrl+cmcEQChosenX | ChangeNum$ 1 | Reveal$ True | Shuffle$ True | References$ X | SpellDescription$ Search your library for a nonland card with converted mana cost X, reveal it, put it into your hand, then shuffle your library. A:AB$ ChangeZone | Cost$ 2 B B SubCounter<X/THEFT> | Origin$ Library | Destination$ Hand | ChangeType$ Card.nonLand+YouCtrl+cmcEQX | ChangeNum$ 1 | Reveal$ True | Shuffle$ True | References$ X | SpellDescription$ Search your library for a nonland card with converted mana cost X, reveal it, put it into your hand, then shuffle your library.
SVar:X:XChoice SVar:X:Count$xPaid
SVar:Y:TriggerCount$DamageAmount SVar:Y:TriggerCount$DamageAmount
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/night_dealings.jpg
Oracle:Whenever a source you control deals damage to another player, put that many theft counters on Night Dealings.\n{2}{B}{B}, Remove X theft counters from Night Dealings: Search your library for a nonland card with converted mana cost X, reveal it, put it into your hand, then shuffle your library. Oracle:Whenever a source you control deals damage to another player, put that many theft counters on Night Dealings.\n{2}{B}{B}, Remove X theft counters from Night Dealings: Search your library for a nonland card with converted mana cost X, reveal it, put it into your hand, then shuffle your library.

View File

@@ -3,9 +3,7 @@ ManaCost:4
Types:Artifact Types:Artifact
A:AB$ PutCounter | Cost$ 2 T | CounterType$ CHARGE | CounterNum$ 1 | SpellDescription$ Put a charge counter on CARDNAME. A:AB$ PutCounter | Cost$ 2 T | CounterType$ CHARGE | CounterNum$ 1 | SpellDescription$ Put a charge counter on CARDNAME.
A:AB$ Mana | Cost$ T SubCounter<X/CHARGE> | Produced$ R | Amount$ Y | References$ X,Y | CostDesc$ {T}, Remove any number of charge counters from CARDNAME: | AILogic$ ManaRitualBattery.1 | AINoRecursiveCheck$ True | SpellDescription$ Add {R}, then add an additional {R} for each charge counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/CHARGE> | Produced$ R | Amount$ Y | References$ X,Y | CostDesc$ {T}, Remove any number of charge counters from CARDNAME: | AILogic$ ManaRitualBattery.1 | AINoRecursiveCheck$ True | SpellDescription$ Add {R}, then add an additional {R} for each charge counter removed this way.
SVar:Y:Number$1/Plus.ChosenX SVar:Y:SVar$X/Plus.1
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/red_mana_battery.jpg
Oracle:{2}, {T}: Put a charge counter on Red Mana Battery.\n{T}, Remove any number of charge counters from Red Mana Battery: Add {R}, then add an additional {R} for each charge counter removed this way. Oracle:{2}, {T}: Put a charge counter on Red Mana Battery.\n{T}, Remove any number of charge counters from Red Mana Battery: Add {R}, then add an additional {R} for each charge counter removed this way.

View File

@@ -3,8 +3,6 @@ ManaCost:no cost
Types:Land Types:Land
K:CARDNAME enters the battlefield tapped. K:CARDNAME enters the battlefield tapped.
A:AB$ PutCounter | Cost$ T | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME. A:AB$ PutCounter | Cost$ T | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME.
A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ G | Amount$ ChosenX | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | AINoRecursiveCheck$ True | SpellDescription$ Add {G} for each storage counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ G | Amount$ X | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | AINoRecursiveCheck$ True | SpellDescription$ Add {G} for each storage counter removed this way.
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
SVar:Picture:http://www.wizards.com/global/images/magic/general/rushwood_grove.jpg
Oracle:Rushwood Grove enters the battlefield tapped.\n{T}: Put a storage counter on Rushwood Grove.\n{T}, Remove any number of storage counters from Rushwood Grove: Add {G} for each storage counter removed this way. Oracle:Rushwood Grove enters the battlefield tapped.\n{T}: Put a storage counter on Rushwood Grove.\n{T}, Remove any number of storage counters from Rushwood Grove: Add {G} for each storage counter removed this way.

View File

@@ -3,8 +3,7 @@ ManaCost:no cost
Types:Land Types:Land
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME. A:AB$ PutCounter | Cost$ 1 T | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME.
A:AB$ Mana | Cost$ 1 SubCounter<X/STORAGE> | Produced$ Combo G W | Amount$ ChosenX | CostDesc$ {1}, Remove X storage counters from CARDNAME: | References$ X | SpellDescription$ Add X mana in any combination of {G} and/or {W}. A:AB$ Mana | Cost$ 1 SubCounter<X/STORAGE> | Produced$ Combo G W | Amount$ X | CostDesc$ {1}, Remove X storage counters from CARDNAME: | References$ X | SpellDescription$ Add X mana in any combination of {G} and/or {W}.
SVar:X:XChoice SVar:X:Count$xPaid
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/saltcrusted_steppe.jpg
Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Saltcrusted Steppe.\n{1}, Remove X storage counters from Saltcrusted Steppe: Add X mana in any combination of {G} and/or {W}. Oracle:{T}: Add {C}.\n{1}, {T}: Put a storage counter on Saltcrusted Steppe.\n{1}, Remove X storage counters from Saltcrusted Steppe: Add X mana in any combination of {G} and/or {W}.

View File

@@ -5,9 +5,7 @@ K:CARDNAME enters the battlefield tapped.
K:You may choose not to untap CARDNAME during your untap step. K:You may choose not to untap CARDNAME during your untap step.
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | IsPresent$ Card.Self+tapped | Execute$ TrigStore | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is tapped, put a storage counter on it. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | IsPresent$ Card.Self+tapped | Execute$ TrigStore | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is tapped, put a storage counter on it.
SVar:TrigStore:DB$PutCounter | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 SVar:TrigStore:DB$PutCounter | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1
A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ U | Amount$ ChosenX | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | SpellDescription$ Add {U} for each storage counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ U | Amount$ X | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | SpellDescription$ Add {U} for each storage counter removed this way.
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/sand_silos.jpg
Oracle:Sand Silos enters the battlefield tapped.\nYou may choose not to untap Sand Silos during your untap step.\nAt the beginning of your upkeep, if Sand Silos is tapped, put a storage counter on it.\n{T}, Remove any number of storage counters from Sand Silos: Add {U} for each storage counter removed this way. Oracle:Sand Silos enters the battlefield tapped.\nYou may choose not to untap Sand Silos during your untap step.\nAt the beginning of your upkeep, if Sand Silos is tapped, put a storage counter on it.\n{T}, Remove any number of storage counters from Sand Silos: Add {U} for each storage counter removed this way.

View File

@@ -3,8 +3,6 @@ ManaCost:no cost
Types:Land Types:Land
K:CARDNAME enters the battlefield tapped. K:CARDNAME enters the battlefield tapped.
A:AB$ PutCounter | Cost$ T | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME. A:AB$ PutCounter | Cost$ T | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME.
A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ U | Amount$ ChosenX | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | AINoRecursiveCheck$ True | SpellDescription$ Add {U} for each storage counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ U | Amount$ X | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | AINoRecursiveCheck$ True | SpellDescription$ Add {U} for each storage counter removed this way.
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
SVar:Picture:http://www.wizards.com/global/images/magic/general/saprazzan_cove.jpg
Oracle:Saprazzan Cove enters the battlefield tapped.\n{T}: Put a storage counter on Saprazzan Cove.\n{T}, Remove any number of storage counters from Saprazzan Cove: Add {U} for each storage counter removed this way. Oracle:Saprazzan Cove enters the battlefield tapped.\n{T}: Put a storage counter on Saprazzan Cove.\n{T}, Remove any number of storage counters from Saprazzan Cove: Add {U} for each storage counter removed this way.

View File

@@ -3,10 +3,9 @@ ManaCost:1 U U
Types:Creature Mutant Wizard Types:Creature Mutant Wizard
PT:0/1 PT:0/1
K:Evolve K:Evolve
A:AB$ GainControl | Announce$ X | XCantBe0$ True | Cost$ T SubCounter<X/P1P1> | ValidTgts$ Creature.powerLEX | TgtPrompt$ Select target with power less than or equal to the number of +1/+1 counters removed this way | SpellDescription$ Gain control of target creature with power less than or equal to the number of +1/+1 counters removed this way. A:AB$ GainControl | Cost$ XCantBe0 T SubCounter<X/P1P1> | ValidTgts$ Creature.powerLEX | TgtPrompt$ Select target with power less than or equal to the number of +1/+1 counters removed this way | SpellDescription$ Gain control of target creature with power less than or equal to the number of +1/+1 counters removed this way.
SVar:X:Count$xPaid SVar:X:Count$xPaid
AI:RemoveDeck:All AI:RemoveDeck:All
DeckHas:Ability$Counters DeckHas:Ability$Counters
DeckHints:Ability$Counters DeckHints:Ability$Counters
SVar:Picture:http://www.wizards.com/global/images/magic/general/simic_manipulator.jpg
Oracle:Evolve (Whenever a creature enters the battlefield under your control, if that creature has greater power or toughness than this creature, put a +1/+1 counter on this creature.)\n{T}, Remove one or more +1/+1 counters from Simic Manipulator: Gain control of target creature with power less than or equal to the number of +1/+1 counters removed this way. Oracle:Evolve (Whenever a creature enters the battlefield under your control, if that creature has greater power or toughness than this creature, put a +1/+1 counter on this creature.)\n{T}, Remove one or more +1/+1 counters from Simic Manipulator: Gain control of target creature with power less than or equal to the number of +1/+1 counters removed this way.

View File

@@ -6,10 +6,9 @@ A:AB$ Dig | Cost$ AddCounter<1/LOYALTY> | DigNum$ 1 | Reveal$ True | ChangeNum$
SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ Y | Defined$ Opponent | SubAbility$ DBCleanup | References$ Y SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ Y | Defined$ Opponent | SubAbility$ DBCleanup | References$ Y
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:Y:Remembered$CardManaCost SVar:Y:Remembered$CardManaCost
A:AB$ DealDamage | Cost$ SubCounter<X/LOYALTY> | ValidTgts$ Creature,Planeswalker | TgtPrompt$ Select target creature or planeswalker | NumDmg$ ChosenX | Planeswalker$ True | SubAbility$ DBGainLife | References$ X,ChosenX | SpellDescription$ CARDNAME deals X damage to target creature or planeswalker and you gain X life. A:AB$ DealDamage | Cost$ SubCounter<X/LOYALTY> | ValidTgts$ Creature,Planeswalker | TgtPrompt$ Select target creature or planeswalker | NumDmg$ X | Planeswalker$ True | SubAbility$ DBGainLife | References$ X | SpellDescription$ CARDNAME deals X damage to target creature or planeswalker and you gain X life.
SVar:DBGainLife:DB$GainLife | LifeAmount$ ChosenX | Defined$ You | References$ ChosenX SVar:DBGainLife:DB$GainLife | LifeAmount$ X | Defined$ You | References$ X
SVar:X:XChoice SVar:X:Count$xPaid
A:AB$ Token | Cost$ SubCounter<9/LOYALTY> | Planeswalker$ True | TokenAmount$ Z | References$ Z | TokenScript$ b_1_1_vampire_knight_lifelink | TokenOwner$ You | LegacyImage$ b 1 1 vampire knight lifelink soi | Ultimate$ True | SpellDescription$ Create a number of 1/1 black Vampire Knight creature tokens with lifelink equal to the highest life total among all players. A:AB$ Token | Cost$ SubCounter<9/LOYALTY> | Planeswalker$ True | TokenAmount$ Z | References$ Z | TokenScript$ b_1_1_vampire_knight_lifelink | TokenOwner$ You | LegacyImage$ b 1 1 vampire knight lifelink soi | Ultimate$ True | SpellDescription$ Create a number of 1/1 black Vampire Knight creature tokens with lifelink equal to the highest life total among all players.
SVar:Z:PlayerCountPlayers$HighestLifeTotal SVar:Z:PlayerCountPlayers$HighestLifeTotal
SVar:Picture:http://www.wizards.com/global/images/magic/general/sorin_grim_nemesis.jpg
Oracle:[+1]: Reveal the top card of your library and put that card into your hand. Each opponent loses life equal to its converted mana cost.\n[-X]: Sorin, Grim Nemesis deals X damage to target creature or planeswalker and you gain X life.\n[-9]: Create a number of 1/1 black Vampire Knight creature tokens with lifelink equal to the highest life total among all players. Oracle:[+1]: Reveal the top card of your library and put that card into your hand. Each opponent loses life equal to its converted mana cost.\n[-X]: Sorin, Grim Nemesis deals X damage to target creature or planeswalker and you gain X life.\n[-9]: Create a number of 1/1 black Vampire Knight creature tokens with lifelink equal to the highest life total among all players.

View File

@@ -3,8 +3,6 @@ ManaCost:no cost
Types:Land Types:Land
K:CARDNAME enters the battlefield tapped. K:CARDNAME enters the battlefield tapped.
A:AB$ PutCounter | Cost$ T | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME. A:AB$ PutCounter | Cost$ T | Defined$ Self | CounterType$ STORAGE | CounterNum$ 1 | SpellDescription$ Put a storage counter on CARDNAME.
A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ B | Amount$ ChosenX | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | AINoRecursiveCheck$ True | SpellDescription$ Add {B} for each storage counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/STORAGE> | Produced$ B | Amount$ X | CostDesc$ {T}, Remove any number of storage counters from CARDNAME: | References$ X | AILogic$ ManaRitualBattery | AINoRecursiveCheck$ True | SpellDescription$ Add {B} for each storage counter removed this way.
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
SVar:Picture:http://www.wizards.com/global/images/magic/general/subterranean_hangar.jpg
Oracle:Subterranean Hangar enters the battlefield tapped.\n{T}: Put a storage counter on Subterranean Hangar.\n{T}, Remove any number of storage counters from Subterranean Hangar: Add {B} for each storage counter removed this way. Oracle:Subterranean Hangar enters the battlefield tapped.\n{T}: Put a storage counter on Subterranean Hangar.\n{T}, Remove any number of storage counters from Subterranean Hangar: Add {B} for each storage counter removed this way.

View File

@@ -5,10 +5,8 @@ PT:1/1
K:etbCounter:P1P1:3 K:etbCounter:P1P1:3
K:Flying K:Flying
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ At the beginning of your upkeep, you may remove any number of +1/+1 counters from CARDNAME. If you do, create that many 1/1 colorless Tetravite artifact creature tokens. They each have flying and "This creature can't be enchanted." T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ At the beginning of your upkeep, you may remove any number of +1/+1 counters from CARDNAME. If you do, create that many 1/1 colorless Tetravite artifact creature tokens. They each have flying and "This creature can't be enchanted."
SVar:TrigToken:AB$Token | Cost$ SubCounter<X/P1P1> | References$ X | TokenAmount$ ChosenX | LegacyImage$ c 1 1 tetravite flying noenchant atq | TokenScript$ c_1_1_a_tetravite_flying_noenchant | TokenOwner$ You | RememberTokens$ True | SubAbility$ DBClearXChoice SVar:TrigToken:AB$Token | Cost$ SubCounter<X/P1P1> | References$ X | TokenAmount$ X | LegacyImage$ c 1 1 tetravite flying noenchant atq | TokenScript$ c_1_1_a_tetravite_flying_noenchant | TokenOwner$ You | RememberTokens$ True
SVar:DBClearXChoice:DB$ Cleanup | ClearChosenX$ True SVar:X:Count$xPaid
SVar:X:XChoice
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounters | TriggerDescription$ At the beginning of your upkeep, you may exile any number of tokens created with CARDNAME. If you do, put that many +1/+1 counters on CARDNAME. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounters | TriggerDescription$ At the beginning of your upkeep, you may exile any number of tokens created with CARDNAME. If you do, put that many +1/+1 counters on CARDNAME.
SVar:TrigPutCounters:AB$PutCounter | Cost$ Exile<X/Creature.IsRemembered/Tetravite> | References$ X | Defined$ Self | CounterType$ P1P1 | CounterNum$ ChosenX | CostDesc$ Exile any number of tokens put onto the battlefield with CARDNAME. | SubAbility$ DBClearXChoice SVar:TrigPutCounters:AB$PutCounter | Cost$ Exile<X/Creature.IsRemembered/Tetravite> | References$ X | Defined$ Self | CounterType$ P1P1 | CounterNum$ X | CostDesc$ Exile any number of tokens put onto the battlefield with CARDNAME.
SVar:Picture:http://www.wizards.com/global/images/magic/general/tetravus.jpg
Oracle:Flying\nTetravus enters the battlefield with three +1/+1 counters on it.\nAt the beginning of your upkeep, you may remove any number of +1/+1 counters from Tetravus. If you do, create that many 1/1 colorless Tetravite artifact creature tokens. They each have flying and "This creature can't be enchanted."\nAt the beginning of your upkeep, you may exile any number of tokens created with Tetravus. If you do, put that many +1/+1 counters on Tetravus. Oracle:Flying\nTetravus enters the battlefield with three +1/+1 counters on it.\nAt the beginning of your upkeep, you may remove any number of +1/+1 counters from Tetravus. If you do, create that many 1/1 colorless Tetravite artifact creature tokens. They each have flying and "This creature can't be enchanted."\nAt the beginning of your upkeep, you may exile any number of tokens created with Tetravus. If you do, put that many +1/+1 counters on Tetravus.

View File

@@ -3,11 +3,9 @@ ManaCost:3 U U
Types:Legendary Planeswalker Tezzeret Types:Legendary Planeswalker Tezzeret
Loyalty:4 Loyalty:4
A:AB$ Untap | Cost$ AddCounter<1/LOYALTY> | ValidTgts$ Artifact | TgtPrompt$ Choose target artifact | TargetMin$ 0 | TargetMax$ 2 | Planeswalker$ True | SpellDescription$ Untap up to two target artifacts. A:AB$ Untap | Cost$ AddCounter<1/LOYALTY> | ValidTgts$ Artifact | TgtPrompt$ Choose target artifact | TargetMin$ 0 | TargetMax$ 2 | Planeswalker$ True | SpellDescription$ Untap up to two target artifacts.
A:AB$ ChangeZone | Cost$ SubCounter<X/LOYALTY> | Origin$ Library | Destination$ Battlefield | ChangeType$ Artifact.cmcLEChosenX | References$ X | ChangeNum$ 1 | Shuffle$ True | Planeswalker$ True | SpellDescription$ Search your library for an artifact card with converted mana cost X or less, put it onto the battlefield, then shuffle your library. A:AB$ ChangeZone | Cost$ SubCounter<X/LOYALTY> | Origin$ Library | Destination$ Battlefield | ChangeType$ Artifact.cmcLEX | References$ X | ChangeNum$ 1 | Shuffle$ True | Planeswalker$ True | SpellDescription$ Search your library for an artifact card with converted mana cost X or less, put it onto the battlefield, then shuffle your library.
A:AB$ AnimateAll | Cost$ SubCounter<5/LOYALTY> | Power$ 5 | Toughness$ 5 | Types$ Creature,Artifact | ValidCards$ Artifact.YouCtrl | Planeswalker$ True | Ultimate$ True | SpellDescription$ Artifacts you control become artifact creatures with base power and toughness 5/5 until end of turn. A:AB$ AnimateAll | Cost$ SubCounter<5/LOYALTY> | Power$ 5 | Toughness$ 5 | Types$ Creature,Artifact | ValidCards$ Artifact.YouCtrl | Planeswalker$ True | Ultimate$ True | SpellDescription$ Artifacts you control become artifact creatures with base power and toughness 5/5 until end of turn.
#ChosenX SVar created by Cost payment SVar:X:Count$xPaid
SVar:X:XChoice
AI:RemoveDeck:Random AI:RemoveDeck:Random
DeckNeeds:Type$Artifact DeckNeeds:Type$Artifact
SVar:Picture:http://www.wizards.com/global/images/magic/general/tezzeret_the_seeker.jpg
Oracle:[+1]: Untap up to two target artifacts.\n[-X]: Search your library for an artifact card with converted mana cost X or less, put it onto the battlefield, then shuffle your library.\n[-5]: Artifacts you control become artifact creatures with base power and toughness 5/5 until end of turn. Oracle:[+1]: Untap up to two target artifacts.\n[-X]: Search your library for an artifact card with converted mana cost X or less, put it onto the battlefield, then shuffle your library.\n[-5]: Artifacts you control become artifact creatures with base power and toughness 5/5 until end of turn.

View File

@@ -2,10 +2,11 @@ Name:Torgaar, Famine Incarnate
ManaCost:6 B B ManaCost:6 B B
Types:Legendary Creature Avatar Types:Legendary Creature Avatar
PT:7/6 PT:7/6
A:SP$ PermanentCreature | Cost$ 6 B B Sac<X/Creature> | Announce$ X | References$ X,Y | AILogic$ SacToReduceCost A:SP$ PermanentCreature | Cost$ 6 B B Sac<X/Creature> | References$ X,Y | AILogic$ SacToReduceCost
S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ Y | EffectZone$ All | References$ Y | Description$ As an additional cost to cast this spell, you may sacrifice any number of creatures. This spell costs {2} less to cast for each creature sacrificed as an additional cost. S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ Y | EffectZone$ All | References$ X,Y | Relative$ True | Description$ As an additional cost to cast this spell, you may sacrifice any number of creatures. This spell costs {2} less to cast for each creature sacrificed as an additional cost.
SVar:X:XChoice SVar:X:Count$xPaid
SVar:Y:SVar$X/Times.2 SVar:Y:SVar$X/Times.2
SVar:AIPreference:SacCost$Creature.token,Creature.cmcLE2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSetLife | TriggerDescription$ When CARDNAME enters the battlefield, up to one target player's life total becomes half their starting life total, rounded down. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSetLife | TriggerDescription$ When CARDNAME enters the battlefield, up to one target player's life total becomes half their starting life total, rounded down.
SVar:TrigSetLife:DB$ SetLife | ValidTgts$ Player | LifeAmount$ HalfLife | TargetMin$ 0 | TargetMax$ 1 | References$ HalfLife SVar:TrigSetLife:DB$ SetLife | ValidTgts$ Player | LifeAmount$ HalfLife | TargetMin$ 0 | TargetMax$ 1 | References$ HalfLife
SVar:HalfLife:TargetedPlayer$StartingLife/HalfDown SVar:HalfLife:TargetedPlayer$StartingLife/HalfDown

View File

@@ -3,10 +3,9 @@ ManaCost:8
Types:Legendary Planeswalker Ugin Types:Legendary Planeswalker Ugin
Loyalty:7 Loyalty:7
A:AB$ DealDamage | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 3 | SpellDescription$ CARDNAME deals 3 damage to any target. A:AB$ DealDamage | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 3 | SpellDescription$ CARDNAME deals 3 damage to any target.
A:AB$ ChangeZoneAll | Cost$ SubCounter<X/LOYALTY> | UseAllOriginZones$ True | Planeswalker$ True | ChangeType$ Permanent.nonColorless+cmcLEChosenX | References$ X | Origin$ Battlefield | Destination$ Exile | SpellDescription$ Exile each permanent with converted mana cost X or less that's one or more colors. A:AB$ ChangeZoneAll | Cost$ SubCounter<X/LOYALTY> | UseAllOriginZones$ True | Planeswalker$ True | ChangeType$ Permanent.nonColorless+cmcLEX | References$ X | Origin$ Battlefield | Destination$ Exile | SpellDescription$ Exile each permanent with converted mana cost X or less that's one or more colors.
SVar:X:XChoice SVar:X:Count$xPaid
A:AB$ GainLife | Cost$ SubCounter<10/LOYALTY> | Planeswalker$ True | Ultimate$ True | LifeAmount$ 7 | SubAbility$ DBDraw | SpellDescription$ You gain 7 life, draw seven cards, then put up to seven permanent cards from your hand onto the battlefield. A:AB$ GainLife | Cost$ SubCounter<10/LOYALTY> | Planeswalker$ True | Ultimate$ True | LifeAmount$ 7 | SubAbility$ DBDraw | SpellDescription$ You gain 7 life, draw seven cards, then put up to seven permanent cards from your hand onto the battlefield.
SVar:DBDraw:DB$ Draw | NumCards$ 7 | SubAbility$ DBChangeZone SVar:DBDraw:DB$ Draw | NumCards$ 7 | SubAbility$ DBChangeZone
SVar:DBChangeZone:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | ChangeType$ Permanent | ChangeNum$ 7 SVar:DBChangeZone:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | ChangeType$ Permanent | ChangeNum$ 7
SVar:Picture:http://www.wizards.com/global/images/magic/general/ugin_the_spirit_dragon.jpg
Oracle:[+2]: Ugin, the Spirit Dragon deals 3 damage to any target.\n[-X]: Exile each permanent with converted mana cost X or less that's one or more colors.\n[-10]: You gain 7 life, draw seven cards, then put up to seven permanent cards from your hand onto the battlefield. Oracle:[+2]: Ugin, the Spirit Dragon deals 3 damage to any target.\n[-X]: Exile each permanent with converted mana cost X or less that's one or more colors.\n[-10]: You gain 7 life, draw seven cards, then put up to seven permanent cards from your hand onto the battlefield.

View File

@@ -3,9 +3,7 @@ ManaCost:4
Types:Artifact Types:Artifact
A:AB$ PutCounter | Cost$ 2 T | CounterType$ CHARGE | CounterNum$ 1 | SpellDescription$ Put a charge counter on CARDNAME. A:AB$ PutCounter | Cost$ 2 T | CounterType$ CHARGE | CounterNum$ 1 | SpellDescription$ Put a charge counter on CARDNAME.
A:AB$ Mana | Cost$ T SubCounter<X/CHARGE> | Produced$ W | Amount$ Y | CostDesc$ {T}, Remove any number of charge counters from CARDNAME: | AILogic$ ManaRitualBattery.1 | AINoRecursiveCheck$ True | SpellDescription$ Add {W}, then add an additional {W} for each charge counter removed this way. A:AB$ Mana | Cost$ T SubCounter<X/CHARGE> | Produced$ W | Amount$ Y | CostDesc$ {T}, Remove any number of charge counters from CARDNAME: | AILogic$ ManaRitualBattery.1 | AINoRecursiveCheck$ True | SpellDescription$ Add {W}, then add an additional {W} for each charge counter removed this way.
SVar:Y:Number$1/Plus.ChosenX SVar:Y:SVar$X/Plus.1
SVar:X:XChoice SVar:X:Count$xPaid
#ChosenX SVar created by Cost payment
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/white_mana_battery.jpg
Oracle:{2}, {T}: Put a charge counter on White Mana Battery.\n{T}, Remove any number of charge counters from White Mana Battery: Add {W}, then add an additional {W} for each charge counter removed this way. Oracle:{2}, {T}: Put a charge counter on White Mana Battery.\n{T}, Remove any number of charge counters from White Mana Battery: Add {W}, then add an additional {W} for each charge counter removed this way.

View File

@@ -29,7 +29,6 @@ import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardPlayOption; import forge.game.card.CardPlayOption;
import forge.game.cost.Cost; import forge.game.cost.Cost;
import forge.game.cost.CostPartMana;
import forge.game.cost.CostPayment; import forge.game.cost.CostPayment;
import forge.game.keyword.KeywordInterface; import forge.game.keyword.KeywordInterface;
import forge.game.mana.ManaPool; import forge.game.mana.ManaPool;
@@ -221,9 +220,7 @@ public class HumanPlaySpellAbility {
if (ability.isCopied()) { return true; } //don't re-announce for spell copies if (ability.isCopied()) { return true; } //don't re-announce for spell copies
boolean needX = true; boolean needX = true;
final boolean allowZero = !ability.hasParam("XCantBe0");
final Cost cost = ability.getPayCosts(); final Cost cost = ability.getPayCosts();
final CostPartMana manaCost = cost.getCostMana();
final PlayerController controller = ability.getActivatingPlayer().getController(); final PlayerController controller = ability.getActivatingPlayer().getController();
final Card card = ability.getHostCard(); final Card card = ability.getHostCard();
@@ -237,7 +234,7 @@ public class HumanPlaySpellAbility {
final boolean isX = "X".equalsIgnoreCase(varName); final boolean isX = "X".equalsIgnoreCase(varName);
if (isX) { needX = false; } if (isX) { needX = false; }
final Integer value = controller.announceRequirements(ability, varName, allowZero && (!isX || manaCost == null || manaCost.canXbe0())); final Integer value = controller.announceRequirements(ability, varName);
if (value == null) { if (value == null) {
return false; return false;
} }
@@ -254,17 +251,17 @@ public class HumanPlaySpellAbility {
} }
} }
if (needX && manaCost != null) { if (needX) {
if (cost.hasXInAnyCostPart()) { if (cost.hasXInAnyCostPart()) {
final String sVar = ability.getSVar("X"); //only prompt for new X value if card doesn't determine it another way final String sVar = ability.getSVar("X"); //only prompt for new X value if card doesn't determine it another way
if ("Count$xPaid".equals(sVar) || sVar.isEmpty()) { if ("Count$xPaid".equals(sVar) || sVar.isEmpty()) {
final Integer value = controller.announceRequirements(ability, "X", allowZero && manaCost.canXbe0()); final Integer value = controller.announceRequirements(ability, "X");
if (value == null) { if (value == null) {
return false; return false;
} }
ability.setXManaCostPaid(value); ability.setXManaCostPaid(value);
} }
} else if (manaCost.getMana().isZero() && ability.isSpell()) { } else {
ability.setXManaCostPaid(0); ability.setXManaCostPaid(0);
} }
} }

View File

@@ -320,12 +320,12 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
} }
@Override @Override
public Integer announceRequirements(final SpellAbility ability, final String announce, public Integer announceRequirements(final SpellAbility ability, final String announce) {
final boolean canChooseZero) {
final int min = canChooseZero ? 0 : 1;
int max = Integer.MAX_VALUE; int max = Integer.MAX_VALUE;
boolean canChooseZero = true;
if ("X".equals(announce)) { if ("X".equals(announce)) {
canChooseZero = !ability.hasParam("XCantBe0");
Cost cost = ability.getPayCosts(); Cost cost = ability.getPayCosts();
if (ability.hasParam("XMaxLimit")) { if (ability.hasParam("XMaxLimit")) {
max = Math.min(max, AbilityUtils.calculateAmount(ability.getHostCard(), ability.getParam("XMaxLimit"), ability)); max = Math.min(max, AbilityUtils.calculateAmount(ability.getHostCard(), ability.getParam("XMaxLimit"), ability));
@@ -333,10 +333,14 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
if (cost != null) { if (cost != null) {
Integer costX = cost.getMaxForNonManaX(ability, player); Integer costX = cost.getMaxForNonManaX(ability, player);
if (costX != null) { if (costX != null) {
max = Math.min(max, min); max = Math.min(max, costX);
}
if (cost.hasManaCost() && !cost.getCostMana().canXbe0()) {
canChooseZero = false;
} }
} }
} }
final int min = canChooseZero ? 0 : 1;
if (ability.usesTargeting()) { if (ability.usesTargeting()) {
// if announce is used as min targets, check what the max possible number would be // if announce is used as min targets, check what the max possible number would be
@@ -344,6 +348,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
max = Math.min(max, CardUtil.getValidCardsToTarget(ability.getTargetRestrictions(), ability).size()); max = Math.min(max, CardUtil.getValidCardsToTarget(ability.getTargetRestrictions(), ability).size());
} }
} }
if (min > max) {
return null;
}
return getGui().getInteger(localizer.getMessage("lblChooseAnnounceForCard", announce, return getGui().getInteger(localizer.getMessage("lblChooseAnnounceForCard", announce,
CardTranslation.getTranslatedName(ability.getHostCard().getName())) , min, max, min + 9); CardTranslation.getTranslatedName(ability.getHostCard().getName())) , min, max, min + 9);
} }