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

View File

@@ -1871,7 +1871,7 @@ public class ComputerUtilCard {
return oppCards;
}
CardCollection aiCreats = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
CardCollection aiCreats = ai.getCreaturesInPlay();
if (temporary) {
// 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);

View File

@@ -168,15 +168,15 @@ public abstract class SpellAbilityAi {
}
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) {
return false;
}
// a mandatory SpellAbility with targeting but without candidates,
// does not need to go any deeper
if (sa.usesTargeting() && mandatory && !sa.isTargetNumberValid()
&& !sa.getTargetRestrictions().hasCandidates(sa)) {
return false;
if (sa.usesTargeting() && mandatory && sa.getTargetRestrictions().getNumCandidates(sa, true) == 0) {
return sa.isTargetNumberValid();
}
return doTriggerNoCostWithSubs(aiPlayer, sa, mandatory);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -92,7 +92,7 @@ public class ClashAi extends SpellAbilityAi {
if ("Creature".equals(valid)) {
// Springjack Knight
// 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);
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.spellability.Spell;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom;
public class CopySpellAbilityAi extends SpellAbilityAi {
@@ -58,8 +57,7 @@ public class CopySpellAbilityAi extends SpellAbilityAi {
}
}
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
if (sa.usesTargeting()) {
// Filter AI-specific targets if provided
if ("OnlyOwned".equals(sa.getParam("AITgts"))) {
if (!top.getActivatingPlayer().equals(aiPlayer)) {

View File

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

View File

@@ -76,8 +76,8 @@ public abstract class DamageAiBase extends SpellAbilityAi {
Card hostcard = sa.getHostCard();
for (Trigger trig : hostcard.getTriggers()) {
if (trig.getMode() == TriggerType.DamageDone) {
if (("Opponent".equals(trig.getParam("ValidTarget")))
&& (!"True".equals(trig.getParam("CombatDamage")))) {
if ("Opponent".equals(trig.getParam("ValidTarget"))
&& !"True".equals(trig.getParam("CombatDamage"))) {
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
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;
@@ -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);
if (divided) {
sa.addDividedAllocation(enemy, dmg);

View File

@@ -91,8 +91,7 @@ public class DebuffAi extends SpellAbilityAi {
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
if (!sa.usesTargeting()) {
// TODO - copied from AF_Pump.pumpDrawbackAI() - what should be
// here?
// TODO - copied from AF_Pump.pumpDrawbackAI() - what should be here?
} else {
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;
}
} else {
break;
return true;
}
} else {
Card c = ComputerUtilCard.getBestAI(preferred);
@@ -380,7 +380,7 @@ public class DestroyAi extends SpellAbilityAi {
}
}
while (sa.canAddMoreTarget()) {
while (!sa.isMinTargetChosen()) {
if (list.isEmpty()) {
break;
} else {

View File

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

View File

@@ -61,7 +61,7 @@ public class DigAi extends SpellAbilityAi {
if ("Never".equals(sa.getParam("AILogic"))) {
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))) {
return false;
}

View File

@@ -40,7 +40,7 @@ public class DigMultipleAi extends SpellAbilityAi {
if ("Never".equals(sa.getParam("AILogic"))) {
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))) {
return false;
}

View File

@@ -130,8 +130,7 @@ public class DigUntilAi extends SpellAbilityAi {
if ("OathOfDruids".equals(logic)) {
final List<Card> creaturesInLibrary =
CardLists.filter(player.getCardsIn(ZoneType.Library), CardPredicates.Presets.CREATURES);
final List<Card> creaturesInBattlefield =
CardLists.filter(player.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
final List<Card> creaturesInBattlefield = player.getCreaturesInPlay();
// if there are at least 3 creatures in library,
// or none in play with one in library, oath
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
// attempt to save the AI from dying
return true;
} else if (logic.equals("AlwaysAtOppEOT")) {
} else if (logic.equals("AtOppEOT")) {
return ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn().equals(ai);
} else if (logic.equals("RespondToOwnActivation")) {
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()) {
return true; // FIXME: shouldn't this return "false" if nothing found?
return false;
}
Card fighter1 = fighter1List.get(0);
for (Card humanCreature : humCreatures) {

View File

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

View File

@@ -122,9 +122,9 @@ public class LifeSetAi extends SpellAbilityAi {
}
// 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
return doHalfStartingLifeLogic(ai, opponent, sa);
return doHalfStartingLifeLogic(ai, opponent, sa) || mandatory;
}
if (sourceName.equals("Eternity Vessel")
@@ -160,9 +160,9 @@ public class LifeSetAi extends SpellAbilityAi {
private boolean doHalfStartingLifeLogic(Player ai, Player opponent, SpellAbility sa) {
int aiAmount = ai.getStartingLife() / 2;
int oppAmount = opponent.getStartingLife() / 2;
int oppAmount = opponent == null ? 0 : opponent.getStartingLife() / 2;
int aiLife = ai.getLife();
int oppLife = opponent.getLife();
int oppLife = opponent == null ? 0 : opponent.getLife();
sa.resetTargets();

View File

@@ -15,6 +15,7 @@ import forge.ai.SpellAbilityAi;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.card.mana.ManaCost;
import forge.game.GlobalRuleChange;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
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) {
if (logic.startsWith("ManaRitual")) {
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);
}

View File

@@ -146,13 +146,13 @@ public class MillAi extends SpellAbilityAi {
// can't target opponent?
if (list.isEmpty()) {
if (mandatory && sa.canTarget(ai)) {
if (mandatory && !sa.isTargetNumberValid() && sa.canTarget(ai)) {
sa.getTargets().add(ai);
return true;
}
// TODO Obscure case when you know what your top card is so you might?
// want to mill yourself here
return false;
return sa.isTargetNumberValid();
}
// 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.collect.Iterables;
import com.google.common.collect.Lists;
import forge.ai.AiCardMemory;
import forge.ai.ComputerUtilCard;
@@ -15,14 +14,12 @@ import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.combat.Combat;
import forge.game.combat.CombatUtil;
import forge.game.keyword.Keyword;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
public class MustBlockAi extends SpellAbilityAi {
@@ -76,7 +73,7 @@ public class MustBlockAi extends SpellAbilityAi {
return false;
}
Card attacker = null;
Card attacker = source;
if (sa.hasParam("DefinedAttacker")) {
final List<Card> cards = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedAttacker"), sa);
if (cards.isEmpty()) {
@@ -86,18 +83,12 @@ public class MustBlockAi extends SpellAbilityAi {
attacker = cards.get(0);
}
if (attacker == null) {
attacker = source;
}
final Card definedAttacker = attacker;
boolean chance = false;
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()) {
return false;
return sa.isTargetNumberValid();
}
final Card blocker = ComputerUtilCard.getBestCreatureAI(list);
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,
final boolean onlyLethal, final boolean testTapped) {
List<Card> list = Lists.newArrayList();
list = CardLists.filter(defender.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
List<Card> list = defender.getCreaturesInPlay();
if (sa.usesTargeting()) {
list = CardLists.getTargetableCards(list, sa);
@@ -187,7 +177,7 @@ public class MustBlockAi extends SpellAbilityAi {
List<Card> better = determineBlockerFromList(attacker, ai, options, sa, false, false);
if (!better.isEmpty()) {
return Iterables.getFirst(options, null);
return Iterables.getFirst(better, null);
}
return Iterables.getFirst(options, null);

View File

@@ -63,7 +63,7 @@ public class PhasesAi extends SpellAbilityAi {
return true;
} else if (mandatory) {
// 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;

View File

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

View File

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

View File

@@ -29,7 +29,7 @@ public class TapAllAi extends SpellAbilityAi {
// or during upkeep/begin combat?
final Card source = sa.getHostCard();
final Player opp = ai.getWeakestOpponent();
final Player opp = ai.getStrongestOpponent();
final Game game = ai.getGame();
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.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.collect.FCollection;
@@ -28,8 +27,7 @@ public class TwoPilesAi extends SpellAbilityAi {
final Player opp = AiAttackController.choosePreferredDefenderPlayer(ai);
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
if (sa.usesTargeting()) {
sa.resetTargets();
if (sa.canTarget(opp)) {
sa.getTargets().add(opp);

View File

@@ -12,7 +12,6 @@ import forge.game.card.Card;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom;
public class UnattachAllAi extends SpellAbilityAi {
@@ -48,7 +47,6 @@ public class UnattachAllAi extends SpellAbilityAi {
return chance;
}
/* (non-Javadoc)
* @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();
// Check if there are any valid targets
List<GameObject> targets = new ArrayList<>();
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt == null) {
if (!sa.usesTargeting()) {
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.Predicates;
import forge.ai.AiAttackController;
import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilAbility;
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) {
final Card source = sa.getHostCard();
Player targetController = ai;
final PlayerCollection targetController = new PlayerCollection();
if (sa.isCurse()) {
// TODO search through all opponents, may need to check if different controllers allowed
targetController = AiAttackController.choosePreferredDefenderPlayer(ai);
targetController.addAll(ai.getOpponents());
} else {
targetController.add(ai);
}
CardCollection list = CardLists.getTargetableCards(targetController.getCardsIn(ZoneType.Battlefield), sa);

View File

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

View File

@@ -1689,10 +1689,6 @@ public class AbilityUtils {
// accept straight numbers
if (l[0].startsWith("Number$")) {
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);
}

View File

@@ -272,8 +272,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
sb.append(".");
} else if (origin.equals("Battlefield")) {
// TODO Expand on this Description as more cards use it
// for the non-targeted SAs when you choose what is returned on
// resolution
// for the non-targeted SAs when you choose what is returned on resolution
sb.append("Return ").append(num).append(" ").append(type).append(" card(s) ");
sb.append(" to your ").append(destination);
}
@@ -361,8 +360,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
sb.append(fromGraveyard);
}
// this needs to be zero indexed. Top = 0, Third = 2, -1 =
// Bottom
// this needs to be zero indexed. Top = 0, Third = 2, -1 = Bottom
final int libraryPosition = sa.hasParam("LibraryPosition") ? AbilityUtils.calculateAmount(host, sa.getParam("LibraryPosition"), sa) : 0;
if (libraryPosition == -1) {
@@ -451,9 +449,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
sb.append(sa.getParam("AlternativeDestinationMessage"));
Player alterDecider = player;
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"));
altDest = true;
}

View File

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

View File

@@ -171,23 +171,6 @@ public class StaticAbilityCantBeCast {
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)
&& activator.getGame().getPhaseHandler().isPlayerTurn(activator)) {
return false;

View File

@@ -11,11 +11,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
@@ -84,6 +80,8 @@ public class VLobby implements ILobbyView {
private final StartButton btnStart = new StartButton();
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
// Variants frame and variables
@@ -212,11 +210,19 @@ public class VLobby implements ILobbyView {
public final void actionPerformed(final ActionEvent arg0) {
Runnable startGame = lobby.startGame();
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();
}
}
});
}
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() {

View File

@@ -3,7 +3,7 @@ ManaCost:1 W
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.
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: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.

View File

@@ -3,7 +3,7 @@ ManaCost:1
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.
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
AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/animation_module.jpg

View File

@@ -3,6 +3,6 @@ ManaCost:no cost
Types:Land
K:Ascend
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
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
Types:Legendary Creature Human Wizard
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
DeckHints:Type$Wizard
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
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$ 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.

View File

@@ -4,7 +4,7 @@ Types:Legendary Creature Human Warrior
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$ 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.
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.

View File

@@ -1,7 +1,7 @@
Name:Consulate Turret
ManaCost:3
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.
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.

View File

@@ -1,7 +1,7 @@
Name:Damping Matrix
ManaCost:3
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
AI:RemoveDeck:Random
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
Types:Instant
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:DBReveal:DB$ DigUntil | Defined$ ImprintedController | Amount$ 1 | Valid$ Creature | ValidDescription$ creature | RevealedDestination$ Library | RevealedLibraryPosition$ 0 | FoundDestination$ Battlefield | SubAbility$ DBCleanup | Shuffle$ True
SVar:DBCleanup:DB$ Cleanup | ClearImprinted$ True
SVar:DBReveal:DB$ DigUntil | Defined$ ImprintedController | Amount$ 1 | Valid$ Creature | ValidDescription$ creature | RevealedDestination$ Library | RevealedLibraryPosition$ 0 | FoundDestination$ Battlefield | Shuffle$ True
SVar:DBCleanRemembered:DB$ Cleanup | ClearRemembered$ True
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.

View File

@@ -3,7 +3,7 @@ ManaCost:3
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.
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
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}.

View File

@@ -5,7 +5,7 @@ K:Enchant permanent
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.
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.
DeckHas:Ability$LifeGain
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.
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: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.

View File

@@ -2,10 +2,11 @@ Name:Halana and Alena, Partners
ManaCost:2 R G
Types:Legendary Creature Human Ranger
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.
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:X:Count$CardPower
DeckHas:Ability$Counters
Oracle:First strike, reach
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.
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.

View File

@@ -2,7 +2,7 @@ Name:Hand to Hand
ManaCost:2 R
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$ CantBeActivated | ValidCard$ Card | Phases$ BeginCombat->EndCombat | NonMana$ True
S:Mode$ CantBeActivated | ValidCard$ Card | Phases$ BeginCombat->EndCombat | ValidSA$ Activated.nonManaAbility
SVar:NonStackingEffect:True
AI:RemoveDeck:Random
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
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.
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
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
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$ CantBeActivated | ValidCard$ Creature.withFlying | AffectedZone$ Battlefield | TapAbility$ True
S:Mode$ CantBeActivated | ValidCard$ Creature.withFlying | ValidSA$ Activated.hasTapCost | AffectedZone$ Battlefield
AI:RemoveDeck:Random
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.

View File

@@ -3,7 +3,7 @@ ManaCost:1 G U
Types:Legendary Creature Merfolk Shaman
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$ 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.
DeckHints:Type$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:X:TargetedPlayer$CardsInLibrary
SVar:Y:Remembered$Valid Card.NamedCard
SVar:Z:Number$ChosenNumber
SVar:Z:Count$ChosenNumber
AI:RemoveDeck:All
AI:RemoveDeck:Random
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
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
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: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

View File

@@ -2,7 +2,7 @@ Name:Muzzio, Visionary Architect
ManaCost:1 U U
Types:Legendary Creature Human Artificer
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: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.

View File

@@ -1,6 +1,6 @@
Name:Mystic Archaeologist
ManaCost:1 U
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.
PT:2/1

View File

@@ -3,7 +3,7 @@ ManaCost:2 U U R R
Types:Legendary Creature Dragon Wizard
PT:4/4
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.
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

View File

@@ -4,6 +4,6 @@ Types:Enchantment Aura Curse
K:Enchant player
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$ 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
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
K:ETBReplacement:Other:DBNameCard
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
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.

View File

@@ -1,7 +1,7 @@
Name:Pristine Talisman
ManaCost:3
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:Picture:http://www.wizards.com/global/images/magic/general/pristine_talisman.jpg
Oracle:{T}: Add {C}. You gain 1 life.

View File

@@ -5,7 +5,7 @@ PT:2/2
K:ETBReplacement:Other:ChooseNumber
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.
SVar:X:Number$ChosenNumber
SVar:X:Count$ChosenNumber
AI:RemoveDeck:All
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.

View File

@@ -5,6 +5,6 @@ K:Enchant creature
K:UpkeepCost:W W
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$ 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
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:DBNameCard:DB$ NameCard | Defined$ You | SubAbility$ DBClear
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
# 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

View File

@@ -4,5 +4,5 @@ Types:Creature Spirit Pirate
PT:1/1
K:Flash
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.

View File

@@ -4,8 +4,6 @@ Types:Artifact Creature Insect
PT:-1/-1
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.
#TODO: For some reason the AI removes beneficial counters from its own permanents with this card.
AI:RemoveDeck:All
AI:RemoveDeck:Random
SVar:NeedsToPlayVar:Z GE3
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
# Draw Cards
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:Loss:Number$0
SVar:CardsToDraw:Count$ChosenNumber/Times.2

View File

@@ -1,7 +1,7 @@
Name:Strixhaven Stadium
ManaCost:3
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
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

View File

@@ -5,6 +5,6 @@ PT:3/3
K:Flash
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.
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>
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
ManaCost:5 W
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.
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturn | RememberObjects$ RememberedLKI | TriggerDescription$ Return exiled permanents to the battlefield. | SubAbility$ DBCleanup
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 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:DBCleanup:DB$ Cleanup | ClearRemembered$ True
AI:RemoveDeck:All

View File

@@ -3,7 +3,7 @@ ManaCost:7 G G
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.
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
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

View File

@@ -1,7 +1,7 @@
Name:The Immortal Sun
ManaCost:6
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.
SVar:TrigDraw:DB$ Draw | NumCards$ 1
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
ManaCost:2 U U
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:Picture:http://www.wizards.com/global/images/magic/general/treasure_trove.jpg
Oracle:{2}{U}{U}: Draw a card.

View File

@@ -1,6 +1,6 @@
Name:Vivien's Arkbow
ManaCost:1 G
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
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.
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:X:Number$ChosenNumber
SVar:X:Count$ChosenNumber
AI:RemoveDeck:All
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.

View File

@@ -1,7 +1,7 @@
Name:Whispers of the Muse
ManaCost:U
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
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.

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: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:X:Number$ChosenNumber
SVar:X:Count$ChosenNumber
SVar:Y:Count$RememberedNumber
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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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