mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +00:00
- Explicitly marked cards that use a re-entry mechanism for testing playability via canPlaySa such that they don't recursively call each other and thus risk getting into an infinite loop (fixes potential check combinations of e.g. various mana rituals + Yawgmoth's Will in AI's hand and other things like that, which would otherwise cause a stack overflow).
- Some simplification in the AICardMemory interface, allowing to use static methods to simplify calls.
This commit is contained in:
@@ -585,9 +585,8 @@ public class AiAttackController {
|
||||
// Cards that are remembered to attack anyway (e.g. temporarily stolen creatures)
|
||||
if (ai.getController() instanceof PlayerControllerAi) {
|
||||
// Only do this if |ai| is actually an AI - as we could be trying to predict how the human will attack.
|
||||
AiCardMemory aiMemory = ((PlayerControllerAi) ai.getController()).getAi().getCardMemory();
|
||||
for (Card attacker : this.attackers) {
|
||||
if (aiMemory.isRememberedCard(attacker, AiCardMemory.MemorySet.MANDATORY_ATTACKERS)) {
|
||||
if (AiCardMemory.isRememberedCard(ai, attacker, AiCardMemory.MemorySet.MANDATORY_ATTACKERS)) {
|
||||
combat.addAttacker(attacker, defender);
|
||||
attackersLeft.remove(attacker);
|
||||
}
|
||||
|
||||
@@ -44,12 +44,14 @@ public class AiCardMemory {
|
||||
private final Set<Card> memHeldManaSources;
|
||||
private final Set<Card> memAttachedThisTurn;
|
||||
private final Set<Card> memAnimatedThisTurn;
|
||||
private final Set<Card> memTestedCanPlayThisTurn;
|
||||
|
||||
public AiCardMemory() {
|
||||
this.memMandatoryAttackers = new HashSet<>();
|
||||
this.memHeldManaSources = new HashSet<>();
|
||||
this.memAttachedThisTurn = new HashSet<>();
|
||||
this.memAnimatedThisTurn = new HashSet<>();
|
||||
this.memTestedCanPlayThisTurn = new HashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,6 +64,7 @@ public class AiCardMemory {
|
||||
HELD_MANA_SOURCES,
|
||||
ATTACHED_THIS_TURN,
|
||||
ANIMATED_THIS_TURN,
|
||||
TESTED_CANPLAY_THIS_PHASE,
|
||||
//REVEALED_CARDS // stub, not linked to AI code yet
|
||||
}
|
||||
|
||||
@@ -75,6 +78,8 @@ public class AiCardMemory {
|
||||
return memAttachedThisTurn;
|
||||
case ANIMATED_THIS_TURN:
|
||||
return memAnimatedThisTurn;
|
||||
case TESTED_CANPLAY_THIS_PHASE:
|
||||
return memTestedCanPlayThisTurn;
|
||||
//case REVEALED_CARDS:
|
||||
// return memRevealedCards;
|
||||
default:
|
||||
@@ -247,5 +252,23 @@ public class AiCardMemory {
|
||||
clearMemorySet(MemorySet.HELD_MANA_SOURCES);
|
||||
clearMemorySet(MemorySet.ATTACHED_THIS_TURN);
|
||||
clearMemorySet(MemorySet.ANIMATED_THIS_TURN);
|
||||
clearMemorySet(MemorySet.TESTED_CANPLAY_THIS_PHASE);
|
||||
}
|
||||
|
||||
// Static functions to simplify access to AI card memory of a given AI player.
|
||||
public static void rememberCard(Player ai, Card c, MemorySet set) {
|
||||
((PlayerControllerAi)ai.getController()).getAi().getCardMemory().rememberCard(c, set);
|
||||
}
|
||||
public static void forgetCard(Player ai, Card c, MemorySet set) {
|
||||
((PlayerControllerAi)ai.getController()).getAi().getCardMemory().forgetCard(c, set);
|
||||
}
|
||||
public static boolean isRememberedCard(Player ai, Card c, MemorySet set) {
|
||||
return ((PlayerControllerAi)ai.getController()).getAi().getCardMemory().isRememberedCard(c, set);
|
||||
}
|
||||
public static void clearMemorySet(Player ai, MemorySet set) {
|
||||
((PlayerControllerAi)ai.getController()).getAi().getCardMemory().clearMemorySet(set);
|
||||
}
|
||||
public static boolean isMemorySetEmpty(Player ai, MemorySet set) {
|
||||
return ((PlayerControllerAi)ai.getController()).getAi().getCardMemory().isMemorySetEmpty(set);
|
||||
}
|
||||
}
|
||||
@@ -607,7 +607,7 @@ public class AiController {
|
||||
ManaCostBeingPaid cost = ComputerUtilMana.calculateManaCost(sa, true, 0);
|
||||
CardCollection manaSources = ComputerUtilMana.getManaSourcesToPayCost(cost, sa, player);
|
||||
for (Card c : manaSources) {
|
||||
((PlayerControllerAi)player.getController()).getAi().getCardMemory().rememberCard(c, AiCardMemory.MemorySet.HELD_MANA_SOURCES);
|
||||
AiCardMemory.rememberCard(player, c, AiCardMemory.MemorySet.HELD_MANA_SOURCES);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -800,10 +800,10 @@ public class ComputerUtilMana {
|
||||
|
||||
PhaseType curPhase = ai.getGame().getPhaseHandler().getPhase();
|
||||
if (curPhase == PhaseType.MAIN2 || curPhase == PhaseType.CLEANUP) {
|
||||
aic.getCardMemory().clearMemorySet(AiCardMemory.MemorySet.HELD_MANA_SOURCES);
|
||||
AiCardMemory.clearMemorySet(ai, AiCardMemory.MemorySet.HELD_MANA_SOURCES);
|
||||
}
|
||||
else {
|
||||
if (aic.getCardMemory().isRememberedCard(sourceCard, AiCardMemory.MemorySet.HELD_MANA_SOURCES)) {
|
||||
if (AiCardMemory.isRememberedCard(ai, sourceCard, AiCardMemory.MemorySet.HELD_MANA_SOURCES)) {
|
||||
// This mana source is held elsewhere for a Main Phase 2 spell.
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -359,8 +359,8 @@ public class SpecialCardAi {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (testSa.getHostCard().getName().equals(sa.getHostCard().getName())) {
|
||||
// prevent infinitely recursing own ability when testing AI play decision
|
||||
if (testSa.getHostCard().getName().equals(sa.getHostCard().getName()) || testSa.hasParam("AIRecursiveTestAbility")) {
|
||||
// prevent infinitely recursing abilities that are susceptible to reentry
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -544,8 +544,9 @@ public class SpecialCardAi {
|
||||
// cut short considering to play counterspells via Yawgmoth's Will
|
||||
continue;
|
||||
}
|
||||
if (ab.getHostCard().getName().equals(sa.getHostCard().getName())) {
|
||||
// prevent infinitely recursing own ability when testing AI play decision
|
||||
|
||||
if (ab.getHostCard().getName().equals(sa.getHostCard().getName()) || ab.hasParam("AIRecursiveTestAbility")) {
|
||||
// prevent infinitely recursing abilities that are susceptible to reentry
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -610,12 +610,10 @@ public class AnimateAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
private void rememberAnimatedThisTurn(Player ai, Card c) {
|
||||
AiCardMemory mem = ((PlayerControllerAi)ai.getController()).getAi().getCardMemory();
|
||||
mem.rememberCard(c, AiCardMemory.MemorySet.ANIMATED_THIS_TURN);
|
||||
AiCardMemory.rememberCard(ai, c, AiCardMemory.MemorySet.ANIMATED_THIS_TURN);
|
||||
}
|
||||
|
||||
public static boolean isAnimatedThisTurn(Player ai, Card c) {
|
||||
AiCardMemory mem = ((PlayerControllerAi)ai.getController()).getAi().getCardMemory();
|
||||
return mem.isRememberedCard(c, AiCardMemory.MemorySet.ANIMATED_THIS_TURN);
|
||||
return AiCardMemory.isRememberedCard(ai, c, AiCardMemory.MemorySet.ANIMATED_THIS_TURN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1095,7 +1095,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
// make sure to prioritize casting spells in main 2 (creatures, other equipment, etc.) rather than moving equipment around
|
||||
boolean decideMoveFromUseless = uselessCreature && aic.getBooleanProperty(AiProps.PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS);
|
||||
|
||||
if (!decideMoveFromUseless && aic.getCardMemory().isMemorySetEmpty(AiCardMemory.MemorySet.HELD_MANA_SOURCES)) {
|
||||
if (!decideMoveFromUseless && AiCardMemory.isMemorySetEmpty(aiPlayer, AiCardMemory.MemorySet.HELD_MANA_SOURCES)) {
|
||||
SpellAbility futureSpell = aic.predictSpellToCastInMain2(ApiType.Attach);
|
||||
if (futureSpell != null && futureSpell.getHostCard() != null) {
|
||||
aic.reserveManaSourcesForMain2(futureSpell);
|
||||
@@ -1103,12 +1103,12 @@ public class AttachAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
// avoid randomly moving the equipment back and forth between several creatures in one turn
|
||||
if (aic.getCardMemory().isRememberedCard(sa.getHostCard(), AiCardMemory.MemorySet.ATTACHED_THIS_TURN)) {
|
||||
if (AiCardMemory.isRememberedCard(aiPlayer, sa.getHostCard(), AiCardMemory.MemorySet.ATTACHED_THIS_TURN)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
aic.getCardMemory().rememberCard(sa.getHostCard(), AiCardMemory.MemorySet.ATTACHED_THIS_TURN);
|
||||
AiCardMemory.rememberCard(aiPlayer, sa.getHostCard(), AiCardMemory.MemorySet.ATTACHED_THIS_TURN);
|
||||
|
||||
if (c == null && mandatory) {
|
||||
CardLists.shuffle(list);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import forge.ai.AiCardMemory;
|
||||
import forge.ai.AiPlayDecision;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
@@ -10,6 +11,7 @@ import forge.ai.SpellAbilityAi;
|
||||
import forge.card.MagicColor;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardLists;
|
||||
@@ -63,7 +65,7 @@ public class ManaEffectAi extends SpellAbilityAi {
|
||||
*/
|
||||
@Override
|
||||
protected boolean checkPhaseRestrictions(Player ai, SpellAbility sa, PhaseHandler ph, String logic) {
|
||||
if ("ManaRitual".equals(logic)) {
|
||||
if (logic.startsWith("ManaRitual")) {
|
||||
return ph.is(PhaseType.MAIN2, ai) || ph.is(PhaseType.MAIN1, ai);
|
||||
}
|
||||
return super.checkPhaseRestrictions(ai, sa, ph, logic);
|
||||
@@ -110,7 +112,9 @@ public class ManaEffectAi extends SpellAbilityAi {
|
||||
|
||||
CardCollection manaSources = ComputerUtilMana.getAvailableMana(ai, true);
|
||||
int numManaSrcs = manaSources.size();
|
||||
int manaReceived = AbilityUtils.calculateAmount(host, sa.getParam("Amount"), sa);
|
||||
int manaReceived = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(host, sa.getParam("Amount"), sa) : 1;
|
||||
manaReceived *= sa.getParam("Produced").split(" ").length;
|
||||
|
||||
int selfCost = sa.getPayCosts().getCostMana() != null ? sa.getPayCosts().getCostMana().getMana().getCMC() : 0;
|
||||
byte producedColor = MagicColor.fromName(sa.getParam("Produced"));
|
||||
int searchCMC = numManaSrcs - selfCost + manaReceived;
|
||||
@@ -139,8 +143,8 @@ public class ManaEffectAi extends SpellAbilityAi {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (testSa.getHostCard().getName().equals(host.getName())) {
|
||||
// prevent infinitely recursing own ability when testing AI play decision
|
||||
if (testSa.getHostCard().equals(host) || testSa.hasParam("AIRecursiveTestAbility")) {
|
||||
// prevent infinitely recursing mana ritual and other abilities with reentry
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@ Name:Apprentice Wizard
|
||||
ManaCost:1 U U
|
||||
Types:Creature Human Wizard
|
||||
PT:0/1
|
||||
A:AB$ Mana | Cost$ U T | Produced$ C | Amount$ 3 | AILogic$ ManaRitual | SpellDescription$ Add {C}{C}{C} to your mana pool.
|
||||
A:AB$ Mana | Cost$ U T | Produced$ C | Amount$ 3 | AILogic$ ManaRitual | AIRecursiveTestAbility$ True | SpellDescription$ Add {C}{C}{C} to your mana pool.
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/apprentice_wizard.jpg
|
||||
Oracle:{U}, {T}: Add {C}{C}{C} to your mana pool.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Name:Battle Hymn
|
||||
ManaCost:1 R
|
||||
Types:Instant
|
||||
A:SP$ Mana | Cost$ 1 R | Produced$ R | Amount$ X | References$ X | AILogic$ ManaRitual | SpellDescription$ Add {R} to your mana pool for each creature you control.
|
||||
A:SP$ Mana | Cost$ 1 R | Produced$ R | Amount$ X | References$ X | AILogic$ ManaRitual | AIRecursiveTestAbility$ True | SpellDescription$ Add {R} to your mana pool for each creature you control.
|
||||
SVar:X:Count$Valid Creature.YouCtrl
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/battle_hymn.jpg
|
||||
Oracle:Add {R} to your mana pool for each creature you control.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Name:Brightstone Ritual
|
||||
ManaCost:R
|
||||
Types:Instant
|
||||
A:SP$ Mana | Cost$ R | Produced$ R | Amount$ X | References$ X | AILogic$ ManaRitual | SpellDescription$ Add {R} to your mana pool for each Goblin on the battlefield.
|
||||
A:SP$ Mana | Cost$ R | Produced$ R | Amount$ X | References$ X | AILogic$ ManaRitual | AIRecursiveTestAbility$ True | SpellDescription$ Add {R} to your mana pool for each Goblin on the battlefield.
|
||||
SVar:X:Count$TypeOnBattlefield.Goblin
|
||||
SVar:RemRandomDeck:True
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/brightstone_ritual.jpg
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Name:Dark Ritual
|
||||
ManaCost:B
|
||||
Types:Instant
|
||||
A:SP$ Mana | Cost$ B | Produced$ B | Amount$ 3 | AILogic$ ManaRitual | SpellDescription$ Add {B}{B}{B} to your mana pool.
|
||||
A:SP$ Mana | Cost$ B | Produced$ B | Amount$ 3 | AILogic$ ManaRitual | AIRecursiveTestAbility$ True | SpellDescription$ Add {B}{B}{B} to your mana pool.
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/dark_ritual.jpg
|
||||
Oracle:Add {B}{B}{B} to your mana pool.
|
||||
|
||||
@@ -2,6 +2,6 @@ Name:Desperate Ritual
|
||||
ManaCost:1 R
|
||||
Types:Instant Arcane
|
||||
K:Splice:Arcane:1 R
|
||||
A:SP$ Mana | Cost$ 1 R | Produced$ R | Amount$ 3 | AILogic$ ManaRitual | SpellDescription$ Add {R}{R}{R} to your mana pool.
|
||||
A:SP$ Mana | Cost$ 1 R | Produced$ R | Amount$ 3 | AILogic$ ManaRitual | AIRecursiveTestAbility$ True | SpellDescription$ Add {R}{R}{R} to your mana pool.
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/desperate_ritual.jpg
|
||||
Oracle:Add {R}{R}{R} to your mana pool.\nSplice onto Arcane {1}{R} (As you cast an Arcane spell, you may reveal this card from your hand and pay its splice cost. If you do, add this card's effects to that spell.)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Name:Geosurge
|
||||
ManaCost:R R R R
|
||||
Types:Sorcery
|
||||
A:SP$ Mana | Cost$ R R R R | Produced$ R | Amount$ 7 | RestrictValid$ Card.Artifact,Card.Creature | AILogic$ ManaRitual | SpellDescription$ Add {R}{R}{R}{R}{R}{R}{R} to your mana pool. Spend this mana only to cast artifact or creature spells.
|
||||
A:SP$ Mana | Cost$ R R R R | Produced$ R | Amount$ 7 | RestrictValid$ Card.Artifact,Card.Creature | AILogic$ ManaRitual | AIRecursiveTestAbility$ True | SpellDescription$ Add {R}{R}{R}{R}{R}{R}{R} to your mana pool. Spend this mana only to cast artifact or creature spells.
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/geosurge.jpg
|
||||
Oracle:Add {R}{R}{R}{R}{R}{R}{R} to your mana pool. Spend this mana only to cast artifact or creature spells.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Name:Inner Fire
|
||||
ManaCost:3 R
|
||||
Types:Sorcery
|
||||
A:SP$ Mana | Cost$ 3 R | Produced$ R | Amount$ X | References$ X | AILogic$ ManaRitual | SpellDescription$ Add {R} to your mana pool for each card in your hand.
|
||||
A:SP$ Mana | Cost$ 3 R | Produced$ R | Amount$ X | References$ X | AILogic$ ManaRitual | AIRecursiveTestAbility$ True | SpellDescription$ Add {R} to your mana pool for each card in your hand.
|
||||
SVar:X:Count$CardsInYourHand
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/inner_fire.jpg
|
||||
Oracle:Add {R} to your mana pool for each card in your hand.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Name:Mana Geyser
|
||||
ManaCost:3 R R
|
||||
Types:Sorcery
|
||||
A:SP$ Mana | Cost$ 3 R R | Produced$ R | Amount$ X | References$ X | AILogic$ ManaRitual | SpellDescription$ Add {R} to your mana pool for each tapped land your opponents control.
|
||||
A:SP$ Mana | Cost$ 3 R R | Produced$ R | Amount$ X | References$ X | AILogic$ ManaRitual | AIRecursiveTestAbility$ True | SpellDescription$ Add {R} to your mana pool for each tapped land your opponents control.
|
||||
SVar:X:Count$Valid Land.tapped+OppCtrl
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/mana_geyser.jpg
|
||||
Oracle:Add {R} to your mana pool for each tapped land your opponents control.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Nykthos, Shrine to Nyx
|
||||
ManaCost:no cost
|
||||
Types:Legendary Land
|
||||
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C} to your mana pool.
|
||||
A:AB$ ChooseColor | Cost$ 2 T | SubAbility$ DBMana | AILogic$ MostProminentComputerControls | SpellDescription$ Choose a color. Add to your mana pool an amount of mana of that color equal to your devotion to that color. (Your devotion to a color is the number of mana symbols of that color in the mana costs of permanents you control.)
|
||||
A:AB$ ChooseColor | Cost$ 2 T | SubAbility$ DBMana | AILogic$ MostProminentComputerControls | AIRecursiveTestAbility$ True | SpellDescription$ Choose a color. Add to your mana pool an amount of mana of that color equal to your devotion to that color. (Your devotion to a color is the number of mana symbols of that color in the mana costs of permanents you control.)
|
||||
SVar:DBMana:DB$ Mana | Produced$ Chosen | Amount$ X | References$ X
|
||||
SVar:X:Count$Devotion.Chosen
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/nykthos_shrine_to_nyx.jpg
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Name:Pyretic Ritual
|
||||
ManaCost:1 R
|
||||
Types:Instant
|
||||
A:SP$ Mana | Cost$ 1 R | Produced$ R | Amount$ 3 | AILogic$ ManaRitual | SpellDescription$ Add {R}{R}{R} to your mana pool.
|
||||
A:SP$ Mana | Cost$ 1 R | Produced$ R | Amount$ 3 | AILogic$ ManaRitual | AIRecursiveTestAbility$ True | SpellDescription$ Add {R}{R}{R} to your mana pool.
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/pyretic_ritual.jpg
|
||||
Oracle:Add {R}{R}{R} to your mana pool.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Name:Rite of Flame
|
||||
ManaCost:R
|
||||
Types:Sorcery
|
||||
A:SP$ Mana | Cost$ R | Produced$ R | Amount$ X | References$ X | AILogic$ ManaRitual | SpellDescription$ Add {R}{R} to your mana pool, then add {R} to your mana pool for each card named CARDNAME in each graveyard.
|
||||
A:SP$ Mana | Cost$ R | Produced$ R | Amount$ X | References$ X | AILogic$ ManaRitual | AIRecursiveTestAbility$ True | SpellDescription$ Add {R}{R} to your mana pool, then add {R} to your mana pool for each card named CARDNAME in each graveyard.
|
||||
SVar:X:Count$NamedInAllYards.Rite of Flame/Plus.2
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/rite_of_flame.jpg
|
||||
Oracle:Add {R}{R} to your mana pool, then add {R} to your mana pool for each card named Rite of Flame in each graveyard.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Name:Seething Song
|
||||
ManaCost:2 R
|
||||
Types:Instant
|
||||
A:SP$ Mana | Cost$ 2 R | Produced$ R | Amount$ 5 | AILogic$ ManaRitual | SpellDescription$ Add {R}{R}{R}{R}{R} to your mana pool.
|
||||
A:SP$ Mana | Cost$ 2 R | Produced$ R | Amount$ 5 | AILogic$ ManaRitual | AIRecursiveTestAbility$ True | SpellDescription$ Add {R}{R}{R}{R}{R} to your mana pool.
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/seething_song.jpg
|
||||
Oracle:Add {R}{R}{R}{R}{R} to your mana pool.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Name:Yawgmoth's Will
|
||||
ManaCost:2 B
|
||||
Types:Sorcery
|
||||
A:SP$ Effect | Cost$ 2 B | Name$ Yawgmoth's Will Effect | ReplacementEffects$ GraveToExile | StaticAbilities$ STPlay | SVars$ Exile | AILogic$ YawgmothsWill | SpellDescription$ Until end of turn, you may play cards from your graveyard. If a card would be put into your graveyard from anywhere this turn, exile that card instead.
|
||||
A:SP$ Effect | Cost$ 2 B | Name$ Yawgmoth's Will Effect | ReplacementEffects$ GraveToExile | StaticAbilities$ STPlay | SVars$ Exile | AILogic$ YawgmothsWill | AIRecursiveTestAbility$ True | SpellDescription$ Until end of turn, you may play cards from your graveyard. If a card would be put into your graveyard from anywhere this turn, exile that card instead.
|
||||
SVar:STPlay:Mode$ Continuous | EffectZone$ Command | Affected$ Card.YouCtrl | AffectedZone$ Graveyard | MayPlay$ True | Description$ You may play cards from your graveyard.
|
||||
SVar:GraveToExile:Event$ Moved | ActiveZones$ Command | Destination$ Graveyard | ValidCard$ Card.nonToken+YouOwn | ReplaceWith$ Exile | Description$ If a card would be put into your graveyard from anywhere, exile it instead.
|
||||
SVar:Exile:AB$ ChangeZone | Cost$ 0 | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard
|
||||
|
||||
Reference in New Issue
Block a user