diff --git a/Mage.Sets/src/mage/sets/alarareborn/MeddlingMage.java b/Mage.Sets/src/mage/sets/alarareborn/MeddlingMage.java index 2ab7ca6092b..e460268a654 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/MeddlingMage.java +++ b/Mage.Sets/src/mage/sets/alarareborn/MeddlingMage.java @@ -27,6 +27,7 @@ */ package mage.sets.alarareborn; +import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -35,13 +36,15 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.common.NameACardEffect; import mage.cards.CardImpl; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import java.util.UUID; - /** * * @author Plopman @@ -54,8 +57,6 @@ public class MeddlingMage extends CardImpl { this.subtype.add("Human"); this.subtype.add("Wizard"); - - this.power = new MageInt(2); this.toughness = new MageInt(2); @@ -118,4 +119,4 @@ class MeddlingMageReplacementEffect extends ContinuousRuleModifyingEffectImpl { return object != null && !object.isCopy() && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY)); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/avacynrestored/WildDefiance.java b/Mage.Sets/src/mage/sets/avacynrestored/WildDefiance.java index 309a9128d61..858c6b9a858 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/WildDefiance.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/WildDefiance.java @@ -93,7 +93,7 @@ class CreaturesYouControlBecomesTargetTriggeredAbility extends TriggeredAbilityI if (permanent != null && permanent.getControllerId().equals(this.controllerId) && permanent.getCardType().contains(CardType.CREATURE)) { MageObject object = game.getObject(event.getSourceId()); if (object != null && object instanceof Spell) { - Card c = (Spell)object; + Card c = (Spell) object; if (c.getCardType().contains(CardType.INSTANT) || c.getCardType().contains(CardType.SORCERY)) { if (getTargets().size() == 0) { for (Effect effect : getEffects()) { @@ -109,6 +109,6 @@ class CreaturesYouControlBecomesTargetTriggeredAbility extends TriggeredAbilityI @Override public String getRule() { - return "Whenever a creature you control becomes the target of an instant or sorcery spell, that creature gets +3/+3 until end of turn"; + return "Whenever a creature you control becomes the target of an instant or sorcery spell, that creature gets +3/+3 until end of turn."; } } diff --git a/Mage.Sets/src/mage/sets/worldwake/Groundswell.java b/Mage.Sets/src/mage/sets/worldwake/Groundswell.java index 9598babd39e..fdcb5411d82 100644 --- a/Mage.Sets/src/mage/sets/worldwake/Groundswell.java +++ b/Mage.Sets/src/mage/sets/worldwake/Groundswell.java @@ -1,16 +1,16 @@ /* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR @@ -20,24 +20,22 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.worldwake; import java.util.UUID; - +import mage.abilities.condition.common.LandfallCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.AddContinuousEffectToGame; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Rarity; -import mage.abilities.condition.LockedInCondition; -import mage.abilities.condition.common.LandfallCondition; -import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.effects.common.continuous.BoostTargetEffect; -import mage.cards.CardImpl; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.LandfallWatcher; @@ -54,8 +52,10 @@ public class Groundswell extends CardImpl { // Target creature gets +2/+2 until end of turn. //Landfall - If you had a land enter the battlefield under your control this turn, that creature gets +4/+4 until end of turn instead. this.getSpellAbility().addWatcher(new LandfallWatcher()); - this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new BoostTargetEffect(4, 4, Duration.EndOfTurn), new BoostTargetEffect(2, 2, Duration.EndOfTurn), - new LockedInCondition(LandfallCondition.getInstance()), + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new AddContinuousEffectToGame(new BoostTargetEffect(4, 4, Duration.EndOfTurn)), + new AddContinuousEffectToGame(new BoostTargetEffect(2, 2, Duration.EndOfTurn)), + LandfallCondition.getInstance(), "Target creature gets +2/+2 until end of turn.
Landfall — If you had a land enter the battlefield under your control this turn, that creature gets +4/44 until end of turn instead")); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/sets/zendikar/CelestialMantle.java b/Mage.Sets/src/mage/sets/zendikar/CelestialMantle.java index b1a4a82922f..d6565ac388e 100644 --- a/Mage.Sets/src/mage/sets/zendikar/CelestialMantle.java +++ b/Mage.Sets/src/mage/sets/zendikar/CelestialMantle.java @@ -25,9 +25,9 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.zendikar; +import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleStaticAbility; @@ -36,7 +36,11 @@ import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; @@ -46,30 +50,32 @@ import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -import java.util.UUID; - /** * * @author Loki */ public class CelestialMantle extends CardImpl { - public CelestialMantle (UUID ownerId) { + public CelestialMantle(UUID ownerId) { super(ownerId, 6, "Celestial Mantle", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{W}{W}"); this.expansionSetCode = "ZEN"; this.subtype.add("Aura"); - + // Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); + + // Enchanted creature gets +3/+3. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(3, 3, Duration.WhileOnBattlefield))); + + // Whenever enchanted creature deals combat damage to a player, double its controller's life total. this.addAbility(new CelestialMantleAbility()); } - public CelestialMantle (final CelestialMantle card) { + public CelestialMantle(final CelestialMantle card) { super(card); } @@ -102,7 +108,7 @@ class CelestialMantleAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event; + DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; Permanent p = game.getPermanent(event.getSourceId()); return damageEvent.isCombatDamage() && p != null && p.getAttachments().contains(this.getSourceId()); } @@ -114,6 +120,7 @@ class CelestialMantleAbility extends TriggeredAbilityImpl { } class CelestialMantleEffect extends OneShotEffect { + CelestialMantleEffect() { super(Outcome.GainLife); } diff --git a/Mage.Tests/src/test/java/org/mage/test/AI/basic/PreventRepeatedActionsTest.java b/Mage.Tests/src/test/java/org/mage/test/AI/basic/PreventRepeatedActionsTest.java index 7237a3fc9b8..1a6259d8e10 100644 --- a/Mage.Tests/src/test/java/org/mage/test/AI/basic/PreventRepeatedActionsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/AI/basic/PreventRepeatedActionsTest.java @@ -83,4 +83,26 @@ public class PreventRepeatedActionsTest extends CardTestPlayerBaseAI { assertTapped("Basalt Monolith", false); } + + /** + * AI gets stuck with two Kiora's Followers #1167 + */ + @Test + public void testKiorasFollower() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2, true); + // {T}: Untap another target permanent. + addCard(Zone.BATTLEFIELD, playerA, "Kiora's Follower", 1, true); + addCard(Zone.BATTLEFIELD, playerA, "Kiora's Follower", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 2); + + attack(2, playerB, "Silvercoat Lion"); + attack(2, playerB, "Silvercoat Lion"); + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 16); + assertTapped("Kiora's Follower", false); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/LandfallTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/LandfallTest.java index 5e3b1b177cc..e1eae68db04 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/LandfallTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/LandfallTest.java @@ -30,6 +30,7 @@ package org.mage.test.cards.abilities.keywords; import mage.abilities.keyword.IntimidateAbility; import mage.constants.PhaseStep; import mage.constants.Zone; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -37,22 +38,21 @@ import org.mage.test.serverside.base.CardTestPlayerBase; * * @author LevelX2 */ - public class LandfallTest extends CardTestPlayerBase { @Test public void testNormalUse() { - addCard(Zone.BATTLEFIELD, playerA, "Plains",3); - addCard(Zone.HAND, playerA, "Plains"); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + addCard(Zone.HAND, playerA, "Plains"); // Instant - {1}{W} // Target player gains 4 life. - // Landfall - If you had a land enter the battlefield under your control this turn, that player gains 8 life instead. - addCard(Zone.HAND, playerA, "Rest for the Weary",2); - + // Landfall - If you had a land enter the battlefield under your control this turn, that player gains 8 life instead. + addCard(Zone.HAND, playerA, "Rest for the Weary", 2); + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rest for the Weary"); - + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Rest for the Weary"); setStopAt(2, PhaseStep.BEGIN_COMBAT); @@ -61,57 +61,59 @@ public class LandfallTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Plains", 4); assertGraveyardCount(playerA, "Rest for the Weary", 2); assertLife(playerA, 32); // + 8 from 1 turn + 4 from second turn - assertLife(playerB, 20); - - } + assertLife(playerB, 20); + + } + /** - * If you Hive Mind an opponent's Rest for the Weary and redirect its target to yourself when it's not your turn, - * the game spits out this message and rolls back to before Rest for the Weary was cast. - * + * If you Hive Mind an opponent's Rest for the Weary and redirect its target + * to yourself when it's not your turn, the game spits out this message and + * rolls back to before Rest for the Weary was cast. + * */ @Test public void testHiveMind() { - addCard(Zone.BATTLEFIELD, playerA, "Plains",2); - + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + // Whenever a player casts an instant or sorcery spell, each other player copies that spell. Each of those players may choose new targets for his or her copy. - addCard(Zone.BATTLEFIELD, playerB, "Hive Mind"); + addCard(Zone.BATTLEFIELD, playerB, "Hive Mind"); // Instant - {1}{W} // Target player gains 4 life. - // Landfall - If you had a land enter the battlefield under your control this turn, that player gains 8 life instead. - addCard(Zone.HAND, playerA, "Rest for the Weary",1); - - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rest for the Weary"); + // Landfall - If you had a land enter the battlefield under your control this turn, that player gains 8 life instead. + addCard(Zone.HAND, playerA, "Rest for the Weary", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rest for the Weary"); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); assertGraveyardCount(playerA, "Rest for the Weary", 1); - assertLife(playerA, 24); - assertLife(playerB, 24); - - } - + assertLife(playerA, 24); + assertLife(playerB, 24); + + } + @Test public void testSurrakarMarauder() { - // Landfall - Whenever a land enters the battlefield under your control, Surrakar Marauder gains intimidate until end of turn. - addCard(Zone.BATTLEFIELD, playerA, "Surrakar Marauder",1); - addCard(Zone.HAND, playerA, "Plains"); - + // Landfall - Whenever a land enters the battlefield under your control, Surrakar Marauder gains intimidate until end of turn. + addCard(Zone.BATTLEFIELD, playerA, "Surrakar Marauder", 1); + addCard(Zone.HAND, playerA, "Plains"); + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains"); - + setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); assertPermanentCount(playerA, "Plains", 1); - + assertAbility(playerA, "Surrakar Marauder", IntimidateAbility.getInstance(), true); - - assertLife(playerA, 20); - assertLife(playerB, 20); - - } - + + assertLife(playerA, 20); + assertLife(playerB, 20); + + } + /** * Searing Blaze's landfall doesn't appear to be working. My opponent played * a mountain, then played searing blaze targeting my Tasigur, the Golden @@ -122,82 +124,98 @@ public class LandfallTest extends CardTestPlayerBase { public void testSearingBlaze() { // Searing Blaze deals 1 damage to target player and 1 damage to target creature that player controls. // Landfall - If you had a land enter the battlefield under your control this turn, Searing Blaze deals 3 damage to that player and 3 damage to that creature instead. - addCard(Zone.HAND, playerA, "Searing Blaze",1); - addCard(Zone.BATTLEFIELD, playerA, "Mountain",1); - addCard(Zone.HAND, playerA, "Mountain"); + addCard(Zone.HAND, playerA, "Searing Blaze", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + addCard(Zone.HAND, playerA, "Mountain"); - addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion",1); + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1); - playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain"); - - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Searing Blaze"); - - + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Searing Blaze"); + setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); assertPermanentCount(playerA, "Mountain", 2); - assertGraveyardCount(playerA, "Searing Blaze" , 1); - - assertLife(playerA, 20); - assertLife(playerB, 17); - - assertGraveyardCount(playerB, "Silvercoat Lion" , 1); - - } + assertGraveyardCount(playerA, "Searing Blaze", 1); + + assertLife(playerA, 20); + assertLife(playerB, 17); + + assertGraveyardCount(playerB, "Silvercoat Lion", 1); + + } @Test public void testGroundswellWithoutLandfall() { // Target creature gets +2/+2 until end of turn. //Landfall - If you had a land enter the battlefield under your control this turn, that creature gets +4/+4 until end of turn instead. - addCard(Zone.HAND, playerB, "Groundswell",1); - addCard(Zone.BATTLEFIELD, playerB, "Forest",1); + addCard(Zone.HAND, playerB, "Groundswell", 1); + addCard(Zone.BATTLEFIELD, playerB, "Forest", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1); - addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion",1); - attack(2, playerB, "Silvercoat Lion"); - castSpell(2, PhaseStep.DECLARE_ATTACKERS, playerB, "Groundswell", "Silvercoat Lion"); - - + castSpell(2, PhaseStep.DECLARE_ATTACKERS, playerB, "Groundswell", "Silvercoat Lion"); + setStopAt(2, PhaseStep.END_COMBAT); execute(); assertPermanentCount(playerB, "Forest", 1); - assertGraveyardCount(playerB, "Groundswell" , 1); + assertGraveyardCount(playerB, "Groundswell", 1); - assertPermanentCount(playerB, "Silvercoat Lion" , 1); + assertPermanentCount(playerB, "Silvercoat Lion", 1); assertPowerToughness(playerB, "Silvercoat Lion", 4, 4); - + assertLife(playerA, 16); // 2 + 4 - assertLife(playerB, 20); - } - + assertLife(playerB, 20); + } + + /* + 21:09: Turn 8 arucki (25 - 16) + 21:09: arucki draws a card + 21:09: Ability triggers: Sylvan Library [868] - At the beginning of your draw step, you may draw two additional cards. If you do, choose two cards in your hand drawn this turn. For each of those cards, pay 4 life or put the card on top of your library. + 21:09: arucki draws two cards + 21:09: arucki loses 4 life + 21:09: arucki pays 4 life to keep a card on hand + 21:09: arucki puts 1 card(s) back to library + 21:09: arucki plays Twilight Mire [f4d] + 21:10: arucki activates: Inkmoth Nexus [1b5] becomes a 1/1 Blinkmoth artifact creature with flying and infect until end of turn. It's still a land. (It deals damage to creatures in the form of -1/-1 counters and to players in the form of poison counters.). from Inkmoth Nexus [1b5] + 21:10: arucki casts Groundswell [b28] targeting Inkmoth Nexus [1b5] + 21:10: Ability triggers: Wild Defiance [990] - Whenever a creature you control becomes the target of an instant or sorcery spell, that creature gets +3/+3 until end of turn + 21:10: arucki puts Groundswell [b28] from stack into his or her graveyard + 21:10: arucki attacks with 1 creature + 21:10: Attacker: Inkmoth Nexus 1b5 unblocked + */ @Test + @Ignore public void testGroundswellWithLandfall() { // Target creature gets +2/+2 until end of turn. //Landfall - If you had a land enter the battlefield under your control this turn, that creature gets +4/+4 until end of turn instead. - addCard(Zone.HAND, playerB, "Groundswell",1); - addCard(Zone.HAND, playerB, "Forest"); + addCard(Zone.HAND, playerB, "Groundswell", 1); // Instant + addCard(Zone.BATTLEFIELD, playerB, "Forest"); + addCard(Zone.HAND, playerB, "Twilight Mire"); - addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion",1); + // Whenever a creature you control becomes the target of an instant or sorcery spell, that creature gets +3/+3 until end of turn. + addCard(Zone.BATTLEFIELD, playerB, "Wild Defiance", 1); - - playLand(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Forest"); + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1); + + playLand(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Twilight Mire"); attack(2, playerB, "Silvercoat Lion"); - castSpell(2, PhaseStep.DECLARE_ATTACKERS, playerB, "Groundswell", "Silvercoat Lion"); - - + castSpell(2, PhaseStep.DECLARE_ATTACKERS, playerB, "Groundswell", "Silvercoat Lion"); + setStopAt(2, PhaseStep.END_COMBAT); execute(); - assertPermanentCount(playerB, "Forest", 1); - assertGraveyardCount(playerB, "Groundswell" , 1); + assertPermanentCount(playerB, "Twilight Mire", 1); + assertGraveyardCount(playerB, "Groundswell", 1); - assertPermanentCount(playerB, "Silvercoat Lion" , 1); - assertPowerToughness(playerB, "Silvercoat Lion", 6, 6); - - assertLife(playerA, 14); // 2 + 4 - assertLife(playerB, 20); - } + assertPermanentCount(playerB, "Silvercoat Lion", 1); + assertPowerToughness(playerB, "Silvercoat Lion", 9, 9); + + assertLife(playerA, 11); // 2 + 4 + 3 + assertLife(playerB, 20); + } } diff --git a/Mage/src/mage/abilities/effects/common/continuous/BoostTargetEffect.java b/Mage/src/mage/abilities/effects/common/continuous/BoostTargetEffect.java index 0cbb14b528d..1d11baae793 100644 --- a/Mage/src/mage/abilities/effects/common/continuous/BoostTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/continuous/BoostTargetEffect.java @@ -115,8 +115,11 @@ public class BoostTargetEffect extends ContinuousEffectImpl { if (staticText != null && !staticText.isEmpty()) { return staticText; } - StringBuilder sb = new StringBuilder(); + if (mode == null || mode.getTargets().size() == 0) { + return "no target"; + } Target target = mode.getTargets().get(0); + StringBuilder sb = new StringBuilder(); if (target.getMaxNumberOfTargets() > 1) { if (target.getNumberOfTargets() < target.getNumberOfTargets()) { sb.append("up to ");