diff --git a/Mage.Sets/src/mage/cards/i/InscriptionOfAbundance.java b/Mage.Sets/src/mage/cards/i/InscriptionOfAbundance.java index 84eb6e1c1a..45677784e0 100644 --- a/Mage.Sets/src/mage/cards/i/InscriptionOfAbundance.java +++ b/Mage.Sets/src/mage/cards/i/InscriptionOfAbundance.java @@ -8,7 +8,7 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.FightTargetsEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; -import mage.abilities.keyword.KickerAbility; +import mage.abilities.keyword.KickerWithAnyNumberModesAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -33,12 +33,11 @@ public final class InscriptionOfAbundance extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); // Kicker {2}{G} - this.addAbility(new KickerAbility(new ManaCostsImpl<>("{2}{G}"))); + this.addAbility(new KickerWithAnyNumberModesAbility(new ManaCostsImpl<>("{2}{G}"))); // Choose one. If this spell was kicked, choose any number instead. - this.getSpellAbility().getModes().setAllWhenKicked(true); - // • Put two +1/+1 counters on target creature. + this.getSpellAbility().getModes().setChooseText("choose one. If this spell was kicked, choose any number instead."); this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2))); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/i/InscriptionOfInsight.java b/Mage.Sets/src/mage/cards/i/InscriptionOfInsight.java index 8155354558..5db7f9c492 100644 --- a/Mage.Sets/src/mage/cards/i/InscriptionOfInsight.java +++ b/Mage.Sets/src/mage/cards/i/InscriptionOfInsight.java @@ -7,7 +7,7 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.effects.keyword.ScryEffect; -import mage.abilities.keyword.KickerAbility; +import mage.abilities.keyword.KickerWithAnyNumberModesAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -29,12 +29,11 @@ public final class InscriptionOfInsight extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}"); // Kicker {2}{U}{U} - this.addAbility(new KickerAbility(new ManaCostsImpl<>("{2}{U}{U}"))); + this.addAbility(new KickerWithAnyNumberModesAbility(new ManaCostsImpl<>("{2}{U}{U}"))); // Choose one. If this spell was kicked, choose any number instead. - this.getSpellAbility().getModes().setAllWhenKicked(true); - // • Return up to two target creatures to their owners' hands. + this.getSpellAbility().getModes().setChooseText("choose one. If this spell was kicked, choose any number instead."); this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2)); diff --git a/Mage.Sets/src/mage/cards/i/InscriptionOfRuin.java b/Mage.Sets/src/mage/cards/i/InscriptionOfRuin.java index b4c7c6e57d..2109ecc05c 100644 --- a/Mage.Sets/src/mage/cards/i/InscriptionOfRuin.java +++ b/Mage.Sets/src/mage/cards/i/InscriptionOfRuin.java @@ -5,7 +5,7 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; -import mage.abilities.keyword.KickerAbility; +import mage.abilities.keyword.KickerWithAnyNumberModesAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -40,12 +40,11 @@ public final class InscriptionOfRuin extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}"); // Kicker {2}{B}{B} - this.addAbility(new KickerAbility(new ManaCostsImpl<>("{2}{B}{B}"))); + this.addAbility(new KickerWithAnyNumberModesAbility(new ManaCostsImpl<>("{2}{B}{B}"))); // Choose one. If this spell was kicked, choose any number instead. - this.getSpellAbility().getModes().setAllWhenKicked(true); - // • Target opponent discards two cards. + this.getSpellAbility().getModes().setChooseText("choose one. If this spell was kicked, choose any number instead."); this.getSpellAbility().addEffect(new DiscardTargetEffect(2)); this.getSpellAbility().addTarget(new TargetOpponent()); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EntwineTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EntwineTest.java index 92bc5d8045..437dd6a6ff 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EntwineTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EntwineTest.java @@ -1,4 +1,3 @@ - package org.mage.test.cards.abilities.keywords; import mage.constants.PhaseStep; @@ -7,39 +6,172 @@ import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; /** - * - * @author LevelX2 + * @author LevelX2, JayDi85 */ public class EntwineTest extends CardTestPlayerBase { + @Test + public void test_CastWithoutEntwine() { + // Choose one — + //• Barbed Lightning deals 3 damage to target creature. + //• Barbed Lightning deals 3 damage to target player or planeswalker. + // Entwine {2} (Choose both if you pay the entwine cost.) + addCard(Zone.HAND, playerA, "Barbed Lightning", 1); // {2}{R} + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + // + addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning"); + setChoice(playerA, "No"); // not use Entwine + setModeChoice(playerA, "1"); // target creature + addTarget(playerA, "Balduvian Bears"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertLife(playerA, 20); + assertPermanentCount(playerA, "Balduvian Bears", 0); + assertTappedCount("Mountain", true, 3); + } + + @Test + public void test_CastEntwine_Normal() { + // Choose one — + //• Barbed Lightning deals 3 damage to target creature. + //• Barbed Lightning deals 3 damage to target player or planeswalker. + // Entwine {2} (Choose both if you pay the entwine cost.) + addCard(Zone.HAND, playerA, "Barbed Lightning", 1); // {2}{R} + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3 + 2); + // + addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning"); + setChoice(playerA, "Yes"); // use Entwine + addTarget(playerA, "Balduvian Bears"); + addTarget(playerA, playerA); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertLife(playerA, 20 - 3); + assertPermanentCount(playerA, "Balduvian Bears", 0); + assertTappedCount("Mountain", true, 3 + 2); + } + + @Test + public void test_CastEntwine_CostReduction() { + addCustomEffect_SpellCostModification(playerA, -4); + + // Choose one — + //• Barbed Lightning deals 3 damage to target creature. + //• Barbed Lightning deals 3 damage to target player or planeswalker. + // Entwine {2} (Choose both if you pay the entwine cost.) + addCard(Zone.HAND, playerA, "Barbed Lightning", 1); // {2}{R} + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); // -4 as cost reduction + // + addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning"); + setChoice(playerA, "Yes"); // use Entwine + addTarget(playerA, "Balduvian Bears"); + addTarget(playerA, playerA); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertLife(playerA, 20 - 3); + assertPermanentCount(playerA, "Balduvian Bears", 0); + assertTappedCount("Mountain", true, 1); + } + + @Test + public void test_CastEntwine_CostIncreasing() { + addCustomEffect_SpellCostModification(playerA, 5); + + // Choose one — + //• Barbed Lightning deals 3 damage to target creature. + //• Barbed Lightning deals 3 damage to target player or planeswalker. + // Entwine {2} (Choose both if you pay the entwine cost.) + addCard(Zone.HAND, playerA, "Barbed Lightning", 1); // {2}{R} + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3 + 2 + 5); + // + addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning"); + setChoice(playerA, "Yes"); // use Entwine + addTarget(playerA, "Balduvian Bears"); + addTarget(playerA, playerA); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertLife(playerA, 20 - 3); + assertPermanentCount(playerA, "Balduvian Bears", 0); + assertTappedCount("Mountain", true, 3 + 2 + 5); + } + + @Test + public void test_CastEntwine_FreeFromHand() { + // You may cast nonland cards from your hand without paying their mana costs. + addCard(Zone.BATTLEFIELD, playerA, "Omniscience"); + + // Choose one — + //• Barbed Lightning deals 3 damage to target creature. + //• Barbed Lightning deals 3 damage to target player or planeswalker. + // Entwine {2} (Choose both if you pay the entwine cost.) + addCard(Zone.HAND, playerA, "Barbed Lightning", 1); // {2}{R} + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); // only Entwine pay need + // + addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning"); + setChoice(playerA, "Yes"); // cast for free + setChoice(playerA, "Yes"); // use Entwine + addTarget(playerA, "Balduvian Bears"); + addTarget(playerA, playerA); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertLife(playerA, 20 - 3); + assertPermanentCount(playerA, "Balduvian Bears", 0); + assertTappedCount("Plains", true, 2); + } + @Test public void test_ToothAndNail() { setStrictChooseMode(true); - + addCard(Zone.LIBRARY, playerA, "Silvercoat Lion", 1); addCard(Zone.LIBRARY, playerA, "Pillarfield Ox", 1); - + addCard(Zone.BATTLEFIELD, playerA, "Forest", 9); // Choose one - // Search your library for up to two creature cards, reveal them, put them into your hand, then shuffle your library; // or put up to two creature cards from your hand onto the battlefield. // Entwine {2} addCard(Zone.HAND, playerA, "Tooth and Nail"); // Sorcery {5}{G}{G} - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tooth and Nail"); setChoice(playerA, "Yes"); // Message: Pay Entwine {2} ? addTarget(playerA, "Silvercoat Lion^Pillarfield Ox"); - - setChoice(playerA, "Silvercoat Lion^Pillarfield Ox"); - + setChoice(playerA, "Silvercoat Lion^Pillarfield Ox"); setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); execute(); - assertAllCommandsUsed(); - + assertPermanentCount(playerA, "Silvercoat Lion", 1); assertPermanentCount(playerA, "Pillarfield Ox", 1); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerTest.java index 666acb1073..0728e66cf2 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerTest.java @@ -400,6 +400,7 @@ public class KickerTest extends CardTestPlayerBase { assertTappedCount("Swamp", true, 5); assertGraveyardCount(playerA, "Marsh Casualties", 1); assertPowerToughness(playerB, "Centaur Courser", 1, 1); - } + + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerWithAnyNumberModesAbilityTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerWithAnyNumberModesAbilityTest.java new file mode 100644 index 0000000000..05b8c998fc --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerWithAnyNumberModesAbilityTest.java @@ -0,0 +1,158 @@ +package org.mage.test.cards.abilities.keywords; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author JayDi85 + */ +public class KickerWithAnyNumberModesAbilityTest extends CardTestPlayerBase { + + @Test + public void test_WithoutKicker() { + // Kicker {2}{G} + // Choose one. If this spell was kicked, choose any number instead. + // • Put two +1/+1 counters on target creature. + // • Target player gains X life, where X is the greatest power among creatures they control. + // • Target creature you control fights target creature you don't control. + addCard(Zone.HAND, playerA, "Inscription of Abundance", 1); // {1}{G} + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Inscription of Abundance"); + setChoice(playerA, "No"); // no kicker + setModeChoice(playerA, "1"); + addTarget(playerA, "Balduvian Bears"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertPowerToughness(playerA, "Balduvian Bears", 2 + 2, 2 + 2); + assertLife(playerA, 20); + assertTappedCount("Forest", true, 2); + } + + @Test + public void test_Kicker_Normal() { + // Kicker {2}{G} + // Choose one. If this spell was kicked, choose any number instead. + // • Put two +1/+1 counters on target creature. + // • Target player gains X life, where X is the greatest power among creatures they control. + // • Target creature you control fights target creature you don't control. + addCard(Zone.HAND, playerA, "Inscription of Abundance", 1); // {1}{G} + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2 + 3); + addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Inscription of Abundance"); + setChoice(playerA, "Yes"); // use kicker + setModeChoice(playerA, "2"); + setModeChoice(playerA, "1"); + addTarget(playerA, playerA); // gain x life + addTarget(playerA, "Balduvian Bears"); // get counters + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertPowerToughness(playerA, "Balduvian Bears", 2 + 2, 2 + 2); + assertLife(playerA, 20 + 4); + assertTappedCount("Forest", true, 2 + 3); + } + + @Test + public void test_Kicker_CostReduction() { + addCustomEffect_SpellCostModification(playerA, -4); + + // Kicker {2}{G} + // Choose one. If this spell was kicked, choose any number instead. + // • Put two +1/+1 counters on target creature. + // • Target player gains X life, where X is the greatest power among creatures they control. + // • Target creature you control fights target creature you don't control. + addCard(Zone.HAND, playerA, "Inscription of Abundance", 1); // {1}{G} + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2 + 3 - 3); // -3 by cost reduction + addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Inscription of Abundance"); + setChoice(playerA, "Yes"); // use kicker + setModeChoice(playerA, "2"); + setModeChoice(playerA, "1"); + addTarget(playerA, playerA); // gain x life + addTarget(playerA, "Balduvian Bears"); // get counters + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertPowerToughness(playerA, "Balduvian Bears", 2 + 2, 2 + 2); + assertLife(playerA, 20 + 4); + assertTappedCount("Forest", true, 2 + 3 - 3); + } + + @Test + public void test_Kicker_CostIncreasing() { + addCustomEffect_SpellCostModification(playerA, 5); + + // Kicker {2}{G} + // Choose one. If this spell was kicked, choose any number instead. + // • Put two +1/+1 counters on target creature. + // • Target player gains X life, where X is the greatest power among creatures they control. + // • Target creature you control fights target creature you don't control. + addCard(Zone.HAND, playerA, "Inscription of Abundance", 1); // {1}{G} + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2 + 3 + 5); // +5 by cost increase + addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Inscription of Abundance"); + setChoice(playerA, "Yes"); // use kicker + setModeChoice(playerA, "2"); + setModeChoice(playerA, "1"); + addTarget(playerA, playerA); // gain x life + addTarget(playerA, "Balduvian Bears"); // get counters + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertPowerToughness(playerA, "Balduvian Bears", 2 + 2, 2 + 2); + assertLife(playerA, 20 + 4); + assertTappedCount("Forest", true, 2 + 3 + 5); + } + + @Test + public void test_Kicker_FreeFromHand() { + // You may cast nonland cards from your hand without paying their mana costs. + addCard(Zone.BATTLEFIELD, playerA, "Omniscience"); + + // Kicker {2}{G} + // Choose one. If this spell was kicked, choose any number instead. + // • Put two +1/+1 counters on target creature. + // • Target player gains X life, where X is the greatest power among creatures they control. + // • Target creature you control fights target creature you don't control. + addCard(Zone.HAND, playerA, "Inscription of Abundance", 1); // {1}{G} + addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); // -2 by free cast + addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Inscription of Abundance"); + setChoice(playerA, "Yes"); // use free cast + setChoice(playerA, "Yes"); // use kicker + setModeChoice(playerA, "2"); + setModeChoice(playerA, "1"); + addTarget(playerA, playerA); // gain x life + addTarget(playerA, "Balduvian Bears"); // get counters + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertPowerToughness(playerA, "Balduvian Bears", 2 + 2, 2 + 2); + assertLife(playerA, 20 + 4); + assertTappedCount("Forest", true, 3); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromHandWithoutPayingManaCostTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromHandWithoutPayingManaCostTest.java index d0b8d4e8e1..a9ddf58c33 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromHandWithoutPayingManaCostTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromHandWithoutPayingManaCostTest.java @@ -192,7 +192,7 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase { /** * Omniscience is not allowing me to cast spells for free. I'm playing a * Commander game against the Computer, if that helps. - * + *
* Edit: It's not letting me cast fused spells for free. Others seems to be
* working.
*/
@@ -276,16 +276,23 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase {
// Choose one - Barbed Lightning deals 3 damage to target creature; or Barbed Lightning deals 3 damage to target player.
// Entwine {2} (Choose both if you pay the entwine cost.)
- addCard(Zone.HAND, playerA, "Barbed Lightning", 1);
+ addCard(Zone.HAND, playerA, "Barbed Lightning", 1); // {2}{R}
// Creature - 3/3 Swampwalk
addCard(Zone.BATTLEFIELD, playerB, "Bog Wraith", 1);
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning", "Bog Wraith");
- addTarget(playerA, playerB);
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning");
+ setChoice(playerA, "Yes"); // cast without cost
+ setChoice(playerA, "Yes"); // pay Entwine
+ addTarget(playerA, "Bog Wraith"); // target form mode 1
+ addTarget(playerA, playerB); // target for mode 2
- setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ showBattlefield("after", 1, PhaseStep.POSTCOMBAT_MAIN, playerA);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.END_TURN);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerA, "Barbed Lightning", 1);
assertGraveyardCount(playerB, "Bog Wraith", 1);
@@ -293,7 +300,7 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase {
assertLife(playerA, 20);
assertLife(playerB, 17);
- assertTapped("Plains", true); // plains have to be tapped because {2} from Entwine have to be paid
+ assertTappedCount("Plains", true, 2); // plains have to be tapped because {2} from Entwine have to be paid
}
/**
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/modal/ChooseOneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/modal/ChooseOneTest.java
index 5453c1cb6c..9bed3184a4 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/modal/ChooseOneTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/modal/ChooseOneTest.java
@@ -1,4 +1,3 @@
-
package org.mage.test.cards.modal;
import mage.abilities.keyword.SwampwalkAbility;
@@ -8,7 +7,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
public class ChooseOneTest extends CardTestPlayerBase {
@@ -48,8 +46,10 @@ public class ChooseOneTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Funeral Charm", "Silvercoat Lion");
setModeChoice(playerA, "2");
+ setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerA, "Funeral Charm", 1);
assertPowerToughness(playerB, "Silvercoat Lion", 4, 1);
diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java
index 36567af94b..eb33a433ba 100644
--- a/Mage/src/main/java/mage/abilities/AbilityImpl.java
+++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java
@@ -1,9 +1,5 @@
package mage.abilities;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.UUID;
import mage.MageIdentifier;
import mage.MageObject;
import mage.abilities.costs.*;
@@ -36,6 +32,11 @@ import mage.util.ThreadLocalStringBuilder;
import mage.watchers.Watcher;
import org.apache.log4j.Logger;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.UUID;
+
/**
* @author BetaSteward_at_googlemail.com
*/
@@ -227,22 +228,10 @@ public abstract class AbilityImpl implements Ability {
}
game.applyEffects();
- /* 20130201 - 601.2b
- * If the spell is modal the player announces the mode choice (see rule 700.2).
- */
- if (!getModes().choose(game, this)) {
- return false;
- }
-
MageObject sourceObject = getSourceObject(game);
if (getSourceObjectZoneChangeCounter() == 0) {
setSourceObjectZoneChangeCounter(game.getState().getZoneChangeCounter(getSourceId()));
}
- if (controller.isTestMode()) {
- if (!controller.addTargets(this, game)) {
- return false;
- }
- }
/* 20130201 - 601.2b
* If the player wishes to splice any cards onto the spell (see rule 702.45), he
@@ -268,9 +257,6 @@ public abstract class AbilityImpl implements Ability {
}
}
- if (getModes().getAdditionalCost() != null) {
- getModes().getAdditionalCost().addOptionalAdditionalModeCosts(this, game);
- }
// 20130201 - 601.2b
// If the spell has alternative or additional costs that will be paid as it's being cast such
// as buyback, kicker, or convoke costs (see rules 117.8 and 117.9), the player announces his
@@ -311,8 +297,29 @@ public abstract class AbilityImpl implements Ability {
handlePhyrexianManaCosts(game, sourceId, controller);
+ /* 20130201 - 601.2b
+ * If the spell is modal the player announces the mode choice (see rule 700.2).
+ */
+ // rules:
+ // You kick a spell as you cast it. You declare whether you're going to pay a kicker cost at the same
+ // time you'd choose a spell's mode, and then you actually pay it at the same time you pay the spell's mana cost.
+ // Kicking a spell is always optional.
+ if (!getModes().choose(game, this)) {
+ return false;
+ }
+
+ // unit tests only: it allows to add targets/choices by two ways:
+ // 1. From cast/activate command params (process it here)
+ // 2. From single addTarget/setChoice, it's a preffered method for tests (process it in normal choose dialogs like human player)
+ if (controller.isTestMode()) {
+ if (!controller.addTargets(this, game)) {
+ return false;
+ }
+ }
+
for (UUID modeId : this.getModes().getSelectedModes()) {
this.getModes().setActiveMode(modeId);
+
//20121001 - 601.2c
// 601.2c The player announces their choice of an appropriate player, object, or zone for
// each target the spell requires. A spell may require some targets only if an alternative or
@@ -333,8 +340,10 @@ public abstract class AbilityImpl implements Ability {
if (sourceObject != null && this.getAbilityType() != AbilityType.TRIGGERED) { // triggered abilities check this already in playerImpl.triggerAbility
sourceObject.adjustTargets(this, game);
}
+
if (!getTargets().isEmpty()) {
Outcome outcome = getEffects().getOutcome(this);
+
// only activated abilities can be canceled by human user (not triggered)
boolean canCancel = this instanceof ActivatedAbility && controller.isHuman();
if (!getTargets().chooseTargets(outcome, this.controllerId, this, noMana, game, canCancel)) {
@@ -434,7 +443,11 @@ public abstract class AbilityImpl implements Ability {
boolean alternativeCostUsed = false;
if (sourceObject != null && !(sourceObject instanceof Permanent)) {
+ // it's important to apply alternative cost first
+ // example: Omniscience gives free mana as alternative, but Entwine ability adds {2} as additional
Abilities