diff --git a/Mage.Sets/src/mage/cards/p/PublicExecution.java b/Mage.Sets/src/mage/cards/p/PublicExecution.java index bd08413a7d8..c5f8e25780c 100644 --- a/Mage.Sets/src/mage/cards/p/PublicExecution.java +++ b/Mage.Sets/src/mage/cards/p/PublicExecution.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; @@ -19,20 +17,21 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class PublicExecution extends CardImpl { - + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature an opponent controls"); - + static { - filter.add(new ControllerPredicate(TargetController.NOT_YOU)); + filter.add(new ControllerPredicate(TargetController.OPPONENT)); } public PublicExecution(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{5}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{5}{B}"); // Destroy target creature an opponent controls. Each other creature that player controls gets -2/-0 until end of turn. this.getSpellAbility().addEffect(new DestroyTargetEffect()); @@ -51,7 +50,7 @@ public final class PublicExecution extends CardImpl { } class PublicExecutionEffect extends OneShotEffect { - + public PublicExecutionEffect() { super(Outcome.Benefit); staticText = "Each other creature that player controls gets -2/-0 until end of turn"; @@ -70,7 +69,7 @@ class PublicExecutionEffect extends OneShotEffect { FilterCreaturePermanent filter = new FilterCreaturePermanent("each other creature that player controls"); filter.add(new ControllerIdPredicate(opponent)); filter.add(Predicates.not(new PermanentIdPredicate(target.getId()))); - ContinuousEffect effect = new BoostAllEffect(-2,0, Duration.EndOfTurn, filter, false); + ContinuousEffect effect = new BoostAllEffect(-2, 0, Duration.EndOfTurn, filter, false); game.addEffect(effect, source); return true; } diff --git a/Mage.Sets/src/mage/cards/t/TreasureKeeper.java b/Mage.Sets/src/mage/cards/t/TreasureKeeper.java index 640272be9af..7b6391b2460 100644 --- a/Mage.Sets/src/mage/cards/t/TreasureKeeper.java +++ b/Mage.Sets/src/mage/cards/t/TreasureKeeper.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; @@ -17,8 +15,9 @@ import mage.constants.SubType; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author fireshoes */ public final class TreasureKeeper extends CardImpl { @@ -71,7 +70,7 @@ class TreasureKeeperEffect extends OneShotEffect { } } controller.revealCards(source, toReveal, game); - if (nonLandCard != null && controller.chooseUse(outcome, "Cast " + nonLandCard.getLogName() + "without paying its mana cost?", source, game)) { + if (nonLandCard != null && controller.chooseUse(outcome, "Cast " + nonLandCard.getLogName() + " without paying its mana cost?", source, game)) { controller.cast(nonLandCard.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game)); toReveal.remove(nonLandCard); } diff --git a/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java b/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java index e7723d4f9ff..234266a6fa7 100644 --- a/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java +++ b/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java @@ -1,4 +1,3 @@ - package mage.cards.v; import mage.MageInt; @@ -77,8 +76,6 @@ class VesuvanShapeShifterFaceUpApplier extends ApplyToPermanent { Effect effect = new VesuvanShapeshifterFaceDownEffect(); Ability ability = new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, true); permanent.getAbilities().add(ability); - // Why is this needed? - permanent.addAbility(new MorphAbility(permanent, new ManaCostsImpl("{1}{U}")), permanent.getId(), game); return true; } diff --git a/Mage.Tests/src/test/java/org/mage/test/AI/basic/ExileTargetTest.java b/Mage.Tests/src/test/java/org/mage/test/AI/basic/ExileTargetTest.java new file mode 100644 index 00000000000..d8fcb3abec0 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/AI/basic/ExileTargetTest.java @@ -0,0 +1,42 @@ +package org.mage.test.AI.basic; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestCommander4Players; + +/** + * @author JayDi85 + */ +public class ExileTargetTest extends CardTestCommander4Players { + + // Player order: A -> D -> C -> B + + @Test + public void test_chooseOpponentTargets() { + // AI sometimes chooses own permanents in multiplayer game instead opponents + + // When Oblivion Ring enters the battlefield, exile another target nonland permanent. + // When Oblivion Ring leaves the battlefield, return the exiled card to the battlefield under its owner’s control. + addCard(Zone.HAND, playerA, "Oblivion Ring", 1); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + // + addCard(Zone.BATTLEFIELD, playerA, "Apex Altisaur", 1); // 10/10 + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1); // 2/2 + addCard(Zone.BATTLEFIELD, playerC, "Balduvian Bears", 1); // 2/2 + + // must select opponent's Balduvian Bears + showAvaileableAbilities("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oblivion Ring"); + //addTarget(playerA, "Balduvian Bears"); // disable to activate AI target choose + + showAvaileableAbilities("after", 1, PhaseStep.BEGIN_COMBAT, playerA); + + //setStrictChooseMode(true); // disable strict mode to activate AI for choosing + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerC, "Balduvian Bears", 0); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EchoTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EchoTest.java index 07cf2e1902d..2d610e86c6b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EchoTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EchoTest.java @@ -36,7 +36,7 @@ public class EchoTest extends CardTestPlayerBase { // cast Avalanche Riders and destroy forest - addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Avalanche Riders"); addTarget(playerA, "Forest"); @@ -45,10 +45,19 @@ public class EchoTest extends CardTestPlayerBase { activateManaAbility(3, PhaseStep.UPKEEP, playerA, "{T}: Add {W}"); activateManaAbility(3, PhaseStep.UPKEEP, playerA, "{T}: Add {W}"); activateManaAbility(3, PhaseStep.UPKEEP, playerA, "{T}: Add {W}"); - castSpell(3, PhaseStep.UPKEEP, playerA, "Restoration Angel", null, "Echo {3}{R} (At the beginning of your upkeep, if this came under your control since the beginning of your last upkeep, sacrifice it unless you pay its echo cost.)"); + castSpell(3, PhaseStep.UPKEEP, playerA, "Restoration Angel"); + addTarget(playerA, "Avalanche Riders"); setChoice(playerA, "Yes"); // raider do restore + + // Avalanche Riders triggered again + addTarget(playerA, "Forest"); + + // but no echo for blinked rider + + setStrictChooseMode(true); setStopAt(3, PhaseStep.PRECOMBAT_MAIN); execute(); + assertAllCommandsUsed(); assertLife(playerA, 20); assertLife(playerB, 20); @@ -56,7 +65,8 @@ public class EchoTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Avalanche Riders", 1); assertPermanentCount(playerA, "Restoration Angel", 1); - assertPermanentCount(playerB, "Forest", 0); + assertPermanentCount(playerA, "Forest", 0); + assertGraveyardCount(playerA, "Forest", 2); assertTappedCount("Plains", true, 4); assertTappedCount("Mountain", true, 0); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java index 50bf73e391a..8ebd4f72878 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java @@ -717,14 +717,22 @@ public class MorphTest extends CardTestPlayerBase { * not work correctly. When Vesuvan Shapeshifter turns face up and becomes a * copy of the targeted creature, it should still be in the state of * "turning face up", thus triggering the ability of the Brine Elemental. + *
+ * combo: + * Vesuvan Shapeshifter + Brine Elemental + * Brine Elemental in play, Vesuvan Shapeshifter in hand + * 1) Cast Vesuvan Shapeshifter face-down. + * 2) Flip Vesuvan Shapeshifter for its morph cost, copying Brine Elemental. Your opponent skips his next untap. + * 3) During your upkeep, flip Vesuvan Shapeshifter face-down. + * 4) Repeat from 2. */ @Test public void testVesuvanShapeshifter() { // Morph {5}{U}{U} // When Brine Elemental is turned face up, each opponent skips their next untap step. - addCard(Zone.HAND, playerA, "Brine Elemental"); // Creature {4}{U}{U} 5/4 - addCard(Zone.BATTLEFIELD, playerA, "Island", 6); + addCard(Zone.BATTLEFIELD, playerA, "Brine Elemental"); // Creature {4}{U}{U} 5/4 + //addCard(Zone.BATTLEFIELD, playerA, "Island", 6); // As Vesuvan Shapeshifter enters the battlefield or is turned face up, you may choose another creature on the battlefield. // If you do, until Vesuvan Shapeshifter is turned face down, it becomes a copy of that creature @@ -733,23 +741,24 @@ public class MorphTest extends CardTestPlayerBase { addCard(Zone.HAND, playerB, "Vesuvan Shapeshifter"); // Creature 0/0 addCard(Zone.BATTLEFIELD, playerB, "Island", 5); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brine Elemental"); - setChoice(playerA, "No"); // cast it normally - + // 1. Cast Vesuvan as face-down castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Vesuvan Shapeshifter"); - setChoice(playerB, "Yes"); + setChoice(playerB, "Yes"); // cast as face-down + // 2. Moth Vesuvan and copy brine activateAbility(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "{1}{U}: Turn this face-down permanent"); - setChoice(playerB, "Brine Elemental"); + addTarget(playerB, "Brine Elemental"); + // No face up trigger and choose from Vesuvan + // But brine's trigger must works on next turn 3 (skip untap) + + setStrictChooseMode(true); setStopAt(2, PhaseStep.END_TURN); - execute(); + assertAllCommandsUsed(); assertPermanentCount(playerA, "Brine Elemental", 1); - assertPermanentCount(playerB, "Brine Elemental", 1); - Assert.assertTrue("Skip next turn has to be added to TurnMods", currentGame.getState().getTurnMods().size() == 1); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/AngelOfJubilationTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/AngelOfJubilationTest.java index e5ce6a0800f..1f3373df032 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/AngelOfJubilationTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/AngelOfJubilationTest.java @@ -83,11 +83,13 @@ public class AngelOfJubilationTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Food Chain"); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{2}, Sacrifice a permanent you control: Return target creature to its owner's hand."); - playerB.addChoice("Food Chain"); - playerA.addTarget("Angel of Jubilation"); + addTarget(playerB, "Angel of Jubilation"); // return to hand + setChoice(playerB, "Food Chain"); // cacrifice cost + setStrictChooseMode(true); setStopAt(1, PhaseStep.END_TURN); execute(); + assertAllCommandsUsed(); assertPermanentCount(playerA, "Angel of Jubilation", 0); assertPermanentCount(playerB, "Food Chain", 0); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/control/GainControlDiedCastAgainTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/control/GainControlDiedCastAgainTest.java index 66977a02087..43cf81ec556 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/control/GainControlDiedCastAgainTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/control/GainControlDiedCastAgainTest.java @@ -42,10 +42,12 @@ public class GainControlDiedCastAgainTest extends CardTestPlayerBase { attack(2, playerB, "Elesh Norn, Grand Cenobite"); block(2, playerA, "Keiga, the Tide Star", "Elesh Norn, Grand Cenobite"); - addTarget(playerB, "Elesh Norn, Grand Cenobite"); + addTarget(playerA, "Elesh Norn, Grand Cenobite"); + setStrictChooseMode(true); setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); execute(); + assertAllCommandsUsed(); assertLife(playerA, 20); assertLife(playerB, 20); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/MisdirectionTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/MisdirectionTest.java index efb30757b70..489e3310ebb 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/MisdirectionTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/MisdirectionTest.java @@ -99,6 +99,7 @@ public class MisdirectionTest extends CardTestPlayerBase { } // check to change target permanent creature legal to to a creature the opponent of the spell controller controls + // target to illegal target can't be tested @Test public void test_ChangePublicExecution() { // Destroy target creature an opponent controls. Each other creature that player controls gets -2/-0 until end of turn. @@ -129,41 +130,5 @@ public class MisdirectionTest extends CardTestPlayerBase { assertGraveyardCount(playerB, "Custodian of the Trove", 1); assertPermanentCount(playerB, "Pillarfield Ox", 1); assertPowerToughness(playerB, "Pillarfield Ox", 0, 4); - - } - - // check to change target permanent creature not legal to to a creature the your opponent controls - @Test - public void test_ChangePublicExecution2() { - // Destroy target creature an opponent controls. Each other creature that player controls gets -2/-0 until end of turn. - addCard(Zone.HAND, playerA, "Public Execution"); - addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6); - addCard(Zone.BATTLEFIELD, playerA, "Keeper of the Lens", 1); - /* - Misdirection {3}{U}{U} - Instant - You may exile a blue card from your hand rather than pay Misdirection's mana cost. - Change the target of target spell with a single target. - */ - addCard(Zone.HAND, playerB, "Misdirection"); - addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1); - addCard(Zone.BATTLEFIELD, playerB, "Custodian of the Trove", 1); // 4/3 - addCard(Zone.BATTLEFIELD, playerB, "Island", 5); - - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Public Execution", "Custodian of the Trove"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Misdirection", "Public Execution", "Public Execution"); - - setStopAt(1, PhaseStep.BEGIN_COMBAT); - execute(); - assertAllCommandsUsed(); - - assertGraveyardCount(playerA, "Public Execution", 1); - assertGraveyardCount(playerB, "Misdirection", 1); - assertPermanentCount(playerA, "Keeper of the Lens", 1); - - assertPermanentCount(playerB, "Pillarfield Ox", 1); - assertPowerToughness(playerB, "Pillarfield Ox", 0, 4); - - assertGraveyardCount(playerB, "Custodian of the Trove", 1); } } \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/akh/DecimatorBeetleTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/akh/DecimatorBeetleTest.java index 2354b76a18f..8519ec3ecaa 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/akh/DecimatorBeetleTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/akh/DecimatorBeetleTest.java @@ -7,7 +7,6 @@ import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; /** - * * @author escplan9 */ public class DecimatorBeetleTest extends CardTestPlayerBase { @@ -19,29 +18,33 @@ When Decimator Beetle enters the battlefield, put a -1/-1 counter on target crea Whenever Decimator Beetle attacks, remove a -1/-1 counter from target creature you control and put a -1/-1 counter on up to one target creature defending player controls. */ private final String decimator = "Decimator Beetle"; - + @Test public void targetOpponentCreatureWithDecimator() { - + String grizzly = "Grizzly Bears"; // {1}{G} 2/2 String hillGiant = "Hill Giant"; // {3}{R} 3/3 - + addCard(Zone.HAND, playerA, decimator); addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); addCard(Zone.BATTLEFIELD, playerA, grizzly); addCard(Zone.BATTLEFIELD, playerB, hillGiant); - + + // put -1/-1 on own creature castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, decimator); addTarget(playerA, grizzly); - + + // remove -1/-1 from own creature and put to defender control attack(3, playerA, decimator); - addTarget(playerA, grizzly); - addTarget(playerA, hillGiant); - + addTarget(playerA, grizzly); // remove + addTarget(playerA, hillGiant); // put + + setStrictChooseMode(true); setStopAt(3, PhaseStep.END_COMBAT); execute(); - + assertAllCommandsUsed(); + assertPowerToughness(playerA, grizzly, 2, 2); // had -1/-1 counter, but removed on attack assertPowerToughness(playerB, hillGiant, 2, 2); // gets -1/-1 counter from decimator attack ability assertCounterCount(playerA, grizzly, CounterType.M1M1, 0); diff --git a/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java b/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java index dc56b7a4990..14911f29176 100644 --- a/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java @@ -250,7 +250,7 @@ public class LoadTest { } @Test - //@Ignore + @Ignore public void test_TwoAIPlayGame_Multiple() { // save random seeds for repeated results