diff --git a/.gitattributes b/.gitattributes index e1c4e0616d5..6aabcb7ea76 100644 --- a/.gitattributes +++ b/.gitattributes @@ -65,6 +65,7 @@ forge-ai/src/main/java/forge/ai/ability/CloneAi.java -text forge-ai/src/main/java/forge/ai/ability/ControlExchangeAi.java -text forge-ai/src/main/java/forge/ai/ability/ControlGainAi.java -text forge-ai/src/main/java/forge/ai/ability/CopyPermanentAi.java -text +forge-ai/src/main/java/forge/ai/ability/CopySpellAbilityAi.java -text forge-ai/src/main/java/forge/ai/ability/CounterAi.java -text forge-ai/src/main/java/forge/ai/ability/CountersAi.java svneol=native#text/plain forge-ai/src/main/java/forge/ai/ability/CountersMoveAi.java -text @@ -3565,6 +3566,7 @@ forge-gui/res/cardsfolder/c/ceta_sanctuary.txt svneol=native#text/plain forge-gui/res/cardsfolder/c/cetavolver.txt -text forge-gui/res/cardsfolder/c/chain_lightning.txt -text forge-gui/res/cardsfolder/c/chain_of_plasma.txt -text +forge-gui/res/cardsfolder/c/chain_of_smog.txt -text forge-gui/res/cardsfolder/c/chain_of_vapor.txt -text forge-gui/res/cardsfolder/c/chain_reaction.txt svneol=native#text/plain forge-gui/res/cardsfolder/c/chain_stasis.txt -text diff --git a/forge-ai/src/main/java/forge/ai/SpellApiToAi.java b/forge-ai/src/main/java/forge/ai/SpellApiToAi.java index f223935686e..5a38913f3ab 100644 --- a/forge-ai/src/main/java/forge/ai/SpellApiToAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellApiToAi.java @@ -45,7 +45,7 @@ public enum SpellApiToAi { .put(ApiType.Cleanup, AlwaysPlayAi.class) .put(ApiType.Clone, CloneAi.class) .put(ApiType.CopyPermanent, CopyPermanentAi.class) - .put(ApiType.CopySpellAbility, CanPlayAsDrawbackAi.class) + .put(ApiType.CopySpellAbility, CopySpellAbilityAi.class) .put(ApiType.ControlPlayer, CannotPlayAi.class) .put(ApiType.ControlSpell, CannotPlayAi.class) .put(ApiType.Counter, CounterAi.class) diff --git a/forge-ai/src/main/java/forge/ai/ability/CopySpellAbilityAi.java b/forge-ai/src/main/java/forge/ai/ability/CopySpellAbilityAi.java new file mode 100644 index 00000000000..7a7f74935fa --- /dev/null +++ b/forge-ai/src/main/java/forge/ai/ability/CopySpellAbilityAi.java @@ -0,0 +1,55 @@ +package forge.ai.ability; + +import forge.ai.SpellAbilityAi; +import forge.game.player.Player; +import forge.game.spellability.SpellAbility; +import forge.game.zone.ZoneType; + +import java.util.List; + +public class CopySpellAbilityAi extends SpellAbilityAi { + + @Override + protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) { + return false; + } + + @Override + protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) { + return false; + } + + @Override + public boolean chkAIDrawback(final SpellAbility sa, final Player aiPlayer) { + // NOTE: Other SAs that use CopySpellAbilityAi (e.g. Chain Lightning) are currently routed through + // generic method SpellAbilityAi#chkDrawbackWithSubs and are handled there. + + if ("ChainOfSmog".equals(sa.getParam("AILogic"))) { + if (aiPlayer.getCardsIn(ZoneType.Hand).size() == 0) { + // avoid failure to add to stack by providing a legal target + // TODO: this makes the AI target opponents with 0 cards in hand, but bailing from here causes a + // "failed to add to stack" error, needs investigation and improvement. + Player targOpp = aiPlayer.getOpponent(); + + for (Player opp : aiPlayer.getOpponents()) { + if (opp.getCardsIn(ZoneType.Hand).size() > 0) { + targOpp = opp; + break; + } + } + + sa.getParent().resetTargets(); + sa.getParent().getTargets().add(targOpp); + return true; + } + } + + return super.chkAIDrawback(sa, aiPlayer); + } + + @Override + public SpellAbility chooseSingleSpellAbility(Player player, SpellAbility sa, List spells) { + return spells.get(0); + } +} + diff --git a/forge-gui/res/cardsfolder/c/chain_of_smog.txt b/forge-gui/res/cardsfolder/c/chain_of_smog.txt new file mode 100644 index 00000000000..ad0ca8a35c1 --- /dev/null +++ b/forge-gui/res/cardsfolder/c/chain_of_smog.txt @@ -0,0 +1,9 @@ +Name:Chain of Smog +ManaCost:1 B +Types:Sorcery +A:SP$ Discard | Cost$ 1 B | ValidTgts$ Player | NumCards$ 2 | Mode$ TgtChoose | SubAbility$ DBCopy | SpellDescription$ Target player discards two cards. That player may copy this spell and may choose a new target for that copy. +SVar:DBCopy:DB$ CopySpellAbility | Defined$ Parent | Controller$ TargetedPlayer | AILogic$ ChainOfSmog | StackDescription$ None +SVar:RemAIDeck:True +SVar:Picture:http://www.wizards.com/global/images/magic/general/chain_of_smog.jpg +Oracle:Target player discards two cards. That player may copy this spell and may choose a new target for that copy. +