From 17ba61e1aab359cacebc7af6460a42aab33a83e3 Mon Sep 17 00:00:00 2001 From: klayhamn Date: Tue, 28 Jul 2015 09:45:24 +0300 Subject: [PATCH 1/5] remove independent RippleEffect and replace with RippleAbility --- .../RippleAbility.java} | 91 +++++++++++-------- 1 file changed, 55 insertions(+), 36 deletions(-) rename Mage/src/mage/abilities/{effects/keyword/RippleEffect.java => keyword/RippleAbility.java} (55%) diff --git a/Mage/src/mage/abilities/effects/keyword/RippleEffect.java b/Mage/src/mage/abilities/keyword/RippleAbility.java similarity index 55% rename from Mage/src/mage/abilities/effects/keyword/RippleEffect.java rename to Mage/src/mage/abilities/keyword/RippleAbility.java index db5dd8a718..3b2735906b 100644 --- a/Mage/src/mage/abilities/effects/keyword/RippleEffect.java +++ b/Mage/src/mage/abilities/keyword/RippleAbility.java @@ -1,7 +1,8 @@ -package mage.abilities.effects.keyword; +package mage.abilities.keyword; import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.Cards; @@ -11,6 +12,7 @@ import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.predicate.mageobject.NamePredicate; import mage.game.Game; +import mage.game.events.GameEvent; import mage.game.stack.Spell; import mage.players.Player; import mage.target.TargetCard; @@ -19,26 +21,62 @@ import mage.util.CardUtil; /** * @author klayhamn */ -public class RippleEffect extends OneShotEffect { +public class RippleAbility extends TriggeredAbilityImpl { - protected int rippleNumber; - protected boolean isTargetSelf; // is the source of the ripple also the target of the ripple? + protected final int rippleNumber; - public RippleEffect(int rippleNumber) { - this(rippleNumber, true); // by default, the source is also the target + public RippleAbility(int rippleNumber) { + super(Zone.STACK, new RippleEffect(rippleNumber), false); + this.rippleNumber = rippleNumber; } - public RippleEffect(int rippleNumber, boolean isTargetSelf) { + public RippleAbility(RippleAbility ability) { + super(ability); + this.rippleNumber = ability.rippleNumber; + + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null && spell.getSourceId().equals(this.getSourceId())) { + return true; + } + return false; + + } + + @Override + public RippleAbility copy() { + return new RippleAbility(this); + } + + + @Override + public String getRule() { + return "Ripple ((When you cast this spell, you may reveal the top " + CardUtil.numberToText(rippleNumber) + " cards of your library. You may cast any revealed cards with the same name as this spell without paying their mana costs. Put the rest on the bottom of your library.))"; + } + + +} + +class RippleEffect extends OneShotEffect { + + protected int rippleNumber; + + public RippleEffect(int rippleNumber) { super(Outcome.PlayForFree); this.rippleNumber = rippleNumber; - this.isTargetSelf = isTargetSelf; - this.setText(); } public RippleEffect(final RippleEffect effect) { super(effect); this.rippleNumber = effect.rippleNumber; - this.isTargetSelf = effect.isTargetSelf; } @Override @@ -55,32 +93,19 @@ public class RippleEffect extends OneShotEffect { if (!player.chooseUse(Outcome.Neutral, "Reveal " + rippleNumber + " cards from the top of your library?", source, game)){ return true; //fizzle } + // reveal to/**/p cards from library Cards cards = new CardsImpl(); - cards.addAll(player.getLibrary().getTopCards(game, rippleNumber)); // pull top cards - player.revealCards(sourceObject.getIdName(), cards, game); // reveal the cards - - // Find out which card should be rippled - // FIXME: I'm not sure the "isTargetSelf" flag is the most elegant solution - String cardNameToRipple; - if (isTargetSelf) { // if the ripple applies to the same card that triggered it - cardNameToRipple = sourceObject.getName(); - } else { // if the ripple is caused by something else (e.g. Thrumming Stone) - Spell spellOnStack = game.getStack().getSpell(targetPointer.getFirst(game, source)); - if (spellOnStack == null) { // if the ripple target got countered or exiled - spellOnStack = (Spell) game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.STACK); - } - if (spellOnStack == null) { - return true; // should not happen? - } - cardNameToRipple = spellOnStack.getName(); - } + cards.addAll(player.getLibrary().getTopCards(game, rippleNumber)); + player.revealCards(sourceObject.getIdName(), cards, game); + // determine which card should be rippled + String cardNameToRipple = sourceObject.getName(); FilterCard sameNameFilter = new FilterCard("card(s) with the name: \"" + cardNameToRipple + "\" to cast without paying their mana cost"); sameNameFilter.add(new NamePredicate(cardNameToRipple)); TargetCard target1 = new TargetCard(Zone.LIBRARY, sameNameFilter); target1.setRequired(false); - // Choose cards to play for free + // choose cards to play for free while (player.isInGame() && cards.count(sameNameFilter, game) > 0 && player.choose(Outcome.PlayForFree, cards, target1, game)) { Card card = cards.get(target1.getFirstTarget(), game); if (card != null) { @@ -97,11 +122,5 @@ public class RippleEffect extends OneShotEffect { return false; } - private void setText() { - StringBuilder sb = new StringBuilder("Ripple ").append(rippleNumber); - sb.append(". (You may reveal the top "); - sb.append(CardUtil.numberToText(rippleNumber)); - sb.append(" cards of your library. You may cast any revealed cards with the same name as this spell without paying their mana costs. Put the rest on the bottom of your library.)"); - staticText = sb.toString(); - } } + From 827dab6d956fa7bba67344d014d1e18c07fb9e94 Mon Sep 17 00:00:00 2001 From: klayhamn Date: Tue, 28 Jul 2015 09:47:02 +0300 Subject: [PATCH 2/5] change Surging Dementia to use the rippleAbility instead of the rippleEffect --- Mage.Sets/src/mage/sets/coldsnap/SurgingDementia.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/sets/coldsnap/SurgingDementia.java b/Mage.Sets/src/mage/sets/coldsnap/SurgingDementia.java index 72a52c42be..a7798996a3 100644 --- a/Mage.Sets/src/mage/sets/coldsnap/SurgingDementia.java +++ b/Mage.Sets/src/mage/sets/coldsnap/SurgingDementia.java @@ -29,11 +29,8 @@ package mage.sets.coldsnap; import java.util.UUID; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.discard.DiscardCardYouChooseTargetEffect; -import mage.abilities.effects.common.discard.DiscardControllerEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; -import mage.abilities.effects.keyword.RippleEffect; +import mage.abilities.keyword.RippleAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; @@ -50,7 +47,8 @@ public class SurgingDementia extends CardImpl { this.expansionSetCode = "CSP"; // Ripple 4 - this.getSpellAbility().addEffect(new RippleEffect(4)); + this.addAbility(new RippleAbility(4)); + // Target player discards a card. this.getSpellAbility().getEffects().add(new DiscardTargetEffect(1)); this.getSpellAbility().getTargets().add(new TargetPlayer()); From 4044817641c2ec15b0e9acc3afcb1817a65e721b Mon Sep 17 00:00:00 2001 From: klayhamn Date: Tue, 28 Jul 2015 09:50:24 +0300 Subject: [PATCH 3/5] * add ThrummingStone test * Add rule text for Thrumming Stone * change ThrummingStones effect to be a static continuous effect that gives a triggered ability to spells, rather than being a triggered ability triggered by the stone itself --- .../mage/sets/coldsnap/ThrummingStone.java | 64 +++++++++++++++++-- .../abilities/other/ThrummingStoneTest.java | 61 ++++++++++++++++++ 2 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/ThrummingStoneTest.java diff --git a/Mage.Sets/src/mage/sets/coldsnap/ThrummingStone.java b/Mage.Sets/src/mage/sets/coldsnap/ThrummingStone.java index 2678180435..c7f1a281d0 100644 --- a/Mage.Sets/src/mage/sets/coldsnap/ThrummingStone.java +++ b/Mage.Sets/src/mage/sets/coldsnap/ThrummingStone.java @@ -28,11 +28,19 @@ package mage.sets.coldsnap; import java.util.UUID; -import mage.abilities.common.SpellCastControllerTriggeredAbility; -import mage.abilities.effects.keyword.RippleEffect; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.keyword.RippleAbility; import mage.cards.CardImpl; import mage.constants.*; import mage.filter.FilterSpell; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.game.stack.StackObject; +import mage.players.Player; /** * @@ -41,14 +49,15 @@ import mage.filter.FilterSpell; public class ThrummingStone extends CardImpl { //applies to all spells - private static final FilterSpell anySpellFilter = new FilterSpell(); + private static final FilterSpell anySpellFilter = new FilterSpell("Spells you cast"); public ThrummingStone(UUID ownerId) { super(ownerId, 142, "Thrumming Stone", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{5}"); this.expansionSetCode = "CSP"; this.supertype.add("Legendary"); - addAbility(new SpellCastControllerTriggeredAbility(new RippleEffect(4, false), anySpellFilter, false, true)); + // spells you cast have Ripple 4 + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ThrummingStoneGainAbilitySpellsEffect(new RippleAbility(4), anySpellFilter))); } public ThrummingStone(final ThrummingStone card) { @@ -62,3 +71,50 @@ public class ThrummingStone extends CardImpl { } +class ThrummingStoneGainAbilitySpellsEffect extends ContinuousEffectImpl { + + private final Ability ability; + private final FilterSpell filter; + + + public ThrummingStoneGainAbilitySpellsEffect(Ability ability, FilterSpell filter) { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + this.ability = ability; + this.filter = filter; + staticText = filter.getMessage() + " have " + ability.getRule(); + } + + public ThrummingStoneGainAbilitySpellsEffect(final ThrummingStoneGainAbilitySpellsEffect effect) { + super(effect); + this.ability = effect.ability; + this.filter = effect.filter; + } + + @Override + public ThrummingStoneGainAbilitySpellsEffect copy() { + return new ThrummingStoneGainAbilitySpellsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (player != null && permanent != null) { + for (StackObject stackObject : game.getStack()) { + // only spells cast, so no copies of spells + if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.getControllerId().equals(source.getControllerId())) { + Spell spell = (Spell) stackObject; + if (filter.match(spell, game)) { + if (!spell.getAbilities().contains(ability)) { + game.getState().addOtherAbility(spell.getCard(), ability); + } + } + } + } + return true; + } + return false; + } +} + + diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/ThrummingStoneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/ThrummingStoneTest.java new file mode 100644 index 0000000000..0776f50e70 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/ThrummingStoneTest.java @@ -0,0 +1,61 @@ +package org.mage.test.cards.abilities.other; + +import jdk.nashorn.internal.ir.annotations.Ignore; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author klayhamn + */ +public class ThrummingStoneTest extends CardTestPlayerBase { + + @Test + public void testApplyForNoneRippleCardsWhenSingleRipple() throws Exception { + + removeAllCardsFromLibrary(playerA); + + addCard(Zone.BATTLEFIELD, playerA, "Thrumming Stone"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp"); + addCard(Zone.HAND, playerA, "Shadowborn Apostle"); + + addCard(Zone.LIBRARY, playerA, "Shadowborn Apostle", 1); + addCard(Zone.LIBRARY, playerA, "Swamp", 3); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shadowborn Apostle"); + setChoice(playerA, "Yes"); + + setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Shadowborn Apostle", 2); + + } + + @Test + @Ignore // FIXME: This still fails + public void testApplyForNoneRippleCardsWhenMultiRipple() throws Exception { + + removeAllCardsFromLibrary(playerA); + + addCard(Zone.BATTLEFIELD, playerA, "Thrumming Stone"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp"); + addCard(Zone.HAND, playerA, "Shadowborn Apostle"); + + addCard(Zone.LIBRARY, playerA, "Shadowborn Apostle"); + addCard(Zone.LIBRARY, playerA, "Swamp", 3); + addCard(Zone.LIBRARY, playerA, "Shadowborn Apostle"); + + skipInitShuffling(); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shadowborn Apostle"); + setChoice(playerA, "Yes"); + + setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Shadowborn Apostle", 3); + + } +} From cac6a03e7ff78a37a3537d1e19113605950d46bf Mon Sep 17 00:00:00 2001 From: klayhamn Date: Tue, 28 Jul 2015 17:38:50 +0300 Subject: [PATCH 4/5] * fix potential bug where the copy constructor of the continuous effect of ThrummingStone did not copy its object parameters * unignore the thrumming stone test --- .../mage/sets/coldsnap/ThrummingStone.java | 113 +++++++++--------- .../abilities/other/ThrummingStoneTest.java | 62 +++++----- 2 files changed, 89 insertions(+), 86 deletions(-) diff --git a/Mage.Sets/src/mage/sets/coldsnap/ThrummingStone.java b/Mage.Sets/src/mage/sets/coldsnap/ThrummingStone.java index c7f1a281d0..a7a7b45af7 100644 --- a/Mage.Sets/src/mage/sets/coldsnap/ThrummingStone.java +++ b/Mage.Sets/src/mage/sets/coldsnap/ThrummingStone.java @@ -27,14 +27,18 @@ */ package mage.sets.coldsnap; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.keyword.RippleAbility; import mage.cards.CardImpl; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.Zone; import mage.filter.FilterSpell; import mage.game.Game; import mage.game.permanent.Permanent; @@ -42,79 +46,80 @@ import mage.game.stack.Spell; import mage.game.stack.StackObject; import mage.players.Player; +import java.util.UUID; + /** - * * @author klayhamn */ public class ThrummingStone extends CardImpl { - //applies to all spells - private static final FilterSpell anySpellFilter = new FilterSpell("Spells you cast"); + //applies to all spells + private static final FilterSpell anySpellFilter = new FilterSpell("Spells you cast"); - public ThrummingStone(UUID ownerId) { - super(ownerId, 142, "Thrumming Stone", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{5}"); - this.expansionSetCode = "CSP"; - this.supertype.add("Legendary"); + public ThrummingStone(UUID ownerId) { + super(ownerId, 142, "Thrumming Stone", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{5}"); + this.expansionSetCode = "CSP"; + this.supertype.add("Legendary"); - // spells you cast have Ripple 4 - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ThrummingStoneGainAbilitySpellsEffect(new RippleAbility(4), anySpellFilter))); - } + // spells you cast have Ripple 4 + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ThrummingStoneGainAbilitySpellsEffect(new RippleAbility(4), anySpellFilter))); + } - public ThrummingStone(final ThrummingStone card) { - super(card); - } + public ThrummingStone(final ThrummingStone card) { + super(card); + } - @Override - public ThrummingStone copy() { - return new ThrummingStone(this); - } + @Override + public ThrummingStone copy() { + return new ThrummingStone(this); + } } class ThrummingStoneGainAbilitySpellsEffect extends ContinuousEffectImpl { - private final Ability ability; - private final FilterSpell filter; + private final Ability ability; + private final FilterSpell filter; - public ThrummingStoneGainAbilitySpellsEffect(Ability ability, FilterSpell filter) { - super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); - this.ability = ability; - this.filter = filter; - staticText = filter.getMessage() + " have " + ability.getRule(); - } + public ThrummingStoneGainAbilitySpellsEffect(Ability ability, FilterSpell filter) { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + this.ability = ability; + this.filter = filter; + staticText = filter.getMessage() + " have " + ability.getRule(); + } - public ThrummingStoneGainAbilitySpellsEffect(final ThrummingStoneGainAbilitySpellsEffect effect) { - super(effect); - this.ability = effect.ability; - this.filter = effect.filter; - } + public ThrummingStoneGainAbilitySpellsEffect(final ThrummingStoneGainAbilitySpellsEffect effect) { + super(effect); + this.ability = effect.ability.copy(); + this.filter = effect.filter.copy(); + } - @Override - public ThrummingStoneGainAbilitySpellsEffect copy() { - return new ThrummingStoneGainAbilitySpellsEffect(this); - } + @Override + public ThrummingStoneGainAbilitySpellsEffect copy() { + return new ThrummingStoneGainAbilitySpellsEffect(this); + } - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - for (StackObject stackObject : game.getStack()) { - // only spells cast, so no copies of spells - if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.getControllerId().equals(source.getControllerId())) { - Spell spell = (Spell) stackObject; - if (filter.match(spell, game)) { - if (!spell.getAbilities().contains(ability)) { - game.getState().addOtherAbility(spell.getCard(), ability); - } - } - } + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (player != null && permanent != null) { + for (StackObject stackObject : game.getStack()) { + // only spells cast, so no copies of spells + if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.getControllerId().equals(source.getControllerId())) { + Spell spell = (Spell) stackObject; + if (filter.match(spell, game)) { + if (!spell.getAbilities().contains(ability)) { + game.getState().addOtherAbility(spell.getCard(), ability); } - return true; + } } - return false; + } + return true; } + return false; + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/ThrummingStoneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/ThrummingStoneTest.java index 0776f50e70..1b84ec26f6 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/ThrummingStoneTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/ThrummingStoneTest.java @@ -1,6 +1,5 @@ package org.mage.test.cards.abilities.other; -import jdk.nashorn.internal.ir.annotations.Ignore; import mage.constants.PhaseStep; import mage.constants.Zone; import org.junit.Test; @@ -11,51 +10,50 @@ import org.mage.test.serverside.base.CardTestPlayerBase; */ public class ThrummingStoneTest extends CardTestPlayerBase { - @Test - public void testApplyForNoneRippleCardsWhenSingleRipple() throws Exception { + @Test + public void testApplyForNoneRippleCardsWhenSingleRipple() throws Exception { - removeAllCardsFromLibrary(playerA); + removeAllCardsFromLibrary(playerA); - addCard(Zone.BATTLEFIELD, playerA, "Thrumming Stone"); - addCard(Zone.BATTLEFIELD, playerA, "Swamp"); - addCard(Zone.HAND, playerA, "Shadowborn Apostle"); + addCard(Zone.BATTLEFIELD, playerA, "Thrumming Stone"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp"); + addCard(Zone.HAND, playerA, "Shadowborn Apostle"); - addCard(Zone.LIBRARY, playerA, "Shadowborn Apostle", 1); - addCard(Zone.LIBRARY, playerA, "Swamp", 3); + addCard(Zone.LIBRARY, playerA, "Shadowborn Apostle", 1); + addCard(Zone.LIBRARY, playerA, "Swamp", 3); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shadowborn Apostle"); - setChoice(playerA, "Yes"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shadowborn Apostle"); + setChoice(playerA, "Yes"); - setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); - execute(); + setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); + execute(); - assertPermanentCount(playerA, "Shadowborn Apostle", 2); + assertPermanentCount(playerA, "Shadowborn Apostle", 2); - } + } - @Test - @Ignore // FIXME: This still fails - public void testApplyForNoneRippleCardsWhenMultiRipple() throws Exception { + @Test + public void testApplyForNoneRippleCardsWhenMultiRipple() throws Exception { - removeAllCardsFromLibrary(playerA); + removeAllCardsFromLibrary(playerA); - addCard(Zone.BATTLEFIELD, playerA, "Thrumming Stone"); - addCard(Zone.BATTLEFIELD, playerA, "Swamp"); - addCard(Zone.HAND, playerA, "Shadowborn Apostle"); + addCard(Zone.BATTLEFIELD, playerA, "Thrumming Stone"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp"); + addCard(Zone.HAND, playerA, "Shadowborn Apostle"); - addCard(Zone.LIBRARY, playerA, "Shadowborn Apostle"); - addCard(Zone.LIBRARY, playerA, "Swamp", 3); - addCard(Zone.LIBRARY, playerA, "Shadowborn Apostle"); + addCard(Zone.LIBRARY, playerA, "Shadowborn Apostle"); + addCard(Zone.LIBRARY, playerA, "Swamp", 3); + addCard(Zone.LIBRARY, playerA, "Shadowborn Apostle"); - skipInitShuffling(); + skipInitShuffling(); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shadowborn Apostle"); - setChoice(playerA, "Yes"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shadowborn Apostle"); + setChoice(playerA, "Yes"); - setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); - execute(); + setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); + execute(); - assertPermanentCount(playerA, "Shadowborn Apostle", 3); + assertPermanentCount(playerA, "Shadowborn Apostle", 3); - } + } } From f677a779aeb40fb834b20cfd51f9cc157cfc53d9 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 28 Jul 2015 22:24:08 +0200 Subject: [PATCH 5/5] * Stranglehold - Fixed the not working abilities. --- .../src/mage/sets/commander/Stranglehold.java | 10 +-- .../mage/test/cards/rules/CantSearchTest.java | 66 +++++++++++++++++++ 2 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/rules/CantSearchTest.java diff --git a/Mage.Sets/src/mage/sets/commander/Stranglehold.java b/Mage.Sets/src/mage/sets/commander/Stranglehold.java index e129b6c310..ae748538b5 100644 --- a/Mage.Sets/src/mage/sets/commander/Stranglehold.java +++ b/Mage.Sets/src/mage/sets/commander/Stranglehold.java @@ -30,6 +30,7 @@ package mage.sets.commander; import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.ReplacementEffectImpl; import mage.cards.CardImpl; @@ -37,6 +38,7 @@ 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; @@ -53,10 +55,10 @@ public class Stranglehold extends CardImpl { this.expansionSetCode = "CMD"; // Your opponents can't search libraries. - this.getSpellAbility().addEffect(new OpponentsCantSearchLibarariesEffect()); - + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new OpponentsCantSearchLibarariesEffect())); + // If an opponent would begin an extra turn, that player skips that turn instead. - this.getSpellAbility().addEffect(new StrangleholdSkipExtraTurnsEffect()); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new StrangleholdSkipExtraTurnsEffect())); } public Stranglehold(final Stranglehold card) { @@ -103,7 +105,7 @@ class OpponentsCantSearchLibarariesEffect extends ContinuousRuleModifyingEffectI public boolean checksEventType(GameEvent event, Game game) { return EventType.SEARCH_LIBRARY.equals(event.getType()); } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { Player controller = game.getPlayer(source.getControllerId()); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/rules/CantSearchTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/rules/CantSearchTest.java new file mode 100644 index 0000000000..f823f47331 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/rules/CantSearchTest.java @@ -0,0 +1,66 @@ +/* + * 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 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * 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 org.mage.test.cards.rules; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class CantSearchTest extends CardTestPlayerBase { + + /** + * Stranglehold doesn´t stop your opponents from searching libraries, at the + * moment it doesn´t work at all. Opponents were able to search their and my + * library in multiple gammes. + */ + @Test + public void testStranglehold() { + // Your opponents can't search libraries. + // If an opponent would begin an extra turn, that player skips that turn instead. + addCard(Zone.BATTLEFIELD, playerB, "Stranglehold"); + + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + // Search your library for a basic land card and put that card onto the battlefield tapped. Then shuffle your library. + addCard(Zone.HAND, playerA, "Rampant Growth", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rampant Growth"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Rampant Growth", 1); + assertPermanentCount(playerA, 2); // only the two forests + + } + +}