Merge branch 'master' of git.cardforge.org:core-developers/forge into agetian-master

This commit is contained in:
Michael Kamensky
2021-11-26 07:41:37 +03:00
95 changed files with 160 additions and 183 deletions

View File

@@ -901,7 +901,7 @@ public class AiController {
return canPlayFromEffectAI((SpellPermanent)sa, false, true); return canPlayFromEffectAI((SpellPermanent)sa, false, true);
} }
if (sa.usesTargeting()) { if (sa.usesTargeting()) {
if (!sa.isTargetNumberValid() && !sa.getTargetRestrictions().hasCandidates(sa)) { if (!sa.isTargetNumberValid() && sa.getTargetRestrictions().getNumCandidates(sa, true) == 0) {
return AiPlayDecision.TargetingFailed; return AiPlayDecision.TargetingFailed;
} }
if (!StaticAbilityMustTarget.meetsMustTargetRestriction(sa)) { if (!StaticAbilityMustTarget.meetsMustTargetRestriction(sa)) {
@@ -1622,6 +1622,7 @@ public class AiController {
Map<String, String> params = t.getMapParams(); Map<String, String> params = t.getMapParams();
if ("ChangesZone".equals(params.get("Mode")) if ("ChangesZone".equals(params.get("Mode"))
&& params.containsKey("ValidCard") && params.containsKey("ValidCard")
&& (!params.containsKey("AILogic") || !params.get("AILogic").equals("SafeToHold"))
&& !params.get("ValidCard").contains("nonLand") && !params.get("ValidCard").contains("nonLand")
&& ((params.get("ValidCard").contains("Land")) || (params.get("ValidCard").contains("Permanent"))) && ((params.get("ValidCard").contains("Land")) || (params.get("ValidCard").contains("Permanent")))
&& "Battlefield".equals(params.get("Destination"))) { && "Battlefield".equals(params.get("Destination"))) {

View File

@@ -1871,7 +1871,7 @@ public class ComputerUtilCard {
return oppCards; return oppCards;
} }
CardCollection aiCreats = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); CardCollection aiCreats = ai.getCreaturesInPlay();
if (temporary) { if (temporary) {
// Pump effects that add "CARDNAME can't attack" and similar things. Only do it if something is untapped. // Pump effects that add "CARDNAME can't attack" and similar things. Only do it if something is untapped.
oppCards = CardLists.filter(oppCards, CardPredicates.Presets.UNTAPPED); oppCards = CardLists.filter(oppCards, CardPredicates.Presets.UNTAPPED);

View File

@@ -162,21 +162,21 @@ public abstract class SpellAbilityAi {
*/ */
protected boolean checkApiLogic(final Player ai, final SpellAbility sa) { protected boolean checkApiLogic(final Player ai, final SpellAbility sa) {
if (ComputerUtil.preventRunAwayActivations(sa)) { if (ComputerUtil.preventRunAwayActivations(sa)) {
return false; // prevent infinite loop return false; // prevent infinite loop
} }
return MyRandom.getRandom().nextFloat() < .8f; // random success return MyRandom.getRandom().nextFloat() < .8f; // random success
} }
public final boolean doTriggerAI(final Player aiPlayer, final SpellAbility sa, final boolean mandatory) { public final boolean doTriggerAI(final Player aiPlayer, final SpellAbility sa, final boolean mandatory) {
// this evaluation order is currently intentional as it does more stuff that helps avoiding some crashes
if (!ComputerUtilCost.canPayCost(sa, aiPlayer) && !mandatory) { if (!ComputerUtilCost.canPayCost(sa, aiPlayer) && !mandatory) {
return false; return false;
} }
// a mandatory SpellAbility with targeting but without candidates, // a mandatory SpellAbility with targeting but without candidates,
// does not need to go any deeper // does not need to go any deeper
if (sa.usesTargeting() && mandatory && !sa.isTargetNumberValid() if (sa.usesTargeting() && mandatory && sa.getTargetRestrictions().getNumCandidates(sa, true) == 0) {
&& !sa.getTargetRestrictions().hasCandidates(sa)) { return sa.isTargetNumberValid();
return false;
} }
return doTriggerNoCostWithSubs(aiPlayer, sa, mandatory); return doTriggerNoCostWithSubs(aiPlayer, sa, mandatory);

View File

@@ -1699,19 +1699,21 @@ public class ChangeZoneAi extends SpellAbilityAi {
if (card.isToken()) { if (card.isToken()) {
return false; return false;
} }
if (card.isCreature() && ComputerUtilCard.isUselessCreature(decider, card)) { if (card.isCreature() && ComputerUtilCard.isUselessCreature(decider, card)) {
return true; return true;
} else if (card.isEquipped()) { }
if (card.isEquipped()) {
return false; return false;
} else if (card.isEnchanted()) { }
if (card.isEnchanted()) {
for (Card enc : card.getEnchantedBy()) { for (Card enc : card.getEnchantedBy()) {
if (enc.getOwner().isOpponentOf(decider)) { if (enc.getOwner().isOpponentOf(decider)) {
return true; return true;
} }
} }
return false; return false;
} else if (card.hasCounters()) { }
if (card.hasCounters()) {
if (card.isPlaneswalker()) { if (card.isPlaneswalker()) {
int maxLoyaltyToConsider = 2; int maxLoyaltyToConsider = 2;
int loyaltyDiff = 2; int loyaltyDiff = 2;

View File

@@ -392,15 +392,19 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
PlayerPredicates.isTargetableBy(sa))); PlayerPredicates.isTargetableBy(sa)));
if (oppList.isEmpty()) { if (oppList.isEmpty()) {
if (mandatory && !sa.isTargetNumberValid() && sa.canTarget(ai)) {
sa.resetTargets();
sa.getTargets().add(ai);
return true;
}
return false; return false;
} }
// get the one with the most handsize // get the one with the most handsize
Player oppTarget = Collections.max(oppList, Player oppTarget = Collections.max(oppList, PlayerPredicates.compareByZoneSize(origin));
PlayerPredicates.compareByZoneSize(origin));
// set the target // set the target
if (!oppTarget.getCardsIn(ZoneType.Hand).isEmpty()) { if (!oppTarget.getCardsIn(ZoneType.Hand).isEmpty() || mandatory) {
sa.resetTargets(); sa.resetTargets();
sa.getTargets().add(oppTarget); sa.getTargets().add(oppTarget);
} else { } else {
@@ -434,7 +438,12 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
PlayerPredicates.isTargetableBy(sa))); PlayerPredicates.isTargetableBy(sa)));
if (oppList.isEmpty()) { if (oppList.isEmpty()) {
return false; if (mandatory && !sa.isTargetNumberValid() && sa.canTarget(ai)) {
sa.resetTargets();
sa.getTargets().add(ai);
return true;
}
return sa.isTargetNumberValid();
} }
// get the one with the most in graveyard // get the one with the most in graveyard
@@ -443,7 +452,7 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
AiPlayerPredicates.compareByZoneValue(sa.getParam("ChangeType"), origin, sa)); AiPlayerPredicates.compareByZoneValue(sa.getParam("ChangeType"), origin, sa));
// set the target // set the target
if (!oppTarget.getCardsIn(ZoneType.Graveyard).isEmpty()) { if (!oppTarget.getCardsIn(ZoneType.Graveyard).isEmpty() || mandatory) {
sa.resetTargets(); sa.resetTargets();
sa.getTargets().add(oppTarget); sa.getTargets().add(oppTarget);
} else { } else {

View File

@@ -4,7 +4,6 @@ import forge.ai.AiAttackController;
import forge.ai.SpellAbilityAi; import forge.ai.SpellAbilityAi;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom; import forge.util.MyRandom;
public class ChooseEvenOddAi extends SpellAbilityAi { public class ChooseEvenOddAi extends SpellAbilityAi {
@@ -14,8 +13,7 @@ public class ChooseEvenOddAi extends SpellAbilityAi {
if (!sa.hasParam("AILogic")) { if (!sa.hasParam("AILogic")) {
return false; return false;
} }
TargetRestrictions tgt = sa.getTargetRestrictions(); if (sa.usesTargeting()) {
if (tgt != null) {
sa.resetTargets(); sa.resetTargets();
Player opp = AiAttackController.choosePreferredDefenderPlayer(aiPlayer); Player opp = AiAttackController.choosePreferredDefenderPlayer(aiPlayer);
if (sa.canTarget(opp)) { if (sa.canTarget(opp)) {
@@ -34,4 +32,3 @@ public class ChooseEvenOddAi extends SpellAbilityAi {
} }
} }

View File

@@ -6,7 +6,6 @@ import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom; import forge.util.MyRandom;
public class ChooseNumberAi extends SpellAbilityAi { public class ChooseNumberAi extends SpellAbilityAi {
@@ -44,8 +43,7 @@ public class ChooseNumberAi extends SpellAbilityAi {
return ownCreatureCount > oppMaxCreatureCount + 2 || ownCreatureCount < Math.min(oppMaxCreatureCount, maxChoiceLimit); return ownCreatureCount > oppMaxCreatureCount + 2 || ownCreatureCount < Math.min(oppMaxCreatureCount, maxChoiceLimit);
} }
TargetRestrictions tgt = sa.getTargetRestrictions(); if (sa.usesTargeting()) {
if (tgt != null) {
sa.resetTargets(); sa.resetTargets();
Player opp = AiAttackController.choosePreferredDefenderPlayer(aiPlayer); Player opp = AiAttackController.choosePreferredDefenderPlayer(aiPlayer);
if (sa.canTarget(opp)) { if (sa.canTarget(opp)) {

View File

@@ -26,7 +26,6 @@ import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance; import forge.game.spellability.SpellAbilityStackInstance;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.util.Aggregates; import forge.util.Aggregates;
@@ -52,8 +51,7 @@ public class ChooseSourceAi extends SpellAbilityAi {
} }
} }
final TargetRestrictions tgt = sa.getTargetRestrictions(); if (sa.usesTargeting()) {
if (tgt != null) {
sa.resetTargets(); sa.resetTargets();
Player opp = AiAttackController.choosePreferredDefenderPlayer(ai); Player opp = AiAttackController.choosePreferredDefenderPlayer(ai);
if (sa.canTarget(opp)) { if (sa.canTarget(opp)) {

View File

@@ -108,7 +108,7 @@ public class ChooseTypeAi extends SpellAbilityAi {
@Override @Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) { protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
boolean isCurse = sa.hasParam("IsCurse"); boolean isCurse = sa.isCurse();
if (sa.usesTargeting()) { if (sa.usesTargeting()) {
final List<Player> oppList = Lists.newArrayList(Iterables.filter( final List<Player> oppList = Lists.newArrayList(Iterables.filter(

View File

@@ -92,7 +92,7 @@ public class ClashAi extends SpellAbilityAi {
if ("Creature".equals(valid)) { if ("Creature".equals(valid)) {
// Springjack Knight // Springjack Knight
// TODO: Whirlpool Whelm also uses creature targeting but it's trickier to support // TODO: Whirlpool Whelm also uses creature targeting but it's trickier to support
CardCollectionView aiCreats = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); CardCollectionView aiCreats = ai.getCreaturesInPlay();
CardCollectionView oppCreats = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); CardCollectionView oppCreats = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
Card tgt = aiCreats.isEmpty() ? ComputerUtilCard.getWorstCreatureAI(oppCreats) : ComputerUtilCard.getBestCreatureAI(aiCreats); Card tgt = aiCreats.isEmpty() ? ComputerUtilCard.getWorstCreatureAI(oppCreats) : ComputerUtilCard.getBestCreatureAI(aiCreats);

View File

@@ -16,7 +16,6 @@ import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode; import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.Spell; import forge.game.spellability.Spell;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom; import forge.util.MyRandom;
public class CopySpellAbilityAi extends SpellAbilityAi { public class CopySpellAbilityAi extends SpellAbilityAi {
@@ -58,8 +57,7 @@ public class CopySpellAbilityAi extends SpellAbilityAi {
} }
} }
final TargetRestrictions tgt = sa.getTargetRestrictions(); if (sa.usesTargeting()) {
if (tgt != null) {
// Filter AI-specific targets if provided // Filter AI-specific targets if provided
if ("OnlyOwned".equals(sa.getParam("AITgts"))) { if ("OnlyOwned".equals(sa.getParam("AITgts"))) {
if (!top.getActivatingPlayer().equals(aiPlayer)) { if (!top.getActivatingPlayer().equals(aiPlayer)) {

View File

@@ -27,7 +27,6 @@ import forge.game.cost.CostSacrifice;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance; import forge.game.spellability.SpellAbilityStackInstance;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.util.MyRandom; import forge.util.MyRandom;
@@ -63,8 +62,7 @@ public class CounterAi extends SpellAbilityAi {
} }
} }
final TargetRestrictions tgt = sa.getTargetRestrictions(); if (sa.usesTargeting()) {
if (tgt != null) {
final SpellAbility topSA = ComputerUtilAbility.getTopSpellAbilityOnStack(game, sa); final SpellAbility topSA = ComputerUtilAbility.getTopSpellAbilityOnStack(game, sa);
if (!CardFactoryUtil.isCounterableBy(topSA.getHostCard(), sa) || topSA.getActivatingPlayer() == ai if (!CardFactoryUtil.isCounterableBy(topSA.getHostCard(), sa) || topSA.getActivatingPlayer() == ai
|| ai.getAllies().contains(topSA.getActivatingPlayer())) { || ai.getAllies().contains(topSA.getActivatingPlayer())) {
@@ -246,10 +244,9 @@ public class CounterAi extends SpellAbilityAi {
@Override @Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) { protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Game game = ai.getGame(); final Game game = ai.getGame();
if (tgt != null) { if (sa.usesTargeting()) {
if (game.getStack().isEmpty()) { if (game.getStack().isEmpty()) {
return false; return false;
} }

View File

@@ -442,7 +442,7 @@ public class CountersPutAi extends CountersAi {
} }
} }
if ("AlwaysAtOppEOT".equals(logic)) { if ("AtOppEOT".equals(logic)) {
if (ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn().equals(ai)) { if (ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn().equals(ai)) {
return true; return true;
} }

View File

@@ -76,8 +76,8 @@ public abstract class DamageAiBase extends SpellAbilityAi {
Card hostcard = sa.getHostCard(); Card hostcard = sa.getHostCard();
for (Trigger trig : hostcard.getTriggers()) { for (Trigger trig : hostcard.getTriggers()) {
if (trig.getMode() == TriggerType.DamageDone) { if (trig.getMode() == TriggerType.DamageDone) {
if (("Opponent".equals(trig.getParam("ValidTarget"))) if ("Opponent".equals(trig.getParam("ValidTarget"))
&& (!"True".equals(trig.getParam("CombatDamage")))) { && !"True".equals(trig.getParam("CombatDamage"))) {
return true; return true;
} }
} }

View File

@@ -448,7 +448,8 @@ public class DamageDealAi extends DamageAiBase {
// We can hurt a planeswalker, so rank the one which is the best target // We can hurt a planeswalker, so rank the one which is the best target
if (!hPlay.isEmpty() && pl.isOpponentOf(ai) && activator.equals(ai)) { if (!hPlay.isEmpty() && pl.isOpponentOf(ai) && activator.equals(ai)) {
return ComputerUtilCard.getBestPlaneswalkerToDamage(hPlay); Card pw = ComputerUtilCard.getBestPlaneswalkerToDamage(hPlay);
return pw == null && mandatory ? hPlay.get(0) : pw;
} }
return null; return null;
@@ -713,7 +714,7 @@ public class DamageDealAi extends DamageAiBase {
} }
} }
if (freePing && sa.canTarget(enemy) && (!avoidTargetP(ai, sa))) { if (freePing && sa.canTarget(enemy) && !avoidTargetP(ai, sa)) {
tcs.add(enemy); tcs.add(enemy);
if (divided) { if (divided) {
sa.addDividedAllocation(enemy, dmg); sa.addDividedAllocation(enemy, dmg);

View File

@@ -91,8 +91,7 @@ public class DebuffAi extends SpellAbilityAi {
@Override @Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) { public boolean chkAIDrawback(SpellAbility sa, Player ai) {
if (!sa.usesTargeting()) { if (!sa.usesTargeting()) {
// TODO - copied from AF_Pump.pumpDrawbackAI() - what should be // TODO - copied from AF_Pump.pumpDrawbackAI() - what should be here?
// here?
} else { } else {
return debuffTgtAI(ai, sa, sa.hasParam("Keywords") ? Arrays.asList(sa.getParam("Keywords").split(" & ")) : null, false); return debuffTgtAI(ai, sa, sa.hasParam("Keywords") ? Arrays.asList(sa.getParam("Keywords").split(" & ")) : null, false);
} }

View File

@@ -371,7 +371,7 @@ public class DestroyAi extends SpellAbilityAi {
break; break;
} }
} else { } else {
break; return true;
} }
} else { } else {
Card c = ComputerUtilCard.getBestAI(preferred); Card c = ComputerUtilCard.getBestAI(preferred);
@@ -380,7 +380,7 @@ public class DestroyAi extends SpellAbilityAi {
} }
} }
while (sa.canAddMoreTarget()) { while (!sa.isMinTargetChosen()) {
if (list.isEmpty()) { if (list.isEmpty()) {
break; break;
} else { } else {

View File

@@ -148,7 +148,7 @@ public class DestroyAllAi extends SpellAbilityAi {
for (Card att : opponent.getCreaturesInPlay()) { for (Card att : opponent.getCreaturesInPlay()) {
if (ComputerUtilCombat.canAttackNextTurn(att, ai)) { if (ComputerUtilCombat.canAttackNextTurn(att, ai)) {
combat.addAttacker(att, ai); combat.addAttacker(att, ai);
containsAttacker = containsAttacker | opplist.contains(att); containsAttacker = containsAttacker || opplist.contains(att);
} }
} }
if (!containsAttacker) { if (!containsAttacker) {

View File

@@ -61,7 +61,7 @@ public class DigAi extends SpellAbilityAi {
if ("Never".equals(sa.getParam("AILogic"))) { if ("Never".equals(sa.getParam("AILogic"))) {
return false; return false;
} else if ("AtOppEndOfTurn".equals(sa.getParam("AILogic"))) { } else if ("AtOppEOT".equals(sa.getParam("AILogic"))) {
if (!(game.getPhaseHandler().getNextTurn() == ai && game.getPhaseHandler().is(PhaseType.END_OF_TURN))) { if (!(game.getPhaseHandler().getNextTurn() == ai && game.getPhaseHandler().is(PhaseType.END_OF_TURN))) {
return false; return false;
} }

View File

@@ -40,7 +40,7 @@ public class DigMultipleAi extends SpellAbilityAi {
if ("Never".equals(sa.getParam("AILogic"))) { if ("Never".equals(sa.getParam("AILogic"))) {
return false; return false;
} else if ("AtOppEndOfTurn".equals(sa.getParam("AILogic"))) { } else if ("AtOppEOT".equals(sa.getParam("AILogic"))) {
if (!(game.getPhaseHandler().getNextTurn() == ai && game.getPhaseHandler().is(PhaseType.END_OF_TURN))) { if (!(game.getPhaseHandler().getNextTurn() == ai && game.getPhaseHandler().is(PhaseType.END_OF_TURN))) {
return false; return false;
} }

View File

@@ -130,8 +130,7 @@ public class DigUntilAi extends SpellAbilityAi {
if ("OathOfDruids".equals(logic)) { if ("OathOfDruids".equals(logic)) {
final List<Card> creaturesInLibrary = final List<Card> creaturesInLibrary =
CardLists.filter(player.getCardsIn(ZoneType.Library), CardPredicates.Presets.CREATURES); CardLists.filter(player.getCardsIn(ZoneType.Library), CardPredicates.Presets.CREATURES);
final List<Card> creaturesInBattlefield = final List<Card> creaturesInBattlefield = player.getCreaturesInPlay();
CardLists.filter(player.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
// if there are at least 3 creatures in library, // if there are at least 3 creatures in library,
// or none in play with one in library, oath // or none in play with one in library, oath
return creaturesInLibrary.size() > 2 return creaturesInLibrary.size() > 2

View File

@@ -140,7 +140,7 @@ public class DrawAi extends SpellAbilityAi {
// LifeLessThan logic presupposes activation as soon as possible in an // LifeLessThan logic presupposes activation as soon as possible in an
// attempt to save the AI from dying // attempt to save the AI from dying
return true; return true;
} else if (logic.equals("AlwaysAtOppEOT")) { } else if (logic.equals("AtOppEOT")) {
return ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn().equals(ai); return ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn().equals(ai);
} else if (logic.equals("RespondToOwnActivation")) { } else if (logic.equals("RespondToOwnActivation")) {
return !ai.getGame().getStack().isEmpty() && ai.getGame().getStack().peekAbility().getHostCard().equals(sa.getHostCard()); return !ai.getGame().getStack().isEmpty() && ai.getGame().getStack().peekAbility().getHostCard().equals(sa.getHostCard());

View File

@@ -66,7 +66,7 @@ public class FightAi extends SpellAbilityAi {
} }
} }
if (fighter1List.isEmpty()) { if (fighter1List.isEmpty()) {
return true; // FIXME: shouldn't this return "false" if nothing found? return false;
} }
Card fighter1 = fighter1List.get(0); Card fighter1 = fighter1List.get(0);
for (Card humanCreature : humCreatures) { for (Card humanCreature : humCreatures) {

View File

@@ -54,7 +54,7 @@ public class FlipACoinAi extends SpellAbilityAi {
return false; return false;
} }
} }
return true; return sa.isTargetNumberValid();
} }
@Override @Override

View File

@@ -122,9 +122,9 @@ public class LifeSetAi extends SpellAbilityAi {
} }
// special cases when amount can't be calculated without targeting first // special cases when amount can't be calculated without targeting first
if (amount == 0 && opponent != null && "TargetedPlayer$StartingLife/HalfDown".equals(source.getSVar(amountStr))) { if (amount == 0 && "TargetedPlayer$StartingLife/HalfDown".equals(source.getSVar(amountStr))) {
// e.g. Torgaar, Famine Incarnate // e.g. Torgaar, Famine Incarnate
return doHalfStartingLifeLogic(ai, opponent, sa); return doHalfStartingLifeLogic(ai, opponent, sa) || mandatory;
} }
if (sourceName.equals("Eternity Vessel") if (sourceName.equals("Eternity Vessel")
@@ -160,9 +160,9 @@ public class LifeSetAi extends SpellAbilityAi {
private boolean doHalfStartingLifeLogic(Player ai, Player opponent, SpellAbility sa) { private boolean doHalfStartingLifeLogic(Player ai, Player opponent, SpellAbility sa) {
int aiAmount = ai.getStartingLife() / 2; int aiAmount = ai.getStartingLife() / 2;
int oppAmount = opponent.getStartingLife() / 2; int oppAmount = opponent == null ? 0 : opponent.getStartingLife() / 2;
int aiLife = ai.getLife(); int aiLife = ai.getLife();
int oppLife = opponent.getLife(); int oppLife = opponent == null ? 0 : opponent.getLife();
sa.resetTargets(); sa.resetTargets();

View File

@@ -15,6 +15,7 @@ import forge.ai.SpellAbilityAi;
import forge.card.ColorSet; import forge.card.ColorSet;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.card.mana.ManaCost; import forge.card.mana.ManaCost;
import forge.game.GlobalRuleChange;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
@@ -79,6 +80,8 @@ public class ManaEffectAi extends SpellAbilityAi {
protected boolean checkPhaseRestrictions(Player ai, SpellAbility sa, PhaseHandler ph, String logic) { protected boolean checkPhaseRestrictions(Player ai, SpellAbility sa, PhaseHandler ph, String logic) {
if (logic.startsWith("ManaRitual")) { if (logic.startsWith("ManaRitual")) {
return ph.is(PhaseType.MAIN2, ai) || ph.is(PhaseType.MAIN1, ai); return ph.is(PhaseType.MAIN2, ai) || ph.is(PhaseType.MAIN1, ai);
} else if ("AtOppEOT".equals(logic)) {
return !ai.getGame().getStaticEffects().getGlobalRuleChange(GlobalRuleChange.manaBurn) && ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn() == ai;
} }
return super.checkPhaseRestrictions(ai, sa, ph, logic); return super.checkPhaseRestrictions(ai, sa, ph, logic);
} }

View File

@@ -146,13 +146,13 @@ public class MillAi extends SpellAbilityAi {
// can't target opponent? // can't target opponent?
if (list.isEmpty()) { if (list.isEmpty()) {
if (mandatory && sa.canTarget(ai)) { if (mandatory && !sa.isTargetNumberValid() && sa.canTarget(ai)) {
sa.getTargets().add(ai); sa.getTargets().add(ai);
return true; return true;
} }
// TODO Obscure case when you know what your top card is so you might? // TODO Obscure case when you know what your top card is so you might?
// want to mill yourself here // want to mill yourself here
return false; return sa.isTargetNumberValid();
} }
// select Player which would cause the most damage // select Player which would cause the most damage

View File

@@ -5,7 +5,6 @@ import java.util.Map;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.ai.AiCardMemory; import forge.ai.AiCardMemory;
import forge.ai.ComputerUtilCard; import forge.ai.ComputerUtilCard;
@@ -15,14 +14,12 @@ import forge.game.Game;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.combat.Combat; import forge.game.combat.Combat;
import forge.game.combat.CombatUtil; import forge.game.combat.CombatUtil;
import forge.game.keyword.Keyword; import forge.game.keyword.Keyword;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
public class MustBlockAi extends SpellAbilityAi { public class MustBlockAi extends SpellAbilityAi {
@@ -76,7 +73,7 @@ public class MustBlockAi extends SpellAbilityAi {
return false; return false;
} }
Card attacker = null; Card attacker = source;
if (sa.hasParam("DefinedAttacker")) { if (sa.hasParam("DefinedAttacker")) {
final List<Card> cards = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedAttacker"), sa); final List<Card> cards = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedAttacker"), sa);
if (cards.isEmpty()) { if (cards.isEmpty()) {
@@ -86,18 +83,12 @@ public class MustBlockAi extends SpellAbilityAi {
attacker = cards.get(0); attacker = cards.get(0);
} }
if (attacker == null) {
attacker = source;
}
final Card definedAttacker = attacker;
boolean chance = false; boolean chance = false;
if (sa.usesTargeting()) { if (sa.usesTargeting()) {
final List<Card> list = determineGoodBlockers(definedAttacker, ai, ai.getWeakestOpponent(), sa, true,true); final List<Card> list = determineGoodBlockers(attacker, ai, ai.getWeakestOpponent(), sa, true, true);
if (list.isEmpty()) { if (list.isEmpty()) {
return false; return sa.isTargetNumberValid();
} }
final Card blocker = ComputerUtilCard.getBestCreatureAI(list); final Card blocker = ComputerUtilCard.getBestCreatureAI(list);
if (blocker == null) { if (blocker == null) {
@@ -160,8 +151,7 @@ public class MustBlockAi extends SpellAbilityAi {
private List<Card> determineGoodBlockers(final Card attacker, final Player ai, Player defender, SpellAbility sa, private List<Card> determineGoodBlockers(final Card attacker, final Player ai, Player defender, SpellAbility sa,
final boolean onlyLethal, final boolean testTapped) { final boolean onlyLethal, final boolean testTapped) {
List<Card> list = Lists.newArrayList(); List<Card> list = defender.getCreaturesInPlay();
list = CardLists.filter(defender.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
if (sa.usesTargeting()) { if (sa.usesTargeting()) {
list = CardLists.getTargetableCards(list, sa); list = CardLists.getTargetableCards(list, sa);
@@ -187,7 +177,7 @@ public class MustBlockAi extends SpellAbilityAi {
List<Card> better = determineBlockerFromList(attacker, ai, options, sa, false, false); List<Card> better = determineBlockerFromList(attacker, ai, options, sa, false, false);
if (!better.isEmpty()) { if (!better.isEmpty()) {
return Iterables.getFirst(options, null); return Iterables.getFirst(better, null);
} }
return Iterables.getFirst(options, null); return Iterables.getFirst(options, null);

View File

@@ -63,7 +63,7 @@ public class PhasesAi extends SpellAbilityAi {
return true; return true;
} else if (mandatory) { } else if (mandatory) {
// not enough preferred targets, but mandatory so keep going: // not enough preferred targets, but mandatory so keep going:
return phasesUnpreferredTargeting(aiPlayer.getGame(), sa, mandatory); return sa.isTargetNumberValid() || phasesUnpreferredTargeting(aiPlayer.getGame(), sa, mandatory);
} }
return false; return false;

View File

@@ -23,7 +23,6 @@ import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
public class PumpAllAi extends PumpAiBase { public class PumpAllAi extends PumpAiBase {
@@ -57,19 +56,20 @@ public class PumpAllAi extends PumpAiBase {
} }
} }
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Player opp = ai.getStrongestOpponent(); final Player opp = ai.getStrongestOpponent();
if (tgt != null && sa.canTarget(opp) && sa.isCurse()) { if (sa.usesTargeting()) {
sa.resetTargets(); if (sa.canTarget(opp) && sa.isCurse()) {
sa.getTargets().add(opp); sa.resetTargets();
return true; sa.getTargets().add(opp);
} return true;
}
if (tgt != null && sa.canTarget(ai) && !sa.isCurse()) {
sa.resetTargets(); if (sa.canTarget(ai) && !sa.isCurse()) {
sa.getTargets().add(ai); sa.resetTargets();
return true; sa.getTargets().add(ai);
return true;
}
} }
final int power = AbilityUtils.calculateAmount(source, sa.getParam("NumAtt"), sa); final int power = AbilityUtils.calculateAmount(source, sa.getParam("NumAtt"), sa);

View File

@@ -1,6 +1,5 @@
package forge.ai.ability; package forge.ai.ability;
import java.util.Collections;
import java.util.List; import java.util.List;
import forge.ai.ComputerUtilCard; import forge.ai.ComputerUtilCard;
@@ -57,13 +56,13 @@ public class SacrificeAi extends SpellAbilityAi {
private boolean sacrificeTgtAI(final Player ai, final SpellAbility sa, boolean mandatory) { private boolean sacrificeTgtAI(final Player ai, final SpellAbility sa, boolean mandatory) {
final Card source = sa.getHostCard(); final Card source = sa.getHostCard();
final boolean destroy = sa.hasParam("Destroy"); final boolean destroy = sa.hasParam("Destroy");
final PlayerCollection targetableOpps = ai.getOpponents().filter(PlayerPredicates.isTargetableBy(sa));
final Player opp = Collections.max(targetableOpps, PlayerPredicates.compareByLife());
if (sa.usesTargeting()) { if (sa.usesTargeting()) {
if (opp == null) { final PlayerCollection targetableOpps = ai.getOpponents().filter(PlayerPredicates.isTargetableBy(sa));
if (targetableOpps.isEmpty()) {
return false; return false;
} }
final Player opp = targetableOpps.max(PlayerPredicates.compareByLife());
sa.resetTargets(); sa.resetTargets();
sa.getTargets().add(opp); sa.getTargets().add(opp);
if (mandatory) { if (mandatory) {

View File

@@ -29,7 +29,7 @@ public class TapAllAi extends SpellAbilityAi {
// or during upkeep/begin combat? // or during upkeep/begin combat?
final Card source = sa.getHostCard(); final Card source = sa.getHostCard();
final Player opp = ai.getWeakestOpponent(); final Player opp = ai.getStrongestOpponent();
final Game game = ai.getGame(); final Game game = ai.getGame();
if (game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_BEGIN)) { if (game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_BEGIN)) {

View File

@@ -10,7 +10,6 @@ import forge.game.card.CardCollectionView;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.util.collect.FCollection; import forge.util.collect.FCollection;
@@ -28,8 +27,7 @@ public class TwoPilesAi extends SpellAbilityAi {
final Player opp = AiAttackController.choosePreferredDefenderPlayer(ai); final Player opp = AiAttackController.choosePreferredDefenderPlayer(ai);
final TargetRestrictions tgt = sa.getTargetRestrictions(); if (sa.usesTargeting()) {
if (tgt != null) {
sa.resetTargets(); sa.resetTargets();
if (sa.canTarget(opp)) { if (sa.canTarget(opp)) {
sa.getTargets().add(opp); sa.getTargets().add(opp);

View File

@@ -12,7 +12,6 @@ import forge.game.card.Card;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom; import forge.util.MyRandom;
public class UnattachAllAi extends SpellAbilityAi { public class UnattachAllAi extends SpellAbilityAi {
@@ -48,7 +47,6 @@ public class UnattachAllAi extends SpellAbilityAi {
return chance; return chance;
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#doTriggerAINoCost(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility, boolean) * @see forge.card.abilityfactory.SpellAiLogic#doTriggerAINoCost(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility, boolean)
*/ */
@@ -57,8 +55,7 @@ public class UnattachAllAi extends SpellAbilityAi {
final Card card = sa.getHostCard(); final Card card = sa.getHostCard();
// Check if there are any valid targets // Check if there are any valid targets
List<GameObject> targets = new ArrayList<>(); List<GameObject> targets = new ArrayList<>();
final TargetRestrictions tgt = sa.getTargetRestrictions(); if (!sa.usesTargeting()) {
if (tgt == null) {
targets = AbilityUtils.getDefinedObjects(sa.getHostCard(), sa.getParam("Defined"), sa); targets = AbilityUtils.getDefinedObjects(sa.getHostCard(), sa.getParam("Defined"), sa);
} }

View File

@@ -6,7 +6,6 @@ import java.util.Map;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import forge.ai.AiAttackController;
import forge.ai.ComputerUtil; import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilAbility; import forge.ai.ComputerUtilAbility;
import forge.ai.ComputerUtilCard; import forge.ai.ComputerUtilCard;
@@ -125,11 +124,11 @@ public class UntapAi extends SpellAbilityAi {
private static boolean untapPrefTargeting(final Player ai, final SpellAbility sa, final boolean mandatory) { private static boolean untapPrefTargeting(final Player ai, final SpellAbility sa, final boolean mandatory) {
final Card source = sa.getHostCard(); final Card source = sa.getHostCard();
Player targetController = ai; final PlayerCollection targetController = new PlayerCollection();
if (sa.isCurse()) { if (sa.isCurse()) {
// TODO search through all opponents, may need to check if different controllers allowed targetController.addAll(ai.getOpponents());
targetController = AiAttackController.choosePreferredDefenderPlayer(ai); } else {
targetController.add(ai);
} }
CardCollection list = CardLists.getTargetableCards(targetController.getCardsIn(ZoneType.Battlefield), sa); CardCollection list = CardLists.getTargetableCards(targetController.getCardsIn(ZoneType.Battlefield), sa);

View File

@@ -156,6 +156,8 @@ public class ForgeScript {
return sa.isKicked(); return sa.isKicked();
} else if (property.equals("Loyalty")) { } else if (property.equals("Loyalty")) {
return sa.isPwAbility(); return sa.isPwAbility();
} else if (property.equals("nonLoyalty")) {
return !sa.isPwAbility();
} else if (property.equals("Aftermath")) { } else if (property.equals("Aftermath")) {
return sa.isAftermath(); return sa.isAftermath();
} else if (property.equals("MorphUp")) { } else if (property.equals("MorphUp")) {

View File

@@ -1689,10 +1689,6 @@ public class AbilityUtils {
// accept straight numbers // accept straight numbers
if (l[0].startsWith("Number$")) { if (l[0].startsWith("Number$")) {
final String number = l[0].substring(7); final String number = l[0].substring(7);
if (number.equals("ChosenNumber")) { // TODO remove in favor of Count ChosenNumber
int x = c.getChosenNumber() == null ? 0 : c.getChosenNumber();
return doXMath(x, expr, c, ctb);
}
return doXMath(Integer.parseInt(number), expr, c, ctb); return doXMath(Integer.parseInt(number), expr, c, ctb);
} }

View File

@@ -272,8 +272,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
sb.append("."); sb.append(".");
} else if (origin.equals("Battlefield")) { } else if (origin.equals("Battlefield")) {
// TODO Expand on this Description as more cards use it // TODO Expand on this Description as more cards use it
// for the non-targeted SAs when you choose what is returned on // for the non-targeted SAs when you choose what is returned on resolution
// resolution
sb.append("Return ").append(num).append(" ").append(type).append(" card(s) "); sb.append("Return ").append(num).append(" ").append(type).append(" card(s) ");
sb.append(" to your ").append(destination); sb.append(" to your ").append(destination);
} }
@@ -361,8 +360,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
sb.append(fromGraveyard); sb.append(fromGraveyard);
} }
// this needs to be zero indexed. Top = 0, Third = 2, -1 = // this needs to be zero indexed. Top = 0, Third = 2, -1 = Bottom
// Bottom
final int libraryPosition = sa.hasParam("LibraryPosition") ? AbilityUtils.calculateAmount(host, sa.getParam("LibraryPosition"), sa) : 0; final int libraryPosition = sa.hasParam("LibraryPosition") ? AbilityUtils.calculateAmount(host, sa.getParam("LibraryPosition"), sa) : 0;
if (libraryPosition == -1) { if (libraryPosition == -1) {
@@ -451,9 +449,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
sb.append(sa.getParam("AlternativeDestinationMessage")); sb.append(sa.getParam("AlternativeDestinationMessage"));
Player alterDecider = player; Player alterDecider = player;
if (sa.hasParam("AlternativeDecider")) { if (sa.hasParam("AlternativeDecider")) {
alterDecider = AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("AlternativeDecider"), sa).get(0); PlayerCollection deciders = AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("AlternativeDecider"), sa);
alterDecider = deciders.isEmpty() ? null : deciders.get(0);
} }
if (!alterDecider.getController().confirmAction(sa, PlayerActionConfirmMode.ChangeZoneToAltDestination, sb.toString())) { if (alterDecider != null && !alterDecider.getController().confirmAction(sa, PlayerActionConfirmMode.ChangeZoneToAltDestination, sb.toString())) {
destination = ZoneType.smartValueOf(sa.getParam("DestinationAlternative")); destination = ZoneType.smartValueOf(sa.getParam("DestinationAlternative"));
altDest = true; altDest = true;
} }

View File

@@ -47,7 +47,7 @@ public class AttackConstraints {
public AttackConstraints(final Combat combat) { public AttackConstraints(final Combat combat) {
final Game game = combat.getAttackingPlayer().getGame(); final Game game = combat.getAttackingPlayer().getGame();
possibleAttackers = CardLists.filter(combat.getAttackingPlayer().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); possibleAttackers = combat.getAttackingPlayer().getCreaturesInPlay();
possibleDefenders = combat.getDefenders(); possibleDefenders = combat.getDefenders();
globalRestrictions = GlobalAttackRestrictions.getGlobalRestrictions(combat.getAttackingPlayer(), possibleDefenders); globalRestrictions = GlobalAttackRestrictions.getGlobalRestrictions(combat.getAttackingPlayer(), possibleDefenders);

View File

@@ -171,23 +171,6 @@ public class StaticAbilityCantBeCast {
return false; return false;
} }
// TODO refactor this ones using ValidSA above
if (stAb.hasParam("NonMana") && (spellAbility.isManaAbility())) {
return false;
}
if (stAb.hasParam("NonLoyalty") && spellAbility.isPwAbility()) {
return false;
}
if (stAb.hasParam("Loyalty") && !spellAbility.isPwAbility()) {
return false;
}
if (stAb.hasParam("TapAbility") && !(spellAbility.getPayCosts().hasTapCost())) {
return false;
}
if (stAb.hasParam("NonActivatorTurn") && (activator != null) if (stAb.hasParam("NonActivatorTurn") && (activator != null)
&& activator.getGame().getPhaseHandler().isPlayerTurn(activator)) { && activator.getGame().getPhaseHandler().isPlayerTurn(activator)) {
return false; return false;

View File

@@ -11,11 +11,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Vector; import java.util.Vector;
import javax.swing.JButton; import javax.swing.*;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionListener;
@@ -84,6 +80,8 @@ public class VLobby implements ILobbyView {
private final StartButton btnStart = new StartButton(); private final StartButton btnStart = new StartButton();
private final JPanel pnlStart = new JPanel(new MigLayout("insets 0, gap 0, wrap 2")); private final JPanel pnlStart = new JPanel(new MigLayout("insets 0, gap 0, wrap 2"));
private final JComboBox gamesInMatch = new JComboBox(new String[] {"1","3","5"});
private final JPanel gamesInMatchFrame = new JPanel(new MigLayout("insets 0, gap 0, wrap 2"));
private final JPanel constructedFrame = new JPanel(new MigLayout("insets 0, gap 0, wrap 2")); // Main content frame private final JPanel constructedFrame = new JPanel(new MigLayout("insets 0, gap 0, wrap 2")); // Main content frame
// Variants frame and variables // Variants frame and variables
@@ -212,11 +210,19 @@ public class VLobby implements ILobbyView {
public final void actionPerformed(final ActionEvent arg0) { public final void actionPerformed(final ActionEvent arg0) {
Runnable startGame = lobby.startGame(); Runnable startGame = lobby.startGame();
if (startGame != null) { if (startGame != null) {
if (!gamesInMatch.getSelectedItem().equals(ForgePreferences.FPref.UI_MATCHES_PER_GAME)) {
FModel.getPreferences().setPref(FPref.UI_MATCHES_PER_GAME, (String) gamesInMatch.getSelectedItem());
}
startGame.run(); startGame.run();
} }
} }
}); });
} }
gamesInMatchFrame.add(newLabel(localizer.getMessage("lblGamesInMatch")), "w 150px!, h 30px!");
gamesInMatchFrame.add(gamesInMatch, "w 50px!, h 30px!");
gamesInMatchFrame.setOpaque(false);
gamesInMatch.setSelectedItem("3");
pnlStart.add(gamesInMatchFrame);
} }
public void updateDeckPanel() { public void updateDeckPanel() {

View File

@@ -3,7 +3,7 @@ ManaCost:1 W
Types:Instant Types:Instant
A:SP$ Effect | Cost$ 1 W | ValidTgts$ Player | Name$ Abeyance Effect | StaticAbilities$ STCantBeCast,STCantBeActivated | RememberObjects$ Targeted | AILogic$ BeginningOfOppTurn | SubAbility$ DBDraw | SpellDescription$ Until end of turn, target player can't cast instant or sorcery spells, and that player can't activate abilities that aren't mana abilities. A:SP$ Effect | Cost$ 1 W | ValidTgts$ Player | Name$ Abeyance Effect | StaticAbilities$ STCantBeCast,STCantBeActivated | RememberObjects$ Targeted | AILogic$ BeginningOfOppTurn | SubAbility$ DBDraw | SpellDescription$ Until end of turn, target player can't cast instant or sorcery spells, and that player can't activate abilities that aren't mana abilities.
SVar:STCantBeCast:Mode$ CantBeCast | ValidCard$ Instant,Sorcery | Caster$ Player.IsRemembered | EffectZone$ Command | Description$ Target player can't cast instant or sorcery spells, and that player can't activate abilities that aren't mana abilities. SVar:STCantBeCast:Mode$ CantBeCast | ValidCard$ Instant,Sorcery | Caster$ Player.IsRemembered | EffectZone$ Command | Description$ Target player can't cast instant or sorcery spells, and that player can't activate abilities that aren't mana abilities.
SVar:STCantBeActivated:Mode$ CantBeActivated | ValidCard$ Card | Activator$ Player.IsRemembered | EffectZone$ Command | NonMana$ True SVar:STCantBeActivated:Mode$ CantBeActivated | ValidCard$ Card | ValidSA$ Activated.nonManaAbility | Activator$ Player.IsRemembered | EffectZone$ Command
SVar:DBDraw:DB$ Draw | NumCards$ 1 | SpellDescription$ Draw a card. SVar:DBDraw:DB$ Draw | NumCards$ 1 | SpellDescription$ Draw a card.
SVar:Picture:http://www.wizards.com/global/images/magic/general/abeyance.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/abeyance.jpg
Oracle:Until end of turn, target player can't cast instant or sorcery spells, and that player can't activate abilities that aren't mana abilities.\nDraw a card. Oracle:Until end of turn, target player can't cast instant or sorcery spells, and that player can't activate abilities that aren't mana abilities.\nDraw a card.

View File

@@ -3,7 +3,7 @@ ManaCost:1
Types:Artifact Types:Artifact
T:Mode$ CounterAddedOnce | ValidCard$ Permanent.YouCtrl | TriggerZones$ Battlefield | CounterType$ P1P1 | Execute$ TrigToken | TriggerDescription$ Whenever one or more +1/+1 counters are put on a permanent you control, you may pay {1}. If you do, create a 1/1 colorless Servo artifact creature token. T:Mode$ CounterAddedOnce | ValidCard$ Permanent.YouCtrl | TriggerZones$ Battlefield | CounterType$ P1P1 | Execute$ TrigToken | TriggerDescription$ Whenever one or more +1/+1 counters are put on a permanent you control, you may pay {1}. If you do, create a 1/1 colorless Servo artifact creature token.
SVar:TrigToken:AB$ Token | Cost$ 1 | TokenAmount$ 1 | TokenScript$ c_1_1_a_servo | TokenOwner$ You | LegacyImage$ c 1 1 a servo kld SVar:TrigToken:AB$ Token | Cost$ 1 | TokenAmount$ 1 | TokenScript$ c_1_1_a_servo | TokenOwner$ You | LegacyImage$ c 1 1 a servo kld
A:AB$ PutCounter | Cost$ 3 T | ValidTgts$ Permanent,Player | TgtPrompt$ Select target player or permanent | CounterType$ ExistingCounter | CounterNum$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Choose a counter on target permanent or player. Give that permanent or player another counter of that kind. A:AB$ PutCounter | Cost$ 3 T | ValidTgts$ Permanent,Player | TgtPrompt$ Select target player or permanent | CounterType$ ExistingCounter | CounterNum$ 1 | AILogic$ AtOppEOT | SpellDescription$ Choose a counter on target permanent or player. Give that permanent or player another counter of that kind.
DeckHints:Ability$Counters DeckHints:Ability$Counters
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/animation_module.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/animation_module.jpg

View File

@@ -3,6 +3,6 @@ ManaCost:no cost
Types:Land Types:Land
K:Ascend K:Ascend
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
A:AB$ Draw | Cost$ 5 T | NumCards$ 1 | Activation$ Blessing | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. Activate only if you have the city's blessing. A:AB$ Draw | Cost$ 5 T | NumCards$ 1 | Activation$ Blessing | AILogic$ AtOppEOT | SpellDescription$ Draw a card. Activate only if you have the city's blessing.
SVar:Picture:http://www.wizards.com/global/images/magic/general/arch_of_orazca.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/arch_of_orazca.jpg
Oracle:Ascend (If you control ten or more permanents, you get the city's blessing for the rest of the game.)\n{T}: Add {C}.\n{5}, {T}: Draw a card. Activate only if you have the city's blessing. Oracle:Ascend (If you control ten or more permanents, you get the city's blessing for the rest of the game.)\n{T}: Add {C}.\n{5}, {T}: Draw a card. Activate only if you have the city's blessing.

View File

@@ -2,7 +2,7 @@ Name:Azami, Lady of Scrolls
ManaCost:2 U U U ManaCost:2 U U U
Types:Legendary Creature Human Wizard Types:Legendary Creature Human Wizard
PT:0/2 PT:0/2
A:AB$ Draw | Cost$ tapXType<1/Wizard> | NumCards$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. A:AB$ Draw | Cost$ tapXType<1/Wizard> | NumCards$ 1 | AILogic$ AtOppEOT | SpellDescription$ Draw a card.
AI:RemoveDeck:Random AI:RemoveDeck:Random
DeckHints:Type$Wizard DeckHints:Type$Wizard
SVar:Picture:http://www.wizards.com/global/images/magic/general/azami_lady_of_scrolls.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/azami_lady_of_scrolls.jpg

View File

@@ -4,5 +4,5 @@ Types:Enchantment Aura
K:Enchant permanent K:Enchant permanent
A:SP$ Attach | Cost$ 2 W | ValidTgts$ Permanent | AILogic$ Curse A:SP$ Attach | Cost$ 2 W | ValidTgts$ Permanent | AILogic$ Curse
S:Mode$ Continuous | Affected$ Permanent.EnchantedBy | AddHiddenKeyword$ CARDNAME can't attack or block. & CARDNAME can't crew Vehicles. | Description$ Enchanted permanent can't attack, block, or crew Vehicles, and its activated abilities can't be activated unless they're mana abilities. S:Mode$ Continuous | Affected$ Permanent.EnchantedBy | AddHiddenKeyword$ CARDNAME can't attack or block. & CARDNAME can't crew Vehicles. | Description$ Enchanted permanent can't attack, block, or crew Vehicles, and its activated abilities can't be activated unless they're mana abilities.
S:Mode$ CantBeActivated | ValidCard$ Card.EnchantedBy | NonMana$ True S:Mode$ CantBeActivated | ValidCard$ Card.EnchantedBy | ValidSA$ Activated.nonManaAbility
Oracle:Enchant permanent\nEnchanted permanent can't attack, block, or crew Vehicles, and its activated abilities can't be activated unless they're mana abilities. Oracle:Enchant permanent\nEnchanted permanent can't attack, block, or crew Vehicles, and its activated abilities can't be activated unless they're mana abilities.

View File

@@ -4,7 +4,7 @@ Types:Legendary Creature Human Warrior
PT:3/5 PT:3/5
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDig | TriggerDescription$ Whenever CARDNAME enters the battlefield or a planeswalker you control dies, look at the top seven cards of your library. You may reveal a planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDig | TriggerDescription$ Whenever CARDNAME enters the battlefield or a planeswalker you control dies, look at the top seven cards of your library. You may reveal a planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Planeswalker.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDig | Secondary$ True | TriggerDescription$ Whenever CARDNAME enters the battlefield or a planeswalker you control dies, look at the top seven cards of your library. You may reveal a planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Planeswalker.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDig | Secondary$ True | TriggerDescription$ Whenever CARDNAME enters the battlefield or a planeswalker you control dies, look at the top seven cards of your library. You may reveal a planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
SVar:TrigDig:DB$ Dig | DigNum$ 7 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Planeswalker | RestRandomOrder$ True | Reveal$ True SVar:TrigDig:DB$ Dig | DigNum$ 7 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Planeswalker | RestRandomOrder$ True | ForceRevealToController$ True
S:Mode$ RaiseCost | ValidCard$ Planeswalker.YouCtrl | Type$ Loyalty | Cost$ AddCounter<1/LOYALTY> | Description$ Planeswalkers' loyalty abilities you activate cost an additional [+1] to activate. S:Mode$ RaiseCost | ValidCard$ Planeswalker.YouCtrl | Type$ Loyalty | Cost$ AddCounter<1/LOYALTY> | Description$ Planeswalkers' loyalty abilities you activate cost an additional [+1] to activate.
DeckNeeds:Type$Planeswalker DeckNeeds:Type$Planeswalker
Oracle:Whenever Carth the Lion enters the battlefield or a planeswalker you control dies, look at the top seven cards of your library. You may reveal a planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.\nPlaneswalkers' loyalty abilities you activate cost an additional [+1] to activate. Oracle:Whenever Carth the Lion enters the battlefield or a planeswalker you control dies, look at the top seven cards of your library. You may reveal a planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.\nPlaneswalkers' loyalty abilities you activate cost an additional [+1] to activate.

View File

@@ -1,7 +1,7 @@
Name:Consulate Turret Name:Consulate Turret
ManaCost:3 ManaCost:3
Types:Artifact Types:Artifact
A:AB$ PutCounter | Cost$ T | Defined$ You | CounterType$ ENERGY | CounterNum$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ You get {E} (an energy counter). A:AB$ PutCounter | Cost$ T | Defined$ You | CounterType$ ENERGY | CounterNum$ 1 | AILogic$ AtOppEOT | SpellDescription$ You get {E} (an energy counter).
A:AB$ DealDamage | Cost$ T PayEnergy<3> | ValidTgts$ Player,Planeswalker | TgtPrompt$ Select target player or planeswalker | NumDmg$ 2 | SpellDescription$ CARDNAME deals 2 damage to target player or planeswalker. A:AB$ DealDamage | Cost$ T PayEnergy<3> | ValidTgts$ Player,Planeswalker | TgtPrompt$ Select target player or planeswalker | NumDmg$ 2 | SpellDescription$ CARDNAME deals 2 damage to target player or planeswalker.
SVar:Picture:http://www.wizards.com/global/images/magic/general/consulate_turret.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/consulate_turret.jpg
Oracle:{T}: You get {E} (an energy counter).\n{T}, Pay {E}{E}{E}: Consulate Turret deals 2 damage to target player or planeswalker. Oracle:{T}: You get {E} (an energy counter).\n{T}, Pay {E}{E}{E}: Consulate Turret deals 2 damage to target player or planeswalker.

View File

@@ -1,7 +1,7 @@
Name:Damping Matrix Name:Damping Matrix
ManaCost:3 ManaCost:3
Types:Artifact Types:Artifact
S:Mode$ CantBeActivated | ValidCard$ Artifact,Creature | AffectedZone$ Battlefield | NonMana$ True | Description$ Activated abilities of artifacts and creatures can't be activated unless they're mana abilities. S:Mode$ CantBeActivated | ValidCard$ Artifact,Creature | ValidSA$ Activated.nonManaAbility | AffectedZone$ Battlefield | Description$ Activated abilities of artifacts and creatures can't be activated unless they're mana abilities.
SVar:NonStackingEffect:True SVar:NonStackingEffect:True
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/damping_matrix.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/damping_matrix.jpg

View File

@@ -2,10 +2,9 @@ Name:Divergent Transformations
ManaCost:6 R ManaCost:6 R
Types:Instant Types:Instant
K:Undaunted K:Undaunted
A:SP$ ChangeZone | Cost$ 6 R | ValidTgts$ Creature | TargetMin$ 2 | TargetMax$ 2 | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | SubAbility$ DBTransform | SpellDescription$ Exile two target creatures. For each of those creatures, its controller reveals cards from the top of their library until they reveal a creature card, puts that card onto the battlefield, then shuffles the rest into their library. A:SP$ ChangeZone | Cost$ 6 R | ValidTgts$ Creature | TargetMin$ 2 | TargetMax$ 2 | Origin$ Battlefield | Destination$ Exile | RememberLKI$ True | SubAbility$ DBTransform | SpellDescription$ Exile two target creatures. For each of those creatures, its controller reveals cards from the top of their library until they reveal a creature card, puts that card onto the battlefield, then shuffles the rest into their library.
SVar:DBTransform:DB$ RepeatEach | UseImprinted$ True | DefinedCards$ DirectRemembered | ChooseOrder$ True | Zone$ Exile | RepeatSubAbility$ DBReveal | SubAbility$ DBCleanRemembered SVar:DBTransform:DB$ RepeatEach | UseImprinted$ True | DefinedCards$ DirectRemembered | ChooseOrder$ True | Zone$ Exile | RepeatSubAbility$ DBReveal | SubAbility$ DBCleanRemembered
SVar:DBReveal:DB$ DigUntil | Defined$ ImprintedController | Amount$ 1 | Valid$ Creature | ValidDescription$ creature | RevealedDestination$ Library | RevealedLibraryPosition$ 0 | FoundDestination$ Battlefield | SubAbility$ DBCleanup | Shuffle$ True SVar:DBReveal:DB$ DigUntil | Defined$ ImprintedController | Amount$ 1 | Valid$ Creature | ValidDescription$ creature | RevealedDestination$ Library | RevealedLibraryPosition$ 0 | FoundDestination$ Battlefield | Shuffle$ True
SVar:DBCleanup:DB$ Cleanup | ClearImprinted$ True
SVar:DBCleanRemembered:DB$ Cleanup | ClearRemembered$ True SVar:DBCleanRemembered:DB$ Cleanup | ClearRemembered$ True
SVar:Picture:http://www.wizards.com/global/images/magic/general/divergent_transformations.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/divergent_transformations.jpg
Oracle:Undaunted (This spell costs {1} less to cast for each opponent.)\nExile two target creatures. For each of those creatures, its controller reveals cards from the top of their library until they reveal a creature card, puts that card onto the battlefield, then shuffles the rest into their library. Oracle:Undaunted (This spell costs {1} less to cast for each opponent.)\nExile two target creatures. For each of those creatures, its controller reveals cards from the top of their library until they reveal a creature card, puts that card onto the battlefield, then shuffles the rest into their library.

View File

@@ -3,7 +3,7 @@ ManaCost:3
Types:Artifact Types:Artifact
T:Mode$ CounterAddedOnce | ValidPlayer$ You | TriggerZones$ Battlefield | CounterType$ ENERGY | Execute$ TrigPutCounter | TriggerDescription$ Whenever you get one or more {E} (energy counters), put a +1/+1 counter on target creature you control. T:Mode$ CounterAddedOnce | ValidPlayer$ You | TriggerZones$ Battlefield | CounterType$ ENERGY | Execute$ TrigPutCounter | TriggerDescription$ Whenever you get one or more {E} (energy counters), put a +1/+1 counter on target creature you control.
SVar:TrigPutCounter:DB$ PutCounter | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | CounterType$ P1P1 | CounterNum$ 1 SVar:TrigPutCounter:DB$ PutCounter | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | CounterType$ P1P1 | CounterNum$ 1
A:AB$ PutCounter | Cost$ 4 T | Defined$ You | CounterType$ ENERGY | CounterNum$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ You get {E}. A:AB$ PutCounter | Cost$ 4 T | Defined$ You | CounterType$ ENERGY | CounterNum$ 1 | AILogic$ AtOppEOT | SpellDescription$ You get {E}.
DeckHas:Ability$Counters DeckHas:Ability$Counters
SVar:Picture:http://www.wizards.com/global/images/magic/general/fabrication_module.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/fabrication_module.jpg
Oracle:Whenever you get one or more {E} (energy counters), put a +1/+1 counter on target creature you control.\n{4}, {T}: You get {E}. Oracle:Whenever you get one or more {E} (energy counters), put a +1/+1 counter on target creature you control.\n{4}, {T}: You get {E}.

View File

@@ -5,7 +5,7 @@ K:Enchant permanent
A:SP$ Attach | Cost$ 3 W | ValidTgts$ Permanent | AITgts$ Creature | AILogic$ Curse A:SP$ Attach | Cost$ 3 W | ValidTgts$ Permanent | AITgts$ Creature | AILogic$ Curse
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigGainLife | TriggerDescription$ When CARDNAME enters the battlefield, you gain 4 life. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigGainLife | TriggerDescription$ When CARDNAME enters the battlefield, you gain 4 life.
SVar:TrigGainLife:DB$ GainLife | LifeAmount$ 4 SVar:TrigGainLife:DB$ GainLife | LifeAmount$ 4
S:Mode$ CantBeActivated | ValidCard$ Card.EnchantedBy | NonMana$ True | Description$ Enchanted permanent can't attack or block, and its activated abilities can't be activated unless they're mana abilities. S:Mode$ CantBeActivated | ValidCard$ Card.EnchantedBy | ValidSA$ Activated.nonManaAbility | Description$ Enchanted permanent can't attack or block, and its activated abilities can't be activated unless they're mana abilities.
S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddHiddenKeyword$ CARDNAME can't attack or block. S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddHiddenKeyword$ CARDNAME can't attack or block.
DeckHas:Ability$LifeGain DeckHas:Ability$LifeGain
SVar:Picture:http://www.wizards.com/global/images/magic/general/faiths_fetters.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/faiths_fetters.jpg

View File

@@ -16,5 +16,5 @@ Types:Instant
A:SP$ Effect | Cost$ W | Name$ Silence Effect | StaticAbilities$ STCantBeCast,STCantBeActivated | AILogic$ BeginningOfOppTurn | SubAbility$ DBChange | StackDescription$ SpellDescription | SpellDescription$ Your opponents can't cast spells or activate planeswalkers' loyalty abilities this turn. Exile CARDNAME. A:SP$ Effect | Cost$ W | Name$ Silence Effect | StaticAbilities$ STCantBeCast,STCantBeActivated | AILogic$ BeginningOfOppTurn | SubAbility$ DBChange | StackDescription$ SpellDescription | SpellDescription$ Your opponents can't cast spells or activate planeswalkers' loyalty abilities this turn. Exile CARDNAME.
SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile | StackDescription$ None SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile | StackDescription$ None
SVar:STCantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ Opponent | Description$ Your opponents can't cast spells. SVar:STCantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ Opponent | Description$ Your opponents can't cast spells.
SVar:STCantBeActivated:Mode$ CantBeActivated | Activator$ Opponent | EffectZone$ Command | ValidCard$ Planeswalker | Loyalty$ True | Description$ Your opponents can't activate planeswalkers' loyalty abilities. SVar:STCantBeActivated:Mode$ CantBeActivated | Activator$ Opponent | EffectZone$ Command | ValidCard$ Planeswalker | ValidSA$ Activated.Loyalty | Description$ Your opponents can't activate planeswalkers' loyalty abilities.
Oracle:Your opponents can't cast spells or activate planeswalkers' loyalty abilities this turn.\nExile Revel in Silence. Oracle:Your opponents can't cast spells or activate planeswalkers' loyalty abilities this turn.\nExile Revel in Silence.

View File

@@ -2,10 +2,11 @@ Name:Halana and Alena, Partners
ManaCost:2 R G ManaCost:2 R G
Types:Legendary Creature Human Ranger Types:Legendary Creature Human Ranger
PT:2/3 PT:2/3
K:Reach
K:First Strike
T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of combat on your turn, put X +1/+1 counters on another target creature you control, where X is NICKNAME's power. That creature gains haste until end of turn. T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of combat on your turn, put X +1/+1 counters on another target creature you control, where X is NICKNAME's power. That creature gains haste until end of turn.
SVar:TrigPutCounter:DB$ PutCounter | ValidTgts$ Creature.Other+YouCtrl | TgtPrompt$ Select another target creature you control | CounterType$ P1P1 | CounterNum$ X | SubAbility$ DBPump SVar:TrigPutCounter:DB$ PutCounter | ValidTgts$ Creature.Other+YouCtrl | TgtPrompt$ Select another target creature you control | CounterType$ P1P1 | CounterNum$ X | SubAbility$ DBPump
SVar:DBPump:DB$ Pump | Defined$ Targeted | KW$ Haste SVar:DBPump:DB$ Pump | Defined$ Targeted | KW$ Haste
SVar:X:Count$CardPower SVar:X:Count$CardPower
DeckHas:Ability$Counters DeckHas:Ability$Counters
Oracle:First strike, reach Oracle:First strike, reach\nAt the beginning of combat on your turn, put X +1/+1 counters on another target creature you control, where X is Halana and Alena's power. That creature gains haste until end of turn.
Oracle:At the beginning of combat on your turn, put X +1/+1 counters on another target creature you control, where X is Halana and Alena's power. That creature gains haste until end of turn.

View File

@@ -2,7 +2,7 @@ Name:Hand to Hand
ManaCost:2 R ManaCost:2 R
Types:Enchantment Types:Enchantment
S:Mode$ CantBeCast | ValidCard$ Instant | Phases$ BeginCombat->EndCombat | Description$ During combat, players can't cast instant spells or activate abilities that aren't mana abilities. S:Mode$ CantBeCast | ValidCard$ Instant | Phases$ BeginCombat->EndCombat | Description$ During combat, players can't cast instant spells or activate abilities that aren't mana abilities.
S:Mode$ CantBeActivated | ValidCard$ Card | Phases$ BeginCombat->EndCombat | NonMana$ True S:Mode$ CantBeActivated | ValidCard$ Card | Phases$ BeginCombat->EndCombat | ValidSA$ Activated.nonManaAbility
SVar:NonStackingEffect:True SVar:NonStackingEffect:True
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/hand_to_hand.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/hand_to_hand.jpg

View File

@@ -4,6 +4,6 @@ Types:Creature Spider
PT:5/7 PT:5/7
K:Reach K:Reach
T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigDig | TriggerDescription$ Undergrowth - When you cast this spell, reveal the top X cards of your library, where X is the number of creature cards in your graveyard. You may put a green permanent card with mana value X or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order. T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigDig | TriggerDescription$ Undergrowth - When you cast this spell, reveal the top X cards of your library, where X is the number of creature cards in your graveyard. You may put a green permanent card with mana value X or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.
SVar:TrigDig:DB$ Dig | DigNum$ X | Reveal$ True | ChangeNum$ 1 | ChangeValid$ Permanent.Green+cmcLEX | DestinationZone$ Battlefield | AILogic$ AtOppEndOfTurn | Optional$ True | RestRandomOrder$ True SVar:TrigDig:DB$ Dig | DigNum$ X | Reveal$ True | ChangeNum$ 1 | ChangeValid$ Permanent.Green+cmcLEX | DestinationZone$ Battlefield | AILogic$ AtOppEOT | Optional$ True | RestRandomOrder$ True
SVar:X:Count$TypeInYourYard.Creature SVar:X:Count$TypeInYourYard.Creature
Oracle:Reach\nUndergrowth — When you cast this spell, reveal the top X cards of your library, where X is the number of creature cards in your graveyard. You may put a green permanent card with mana value X or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order. Oracle:Reach\nUndergrowth — When you cast this spell, reveal the top X cards of your library, where X is the number of creature cards in your graveyard. You may put a green permanent card with mana value X or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.

View File

@@ -3,7 +3,7 @@ ManaCost:2 G
Types:Enchantment Types:Enchantment
K:Phasing K:Phasing
S:Mode$ Continuous | Affected$ Creature.withFlying | AddHiddenKeyword$ CARDNAME can't attack or block. | Description$ Creatures with flying can't attack or block, and their activated abilities with {T} in their costs can't be activated. S:Mode$ Continuous | Affected$ Creature.withFlying | AddHiddenKeyword$ CARDNAME can't attack or block. | Description$ Creatures with flying can't attack or block, and their activated abilities with {T} in their costs can't be activated.
S:Mode$ CantBeActivated | ValidCard$ Creature.withFlying | AffectedZone$ Battlefield | TapAbility$ True S:Mode$ CantBeActivated | ValidCard$ Creature.withFlying | ValidSA$ Activated.hasTapCost | AffectedZone$ Battlefield
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/katabatic_winds.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/katabatic_winds.jpg
Oracle:Phasing (This phases in or out before you untap during each of your untap steps. While it's phased out, it's treated as though it doesn't exist.)\nCreatures with flying can't attack or block, and their activated abilities with {T} in their costs can't be activated. Oracle:Phasing (This phases in or out before you untap during each of your untap steps. While it's phased out, it's treated as though it doesn't exist.)\nCreatures with flying can't attack or block, and their activated abilities with {T} in their costs can't be activated.

View File

@@ -3,6 +3,6 @@ ManaCost:2
Types:Artifact Types:Artifact
A:AB$ Pump | Cost$ T Discard<1/Card> | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ HIDDEN Unblockable | SpellDescription$ Up to one target creature can't be blocked this turn. A:AB$ Pump | Cost$ T Discard<1/Card> | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ HIDDEN Unblockable | SpellDescription$ Up to one target creature can't be blocked this turn.
T:Mode$ Untaps | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever CARDNAME becomes untapped, you may pay {2}. If you do, draw a card. T:Mode$ Untaps | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever CARDNAME becomes untapped, you may pay {2}. If you do, draw a card.
SVar:TrigDraw:AB$Draw | Cost$ 2 | Defined$ You | NumCards$ 1 SVar:TrigDraw:AB$ Draw | Cost$ 2 | Defined$ You | NumCards$ 1
SVar:Picture:http://www.wizards.com/global/images/magic/general/key_to_the_city.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/key_to_the_city.jpg
Oracle:{T}, Discard a card: Up to one target creature can't be blocked this turn.\nWhenever Key to the City becomes untapped, you may pay {2}. If you do, draw a card. Oracle:{T}, Discard a card: Up to one target creature can't be blocked this turn.\nWhenever Key to the City becomes untapped, you may pay {2}. If you do, draw a card.

View File

@@ -3,7 +3,7 @@ ManaCost:1 G U
Types:Legendary Creature Merfolk Shaman Types:Legendary Creature Merfolk Shaman
PT:2/4 PT:2/4
A:AB$ Pump | Cost$ tapXType<1/Merfolk.Other> | CostDesc$ Tap another untapped Merfolk you control: | Defined$ Self | KW$ HIDDEN Unblockable | AILogic$ BeforeCombat | SpellDescription$ CARDNAME can't be blocked this turn. A:AB$ Pump | Cost$ tapXType<1/Merfolk.Other> | CostDesc$ Tap another untapped Merfolk you control: | Defined$ Self | KW$ HIDDEN Unblockable | AILogic$ BeforeCombat | SpellDescription$ CARDNAME can't be blocked this turn.
A:AB$ Draw | Cost$ tapXType<3/Merfolk> | CostDesc$ Tap three untapped Merfolk you control: | NumCards$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. A:AB$ Draw | Cost$ tapXType<3/Merfolk> | CostDesc$ Tap three untapped Merfolk you control: | NumCards$ 1 | AILogic$ AtOppEOT | SpellDescription$ Draw a card.
A:AB$ PutCounterAll | Cost$ tapXType<5/Merfolk> | CostDesc$ Tap five untapped Merfolk you control: | ValidCards$ Merfolk.YouCtrl | CounterType$ P1P1 | CounterNum$ 1 | AILogic$ AtOppEOT | SpellDescription$ Put a +1/+1 counter on each Merfolk you control. A:AB$ PutCounterAll | Cost$ tapXType<5/Merfolk> | CostDesc$ Tap five untapped Merfolk you control: | ValidCards$ Merfolk.YouCtrl | CounterType$ P1P1 | CounterNum$ 1 | AILogic$ AtOppEOT | SpellDescription$ Put a +1/+1 counter on each Merfolk you control.
DeckHints:Type$Merfolk DeckHints:Type$Merfolk
SVar:BuffedBy:Merfolk SVar:BuffedBy:Merfolk

View File

@@ -9,7 +9,7 @@ SVar:DBShuffle:DB$ Shuffle | Defined$ ParentTarget | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:TargetedPlayer$CardsInLibrary SVar:X:TargetedPlayer$CardsInLibrary
SVar:Y:Remembered$Valid Card.NamedCard SVar:Y:Remembered$Valid Card.NamedCard
SVar:Z:Number$ChosenNumber SVar:Z:Count$ChosenNumber
AI:RemoveDeck:All AI:RemoveDeck:All
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/mindblaze.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/mindblaze.jpg

View File

@@ -4,7 +4,7 @@ Types:Legendary Creature Minotaur Warrior
PT:6/6 PT:6/6
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddPower$ AffectedX | Description$ Each creature you control gets +1/+0 for each time it has attacked this turn. S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddPower$ AffectedX | Description$ Each creature you control gets +1/+0 for each time it has attacked this turn.
SVar:AffectedX:Count$CardNumAttacksThisTurn SVar:AffectedX:Count$CardNumAttacksThisTurn
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Land.YouCtrl | TriggerZones$ Battlefield | PlayerTurn$ True | Phase$ Main1,Main2 | Execute$ TrigAddPhase | TriggerDescription$ Landfall - Whenever a land enters the battlefield under your control, if it's your main phase, there's an additional combat phase after this phase. At the beginning of that combat, untap all creatures you control. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | AILogic$ SafeToHold | ValidCard$ Land.YouCtrl | TriggerZones$ Battlefield | PlayerTurn$ True | Phase$ Main1,Main2 | Execute$ TrigAddPhase | TriggerDescription$ Landfall - Whenever a land enters the battlefield under your control, if it's your main phase, there's an additional combat phase after this phase. At the beginning of that combat, untap all creatures you control.
SVar:TrigAddPhase:DB$ AddPhase | ExtraPhase$ Combat | ConditionPhases$ Main1,Main2 | ExtraPhaseDelayedTrigger$ DelTrigUntap | ExtraPhaseDelayedTriggerExcute$ TrigUntapAll SVar:TrigAddPhase:DB$ AddPhase | ExtraPhase$ Combat | ConditionPhases$ Main1,Main2 | ExtraPhaseDelayedTrigger$ DelTrigUntap | ExtraPhaseDelayedTriggerExcute$ TrigUntapAll
SVar:DelTrigUntap:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerDescription$ At the beginning of that combat, untap all creatures you control. SVar:DelTrigUntap:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerDescription$ At the beginning of that combat, untap all creatures you control.
SVar:TrigUntapAll:DB$ UntapAll | ValidCards$ Creature.YouCtrl SVar:TrigUntapAll:DB$ UntapAll | ValidCards$ Creature.YouCtrl

View File

@@ -2,7 +2,7 @@ Name:Muzzio, Visionary Architect
ManaCost:1 U U ManaCost:1 U U
Types:Legendary Creature Human Artificer Types:Legendary Creature Human Artificer
PT:1/3 PT:1/3
A:AB$ Dig | Cost$ 3 U T | DigNum$ X | Optional$ True | ChangeValid$ Artifact | DestinationZone$ Battlefield | AILogic$ AtOppEndOfTurn | SpellDescription$ Look at the top X cards of your library, where X is the highest mana value among artifacts you control. You may put an artifact card from among them onto the battlefield. Put the rest on the bottom of your library in any order. A:AB$ Dig | Cost$ 3 U T | DigNum$ X | Optional$ True | ChangeValid$ Artifact | DestinationZone$ Battlefield | AILogic$ AtOppEOT | SpellDescription$ Look at the top X cards of your library, where X is the highest mana value among artifacts you control. You may put an artifact card from among them onto the battlefield. Put the rest on the bottom of your library in any order.
SVar:X:Count$HighestCMC_Artifact.YouCtrl+inZoneBattlefield SVar:X:Count$HighestCMC_Artifact.YouCtrl+inZoneBattlefield
SVar:Picture:http://www.wizards.com/global/images/magic/general/muzzio_visionary_architect.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/muzzio_visionary_architect.jpg
Oracle:{3}{U}, {T}: Look at the top X cards of your library, where X is the highest mana value among artifacts you control. You may put an artifact card from among them onto the battlefield. Put the rest on the bottom of your library in any order. Oracle:{3}{U}, {T}: Look at the top X cards of your library, where X is the highest mana value among artifacts you control. You may put an artifact card from among them onto the battlefield. Put the rest on the bottom of your library in any order.

View File

@@ -1,6 +1,6 @@
Name:Mystic Archaeologist Name:Mystic Archaeologist
ManaCost:1 U ManaCost:1 U
Types:Creature Human Wizard Types:Creature Human Wizard
A:AB$ Draw | Cost$ 3 U U | Defined$ You | NumCards$ 2 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw two cards. A:AB$ Draw | Cost$ 3 U U | Defined$ You | NumCards$ 2 | AILogic$ AtOppEOT | SpellDescription$ Draw two cards.
Oracle:{3}{U}{U}: Draw two cards. Oracle:{3}{U}{U}: Draw two cards.
PT:2/1 PT:2/1

View File

@@ -3,7 +3,7 @@ ManaCost:2 U U R R
Types:Legendary Creature Dragon Wizard Types:Legendary Creature Dragon Wizard
PT:4/4 PT:4/4
K:Flying K:Flying
A:AB$ Draw | Cost$ T | NumCards$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. A:AB$ Draw | Cost$ T | NumCards$ 1 | AILogic$ AtOppEOT | SpellDescription$ Draw a card.
T:Mode$ Drawn | ValidCard$ Card.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDealDamage | TriggerDescription$ Whenever you draw a card, CARDNAME deals 1 damage to any target. T:Mode$ Drawn | ValidCard$ Card.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDealDamage | TriggerDescription$ Whenever you draw a card, CARDNAME deals 1 damage to any target.
SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1
SVar:Picture:http://www.wizards.com/global/images/magic/general/niv_mizzet_the_firemind.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/niv_mizzet_the_firemind.jpg

View File

@@ -4,6 +4,6 @@ Types:Enchantment Aura Curse
K:Enchant player K:Enchant player
A:SP$ Attach | Cost$ 6 W W | ValidTgts$ Player | AILogic$ Curse A:SP$ Attach | Cost$ 6 W W | ValidTgts$ Player | AILogic$ Curse
S:Mode$ Continuous | Affected$ Creature.EnchantedPlayerCtrl | SetPower$ 1 | SetToughness$ 1 | RemoveAllAbilities$ True | Description$ Creatures enchanted player controls lose all abilities and have base power and toughness 1/1. S:Mode$ Continuous | Affected$ Creature.EnchantedPlayerCtrl | SetPower$ 1 | SetToughness$ 1 | RemoveAllAbilities$ True | Description$ Creatures enchanted player controls lose all abilities and have base power and toughness 1/1.
S:Mode$ CantBeActivated | Activator$ Player.EnchantedBy | NonMana$ True | NonLoyalty$ True | Description$ Enchanted player can't activate abilities that aren't mana abilities or loyalty abilities. S:Mode$ CantBeActivated | Activator$ Player.EnchantedBy | ValidSA$ Activated.nonManaAbility+nonLoyalty | Description$ Enchanted player can't activate abilities that aren't mana abilities or loyalty abilities.
SVar:Picture:http://www.wizards.com/global/images/magic/general/overwhelming_splendor.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/overwhelming_splendor.jpg
Oracle:Enchant player\nCreatures enchanted player controls lose all abilities and have base power and toughness 1/1.\nEnchanted player can't activate abilities that aren't mana abilities or loyalty abilities. Oracle:Enchant player\nCreatures enchanted player controls lose all abilities and have base power and toughness 1/1.\nEnchanted player can't activate abilities that aren't mana abilities or loyalty abilities.

View File

@@ -3,7 +3,7 @@ ManaCost:1
Types:Artifact Types:Artifact
K:ETBReplacement:Other:DBNameCard K:ETBReplacement:Other:DBNameCard
SVar:DBNameCard:DB$ NameCard | Defined$ You | SpellDescription$ As CARDNAME enters the battlefield, choose a card name. SVar:DBNameCard:DB$ NameCard | Defined$ You | SpellDescription$ As CARDNAME enters the battlefield, choose a card name.
S:Mode$ CantBeActivated | ValidCard$ Card.NamedCard | NonMana$ True | Description$ Activated abilities of sources with the chosen name can't be activated unless they're mana abilities. S:Mode$ CantBeActivated | ValidCard$ Card.NamedCard | ValidSA$ Activated.nonManaAbility | Description$ Activated abilities of sources with the chosen name can't be activated unless they're mana abilities.
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/pithing_needle.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/pithing_needle.jpg
Oracle:As Pithing Needle enters the battlefield, choose a card name.\nActivated abilities of sources with the chosen name can't be activated unless they're mana abilities. Oracle:As Pithing Needle enters the battlefield, choose a card name.\nActivated abilities of sources with the chosen name can't be activated unless they're mana abilities.

View File

@@ -1,7 +1,7 @@
Name:Pristine Talisman Name:Pristine Talisman
ManaCost:3 ManaCost:3
Types:Artifact Types:Artifact
A:AB$ Mana | Cost$ T | Produced$ C | SubAbility$ DBGainLife | SpellDescription$ Add {C}. You gain 1 life. A:AB$ Mana | Cost$ T | Produced$ C | SubAbility$ DBGainLife | AILogic$ AtOppEOT | SpellDescription$ Add {C}. You gain 1 life.
SVar:DBGainLife:DB$ GainLife | LifeAmount$ 1 | Defined$ You SVar:DBGainLife:DB$ GainLife | LifeAmount$ 1 | Defined$ You
SVar:Picture:http://www.wizards.com/global/images/magic/general/pristine_talisman.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/pristine_talisman.jpg
Oracle:{T}: Add {C}. You gain 1 life. Oracle:{T}: Add {C}. You gain 1 life.

View File

@@ -5,7 +5,7 @@ PT:2/2
K:ETBReplacement:Other:ChooseNumber K:ETBReplacement:Other:ChooseNumber
SVar:ChooseNumber:DB$ ChooseNumber | Defined$ You | SpellDescription$ As CARDNAME enters the battlefield, choose a number. SVar:ChooseNumber:DB$ ChooseNumber | Defined$ You | SpellDescription$ As CARDNAME enters the battlefield, choose a number.
S:Mode$ CantBeCast | ValidCard$ Card.nonCreature+cmcEQX | Description$ Noncreature spells with mana value equal to the chosen number can't be cast. S:Mode$ CantBeCast | ValidCard$ Card.nonCreature+cmcEQX | Description$ Noncreature spells with mana value equal to the chosen number can't be cast.
SVar:X:Number$ChosenNumber SVar:X:Count$ChosenNumber
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/sanctum_prelate.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/sanctum_prelate.jpg
Oracle:As Sanctum Prelate enters the battlefield, choose a number.\nNoncreature spells with mana value equal to the chosen number can't be cast. Oracle:As Sanctum Prelate enters the battlefield, choose a number.\nNoncreature spells with mana value equal to the chosen number can't be cast.

View File

@@ -5,6 +5,6 @@ K:Enchant creature
K:UpkeepCost:W W K:UpkeepCost:W W
A:SP$ Attach | Cost$ W W | ValidTgts$ Creature | AILogic$ Curse A:SP$ Attach | Cost$ W W | ValidTgts$ Creature | AILogic$ Curse
S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddHiddenKeyword$ CARDNAME can't attack or block. | Description$ Enchanted creature can't attack or block, and its activated abilities with {T} in their costs can't be activated. S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddHiddenKeyword$ CARDNAME can't attack or block. | Description$ Enchanted creature can't attack or block, and its activated abilities with {T} in their costs can't be activated.
S:Mode$ CantBeActivated | ValidCard$ Card.EnchantedBy | TapAbility$ True S:Mode$ CantBeActivated | ValidCard$ Card.EnchantedBy | ValidSA$ Activated.hasTapCost
SVar:Picture:http://www.wizards.com/global/images/magic/general/serra_bestiary.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/serra_bestiary.jpg
Oracle:Enchant creature\nAt the beginning of your upkeep, sacrifice Serra Bestiary unless you pay {W}{W}.\nEnchanted creature can't attack or block, and its activated abilities with {T} in their costs can't be activated. Oracle:Enchant creature\nAt the beginning of your upkeep, sacrifice Serra Bestiary unless you pay {W}{W}.\nEnchanted creature can't attack or block, and its activated abilities with {T} in their costs can't be activated.

View File

@@ -6,7 +6,7 @@ SVar:ChoosePlayer:DB$ ChoosePlayer | Defined$ You | Choices$ Player.Opponent | C
SVar:DBLook:DB$ RevealHand | Defined$ ChosenPlayer | SubAbility$ DBNameCard SVar:DBLook:DB$ RevealHand | Defined$ ChosenPlayer | SubAbility$ DBNameCard
SVar:DBNameCard:DB$ NameCard | Defined$ You | SubAbility$ DBClear SVar:DBNameCard:DB$ NameCard | Defined$ You | SubAbility$ DBClear
SVar:DBClear:DB$ Cleanup | ClearChosenPlayer$ True SVar:DBClear:DB$ Cleanup | ClearChosenPlayer$ True
S:Mode$ CantBeActivated | ValidCard$ Card.NamedCard | NonMana$ True | Description$ Activated abilities of sources with the chosen name can't be activated unless they're mana abilities. S:Mode$ CantBeActivated | ValidCard$ Card.NamedCard | ValidSA$ Activated.nonManaAbility | Description$ Activated abilities of sources with the chosen name can't be activated unless they're mana abilities.
AI:RemoveDeck:Random AI:RemoveDeck:Random
# TODO: Might improve AI logic to support it (the AI needs to pick cards that actually have activated nonmana abilities on them) # TODO: Might improve AI logic to support it (the AI needs to pick cards that actually have activated nonmana abilities on them)
AI:RemoveDeck:All AI:RemoveDeck:All

View File

@@ -4,5 +4,5 @@ Types:Creature Spirit Pirate
PT:1/1 PT:1/1
K:Flash K:Flash
K:Flying K:Flying
A:AB$ Draw | Cost$ 3 U | NumCards$ 1 | Defined$ You | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. A:AB$ Draw | Cost$ 3 U | NumCards$ 1 | Defined$ You | AILogic$ AtOppEOT | SpellDescription$ Draw a card.
Oracle:Flash (You may cast this spell any time you could cast an instant.)\nFlying\n{3}{U}: Draw a card. Oracle:Flash (You may cast this spell any time you could cast an instant.)\nFlying\n{3}{U}: Draw a card.

View File

@@ -4,8 +4,6 @@ Types:Artifact Creature Insect
PT:-1/-1 PT:-1/-1
K:Sunburst K:Sunburst
A:AB$ RemoveCounter | Cost$ SubCounter<2/P1P1> | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | CounterType$ Any | CounterNum$ 1 | SpellDescription$ Remove a counter from target permanent. A:AB$ RemoveCounter | Cost$ SubCounter<2/P1P1> | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | CounterType$ Any | CounterNum$ 1 | SpellDescription$ Remove a counter from target permanent.
#TODO: For some reason the AI removes beneficial counters from its own permanents with this card.
AI:RemoveDeck:All
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:NeedsToPlayVar:Z GE3 SVar:NeedsToPlayVar:Z GE3
SVar:NoZeroToughnessAI:True SVar:NoZeroToughnessAI:True

View File

@@ -10,7 +10,7 @@ SVar:IncrementLoss:DB$ StoreSVar | SVar$ Loss | Type$ CountSVar | Expression$ Lo
SVar:SetFilpsDone:DB$ StoreSVar | SVar$ FlipsDone | Type$ CountSVar | Expression$ TimesToFlip SVar:SetFilpsDone:DB$ StoreSVar | SVar$ FlipsDone | Type$ CountSVar | Expression$ TimesToFlip
# Draw Cards # Draw Cards
SVar:DrawIfWin:DB$ Draw | Defined$ You | NumCards$ CardsToDraw | ConditionCheckSVar$ Loss | ConditionSVarCompare$ EQ0 SVar:DrawIfWin:DB$ Draw | Defined$ You | NumCards$ CardsToDraw | ConditionCheckSVar$ Loss | ConditionSVarCompare$ EQ0
SVar:TimesToFlip:Number$ChosenNumber SVar:TimesToFlip:Count$ChosenNumber
SVar:FlipsDone:Number$0 SVar:FlipsDone:Number$0
SVar:Loss:Number$0 SVar:Loss:Number$0
SVar:CardsToDraw:Count$ChosenNumber/Times.2 SVar:CardsToDraw:Count$ChosenNumber/Times.2

View File

@@ -1,7 +1,7 @@
Name:Strixhaven Stadium Name:Strixhaven Stadium
ManaCost:3 ManaCost:3
Types:Artifact Types:Artifact
A:AB$ Mana | Cost$ T | Produced$ C | SubAbility$ DBPutCounter | SpellDescription$ Add {C}. Put a point counter on CARDNAME. A:AB$ Mana | Cost$ T | Produced$ C | SubAbility$ DBPutCounter | AILogic$ AtOppEOT | SpellDescription$ Add {C}. Put a point counter on CARDNAME.
SVar:DBPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ POINT | CounterNum$ 1 SVar:DBPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ POINT | CounterNum$ 1
T:Mode$ DamageDone | ValidSource$ Creature | ValidTarget$ You | CombatDamage$ True | Execute$ TrigRemove | TriggerZones$ Battlefield | TriggerDescription$ Whenever a creature deals combat damage to you, remove a point counter from CARDNAME. T:Mode$ DamageDone | ValidSource$ Creature | ValidTarget$ You | CombatDamage$ True | Execute$ TrigRemove | TriggerZones$ Battlefield | TriggerDescription$ Whenever a creature deals combat damage to you, remove a point counter from CARDNAME.
SVar:TrigRemove:DB$ RemoveCounter | Defined$ Self | CounterType$ POINT | CounterNum$ 1 SVar:TrigRemove:DB$ RemoveCounter | Defined$ Self | CounterType$ POINT | CounterNum$ 1

View File

@@ -5,6 +5,6 @@ PT:3/3
K:Flash K:Flash
K:Flying K:Flying
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigTuck | TriggerDescription$ When CARDNAME enters the battlefield, choose up to one target creature spell or planeswalker spell. Its owner puts it on the top or bottom of their library. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigTuck | TriggerDescription$ When CARDNAME enters the battlefield, choose up to one target creature spell or planeswalker spell. Its owner puts it on the top or bottom of their library.
SVar:TrigTuck:DB$ ChangeZone | ValidTgts$ Card.inZoneStack+Creature,Card.inZoneStack+Planeswalker | TgtZone$ Stack | TgtPrompt$ Select up to one target creature spell or planeswalker spell | AlternativeDecider$ TargetedController | Origin$ Stack | Fizzle$ True | Destination$ Library | LibraryPosition$ 0 | DestinationAlternative$ Library | LibraryPositionAlternative$ -1 | AlternativeDestinationMessage$ Would you like to put the card on the top of your library (and not on the bottom)? | SpellDescription$ Choose up to one target creature spell or planeswalker spell. Its owner puts it on the top or bottom of their library. SVar:TrigTuck:DB$ ChangeZone | ValidTgts$ Card.inZoneStack+Creature,Card.inZoneStack+Planeswalker | TgtZone$ Stack | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select up to one target creature spell or planeswalker spell | AlternativeDecider$ TargetedController | Origin$ Stack | Fizzle$ True | Destination$ Library | LibraryPosition$ 0 | DestinationAlternative$ Library | LibraryPositionAlternative$ -1 | AlternativeDestinationMessage$ Would you like to put the card on the top of your library (and not on the bottom)? | SpellDescription$ Choose up to one target creature spell or planeswalker spell. Its owner puts it on the top or bottom of their library.
K:Evoke:ExileFromHand<1/Card.Blue+Other/blue card> K:Evoke:ExileFromHand<1/Card.Blue+Other/blue card>
Oracle:Flash\nFlying\nWhen Subtlety enters the battlefield, choose up to one target creature spell or planeswalker spell. Its owner puts it on the top or bottom of their library.\nEvoke—Exile a blue card from your hand. Oracle:Flash\nFlying\nWhen Subtlety enters the battlefield, choose up to one target creature spell or planeswalker spell. Its owner puts it on the top or bottom of their library.\nEvoke—Exile a blue card from your hand.

View File

@@ -1,8 +1,8 @@
Name:Sudden Disappearance Name:Sudden Disappearance
ManaCost:5 W ManaCost:5 W
Types:Sorcery Types:Sorcery
A:SP$ ChangeZoneAll | Cost$ 5 W | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Player | TgtPrompt$ Select target player | ChangeType$ Permanent.nonLand | RememberChanged$ True | SubAbility$ DelTrig | IsCurse$ True | SpellDescription$ Exile all nonland permanents target player controls. Return the exiled cards to the battlefield under their owners control at the beginning of the next end step. A:SP$ ChangeZoneAll | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Player | TgtPrompt$ Select target player | ChangeType$ Permanent.nonLand | RememberChanged$ True | SubAbility$ DelTrig | IsCurse$ True | SpellDescription$ Exile all nonland permanents target player controls. Return the exiled cards to the battlefield under their owner's control at the beginning of the next end step.
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturn | RememberObjects$ RememberedLKI | TriggerDescription$ Return exiled permanents to the battlefield. | SubAbility$ DBCleanup SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturn | RememberObjects$ RememberedLKI | TriggerDescription$ Return the exiled cards to the battlefield under their owner's control at the beginning of the next end step. | SubAbility$ DBCleanup
SVar:TrigReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI SVar:TrigReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
AI:RemoveDeck:All AI:RemoveDeck:All

View File

@@ -3,7 +3,7 @@ ManaCost:7 G G
Types:Legendary Artifact Types:Legendary Artifact
S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ X | EffectZone$ All | Description$ CARDNAME costs {X} less to cast, where X is the greatest power among creatures you control. S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ X | EffectZone$ All | Description$ CARDNAME costs {X} less to cast, where X is the greatest power among creatures you control.
SVar:X:Count$GreatestPower_Creature.YouCtrl SVar:X:Count$GreatestPower_Creature.YouCtrl
A:AB$ Mana | Cost$ T | Produced$ G | Amount$ 2 | SubAbility$ DBGainLife | SpellDescription$ Add {G}{G}. You gain 2 life. A:AB$ Mana | Cost$ T | Produced$ G | Amount$ 2 | SubAbility$ DBGainLife | AILogic$ AtOppEOT | SpellDescription$ Add {G}{G}. You gain 2 life.
SVar:DBGainLife:DB$ GainLife | LifeAmount$ 2 SVar:DBGainLife:DB$ GainLife | LifeAmount$ 2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.nonToken+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever a nontoken creature enters the battlefield under your control, put a +1/+1 counter on it and draw a card. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.nonToken+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever a nontoken creature enters the battlefield under your control, put a +1/+1 counter on it and draw a card.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ TriggeredCardLKICopy | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBDraw SVar:TrigPutCounter:DB$ PutCounter | Defined$ TriggeredCardLKICopy | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBDraw

View File

@@ -1,7 +1,7 @@
Name:The Immortal Sun Name:The Immortal Sun
ManaCost:6 ManaCost:6
Types:Legendary Artifact Types:Legendary Artifact
S:Mode$ CantBeActivated | Activator$ Player | ValidCard$ Planeswalker | Loyalty$ True | Description$ Players can't activate planeswalkers' loyalty abilities. S:Mode$ CantBeActivated | Activator$ Player | ValidCard$ Planeswalker | ValidSA$ Activated.Loyalty | Description$ Players can't activate planeswalkers' loyalty abilities.
T:Mode$ Phase | Phase$ Draw | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ At the beginning of your draw step, draw an additional card. T:Mode$ Phase | Phase$ Draw | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ At the beginning of your draw step, draw an additional card.
SVar:TrigDraw:DB$ Draw | NumCards$ 1 SVar:TrigDraw:DB$ Draw | NumCards$ 1
S:Mode$ ReduceCost | Type$ Spell | Activator$ You | Amount$ 1 | Description$ Spells you cast cost {1} less to cast. S:Mode$ ReduceCost | Type$ Spell | Activator$ You | Amount$ 1 | Description$ Spells you cast cost {1} less to cast.

View File

@@ -1,7 +1,7 @@
Name:Treasure Trove Name:Treasure Trove
ManaCost:2 U U ManaCost:2 U U
Types:Enchantment Types:Enchantment
A:AB$ Draw | Cost$ 2 U U | NumCards$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. A:AB$ Draw | Cost$ 2 U U | NumCards$ 1 | AILogic$ AtOppEOT | SpellDescription$ Draw a card.
SVar:NonStackingEffect:True SVar:NonStackingEffect:True
SVar:Picture:http://www.wizards.com/global/images/magic/general/treasure_trove.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/treasure_trove.jpg
Oracle:{2}{U}{U}: Draw a card. Oracle:{2}{U}{U}: Draw a card.

View File

@@ -1,6 +1,6 @@
Name:Vivien's Arkbow Name:Vivien's Arkbow
ManaCost:1 G ManaCost:1 G
Types:Legendary Artifact Types:Legendary Artifact
A:AB$ Dig | Cost$ X T Discard<1/Card> | DigNum$ X | AILogic$ AtOppEndOfTurn | Optional$ True | Reveal$ False | ChangeNum$ 1 | ChangeValid$ Creature.cmcLEX | DestinationZone$ Battlefield | DestinationZone2$ Library | LibraryPosition$ -1 | RestRandomOrder$ True | SpellDescription$ Look at the top X cards of your library. You may put a creature card with mana value X or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order. A:AB$ Dig | Cost$ X T Discard<1/Card> | DigNum$ X | AILogic$ AtOppEOT | Optional$ True | Reveal$ False | ChangeNum$ 1 | ChangeValid$ Creature.cmcLEX | DestinationZone$ Battlefield | DestinationZone2$ Library | LibraryPosition$ -1 | RestRandomOrder$ True | SpellDescription$ Look at the top X cards of your library. You may put a creature card with mana value X or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.
SVar:X:Count$xPaid SVar:X:Count$xPaid
Oracle:{X}, {T}, Discard a card: Look at the top X cards of your library. You may put a creature card with mana value X or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order. Oracle:{X}, {T}, Discard a card: Look at the top X cards of your library. You may put a creature card with mana value X or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.

View File

@@ -4,7 +4,7 @@ Types:Sorcery
A:SP$ ChooseNumber | Cost$ 3 B R | SubAbility$ DBVoidDestroyAll | SpellDescription$ Choose a number. Destroy all artifacts and creatures with mana value equal to that number. Then target player reveals their hand and discards all nonland cards with mana value equal to the number. A:SP$ ChooseNumber | Cost$ 3 B R | SubAbility$ DBVoidDestroyAll | SpellDescription$ Choose a number. Destroy all artifacts and creatures with mana value equal to that number. Then target player reveals their hand and discards all nonland cards with mana value equal to the number.
SVar:DBVoidDestroyAll:DB$ DestroyAll | ValidCards$ Artifact.cmcEQX,Creature.cmcEQX | SubAbility$ DBVoidRevealDiscard SVar:DBVoidDestroyAll:DB$ DestroyAll | ValidCards$ Artifact.cmcEQX,Creature.cmcEQX | SubAbility$ DBVoidRevealDiscard
SVar:DBVoidRevealDiscard:DB$ Discard | ValidTgts$ Player | TgtPrompt$ Select target player | Mode$ RevealDiscardAll | DiscardValid$ Card.nonLand+cmcEQX SVar:DBVoidRevealDiscard:DB$ Discard | ValidTgts$ Player | TgtPrompt$ Select target player | Mode$ RevealDiscardAll | DiscardValid$ Card.nonLand+cmcEQX
SVar:X:Number$ChosenNumber SVar:X:Count$ChosenNumber
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/void.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/void.jpg
Oracle:Choose a number. Destroy all artifacts and creatures with mana value equal to that number. Then target player reveals their hand and discards all nonland cards with mana value equal to the number. Oracle:Choose a number. Destroy all artifacts and creatures with mana value equal to that number. Then target player reveals their hand and discards all nonland cards with mana value equal to the number.

View File

@@ -1,7 +1,7 @@
Name:Whispers of the Muse Name:Whispers of the Muse
ManaCost:U ManaCost:U
Types:Instant Types:Instant
A:SP$ Draw | Cost$ U | NumCards$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. A:SP$ Draw | Cost$ U | NumCards$ 1 | AILogic$ AtOppEOT | SpellDescription$ Draw a card.
K:Buyback:5 K:Buyback:5
SVar:Picture:http://www.wizards.com/global/images/magic/general/whispers_of_the_muse.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/whispers_of_the_muse.jpg
Oracle:Buyback {5} (You may pay an additional {5} as you cast this spell. If you do, put this card into your hand as it resolves.)\nDraw a card. Oracle:Buyback {5} (You may pay an additional {5} as you cast this spell. If you do, put this card into your hand as it resolves.)\nDraw a card.

View File

@@ -11,7 +11,7 @@ SVar:DBDamage:DB$ DealDamage | NumDmg$ Damage | Defined$ You
SVar:DBEffect:DB$ Effect | StaticAbilities$ MayPlay | Stackable$ False | ConditionCheckSVar$ Y | ConditionSVarCompare$ EQ5 | SubAbility$ DBCleanup SVar:DBEffect:DB$ Effect | StaticAbilities$ MayPlay | Stackable$ False | ConditionCheckSVar$ Y | ConditionSVarCompare$ EQ5 | SubAbility$ DBCleanup
SVar:MayPlay:Mode$ Continuous | EffectZone$ Command | Affected$ Card.nonLand+YouOwn | MayPlay$ True | MayPlayWithoutManaCost$ True | AffectedZone$ Hand | Description$ You may cast spells from your hand this turn without paying their mana costs. SVar:MayPlay:Mode$ Continuous | EffectZone$ Command | Affected$ Card.nonLand+YouOwn | MayPlay$ True | MayPlayWithoutManaCost$ True | AffectedZone$ Hand | Description$ You may cast spells from your hand this turn without paying their mana costs.
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Number$ChosenNumber SVar:X:Count$ChosenNumber
SVar:Y:Count$RememberedNumber SVar:Y:Count$RememberedNumber
SVar:Damage:SVar$Losses/Times.2 SVar:Damage:SVar$Losses/Times.2
Oracle:Flying\nWhenever Yusri, Fortune's Flame attacks, choose a number between 1 and 5. Flip that many coins. For each flip you win, draw a card. For each flip you lose, Yusri deals 2 damage to you. If you won five flips this way, you may cast spells from your hand this turn without paying their mana costs. Oracle:Flying\nWhenever Yusri, Fortune's Flame attacks, choose a number between 1 and 5. Flip that many coins. For each flip you win, draw a card. For each flip you lose, Yusri deals 2 damage to you. If you won five flips this way, you may cast spells from your hand this turn without paying their mana costs.

View File

@@ -286,6 +286,7 @@ lblTryAgain=Neu
lblAddAPlayer=Spieler hinzufügen lblAddAPlayer=Spieler hinzufügen
lblVariants=Varianten lblVariants=Varianten
lblRandom=Zufällig lblRandom=Zufällig
lblGamesInMatch=Games in match:
#VSubmenuConstructed.java #VSubmenuConstructed.java
lblConstructedMode=Constructed-Modus lblConstructedMode=Constructed-Modus
lblConstructed=Constructed lblConstructed=Constructed

View File

@@ -287,6 +287,7 @@ lblTryAgain=Try Again
lblAddAPlayer=Add a Player lblAddAPlayer=Add a Player
lblVariants=Variants lblVariants=Variants
lblRandom=Random lblRandom=Random
lblGamesInMatch=Games in match:
#VSubmenuConstructed.java #VSubmenuConstructed.java
lblConstructedMode=Constructed Mode lblConstructedMode=Constructed Mode
lblConstructed=Constructed lblConstructed=Constructed

View File

@@ -287,6 +287,7 @@ lblTryAgain=Probar de nuevo
lblAddAPlayer=Añadir jugador lblAddAPlayer=Añadir jugador
lblVariants=Variantes lblVariants=Variantes
lblRandom=Aleatorio lblRandom=Aleatorio
lblGamesInMatch=Games in match:
#VSubmenuConstructed.java #VSubmenuConstructed.java
lblConstructedMode=Modo Construido lblConstructedMode=Modo Construido
lblConstructed=Construido lblConstructed=Construido

View File

@@ -286,6 +286,7 @@ lblTryAgain=Riprova
lblAddAPlayer=Aggiungi un giocatore lblAddAPlayer=Aggiungi un giocatore
lblVariants=Varianti lblVariants=Varianti
lblRandom=Casuale lblRandom=Casuale
lblGamesInMatch=Games in match:
#VSubmenuConstructed.java #VSubmenuConstructed.java
lblConstructedMode=Modalità costruita lblConstructedMode=Modalità costruita
lblConstructed=Costruito lblConstructed=Costruito

View File

@@ -287,6 +287,7 @@ lblTryAgain=再試行
lblAddAPlayer=プレーヤーを追加 lblAddAPlayer=プレーヤーを追加
lblVariants=バリエーション lblVariants=バリエーション
lblRandom=ランダム lblRandom=ランダム
lblGamesInMatch=Games in match:
#VSubmenuConstructed.java #VSubmenuConstructed.java
lblConstructedMode=構築戦 lblConstructedMode=構築戦
lblConstructed=構築戦 lblConstructed=構築戦

View File

@@ -287,6 +287,7 @@ lblTryAgain=再试一次
lblAddAPlayer=增加一个玩家 lblAddAPlayer=增加一个玩家
lblVariants=变种 lblVariants=变种
lblRandom=随机 lblRandom=随机
lblGamesInMatch=Games in match:
#VSubmenuConstructed.java #VSubmenuConstructed.java
lblConstructedMode=构筑模式 lblConstructedMode=构筑模式
lblConstructed=构筑 lblConstructed=构筑

View File

@@ -89,6 +89,7 @@ public class HostedMatch {
gameRules.setSideboardForAI(FModel.getPreferences().getPrefBoolean(FPref.MATCH_SIDEBOARD_FOR_AI)); gameRules.setSideboardForAI(FModel.getPreferences().getPrefBoolean(FPref.MATCH_SIDEBOARD_FOR_AI));
gameRules.setCanCloneUseTargetsImage(FModel.getPreferences().getPrefBoolean(FPref.UI_CLONE_MODE_SOURCE)); gameRules.setCanCloneUseTargetsImage(FModel.getPreferences().getPrefBoolean(FPref.UI_CLONE_MODE_SOURCE));
gameRules.setUseGrayText(FModel.getPreferences().getPrefBoolean(FPref.UI_GRAY_INACTIVE_TEXT)); gameRules.setUseGrayText(FModel.getPreferences().getPrefBoolean(FPref.UI_GRAY_INACTIVE_TEXT));
gameRules.setGamesPerMatch(FModel.getPreferences().getPrefInt(FPref.UI_MATCHES_PER_GAME));
return gameRules; return gameRules;
} }

View File

@@ -68,6 +68,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
BRAWL_P7_DECK_STATE(""), BRAWL_P7_DECK_STATE(""),
BRAWL_P8_DECK_STATE(""), BRAWL_P8_DECK_STATE(""),
UI_LANDSCAPE_MODE ("false"), UI_LANDSCAPE_MODE ("false"),
UI_MATCHES_PER_GAME("3"),
UI_COMPACT_MAIN_MENU ("false"), UI_COMPACT_MAIN_MENU ("false"),
UI_USE_OLD ("false"), UI_USE_OLD ("false"),
UI_RANDOM_FOIL ("false"), UI_RANDOM_FOIL ("false"),