diff --git a/Mage.Sets/src/mage/cards/b/BrothersYamazaki.java b/Mage.Sets/src/mage/cards/b/BrothersYamazaki.java index ee936a0012..c62b5f5e6b 100644 --- a/Mage.Sets/src/mage/cards/b/BrothersYamazaki.java +++ b/Mage.Sets/src/mage/cards/b/BrothersYamazaki.java @@ -1,12 +1,9 @@ - package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.Effect; +import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.keyword.BushidoAbility; @@ -16,14 +13,15 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.NamePredicate; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.NamePredicate; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import java.util.List; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class BrothersYamazaki extends CardImpl { @@ -36,7 +34,7 @@ public final class BrothersYamazaki extends CardImpl { } public BrothersYamazaki(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN, SubType.SAMURAI); this.power = new MageInt(2); @@ -46,15 +44,15 @@ public final class BrothersYamazaki extends CardImpl { this.addAbility(new BushidoAbility(1)); // If there are exactly two permanents named Brothers Yamazaki on the battlefield, the "legend rule" doesn't apply to them. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BrothersYamazakiIgnoreLegendRuleEffectEffect())); + this.addAbility(new SimpleStaticAbility(new BrothersYamazakiIgnoreLegendRuleEffectEffect())); // Each other creature named Brothers Yamazaki gets +2/+2 and has haste. - Effect effect = new BoostAllEffect(2, 2, Duration.WhileOnBattlefield, filter, true); - effect.setText("Each other creature named Brothers Yamazaki gets +2/+2"); - Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); - effect = new GainAbilityAllEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield, filter); - effect.setText("and has haste"); - ability.addEffect(effect); + Ability ability = new SimpleStaticAbility(new BoostAllEffect( + 2, 2, Duration.WhileOnBattlefield, filter, true + ).setText("Each other creature named Brothers Yamazaki gets +2/+2")); + ability.addEffect(new GainAbilityAllEffect( + HasteAbility.getInstance(), Duration.WhileOnBattlefield, filter + ).setText("and has haste")); this.addAbility(ability); } @@ -68,7 +66,7 @@ public final class BrothersYamazaki extends CardImpl { } } -class BrothersYamazakiIgnoreLegendRuleEffectEffect extends ContinuousRuleModifyingEffectImpl { +class BrothersYamazakiIgnoreLegendRuleEffectEffect extends ContinuousEffectImpl { private static final FilterPermanent filter = new FilterPermanent(); @@ -77,7 +75,7 @@ class BrothersYamazakiIgnoreLegendRuleEffectEffect extends ContinuousRuleModifyi } public BrothersYamazakiIgnoreLegendRuleEffectEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment, false, false); + super(Duration.WhileOnBattlefield, Layer.RulesEffects, SubLayer.NA, Outcome.Detriment); staticText = "If there are exactly two permanents named Brothers Yamazaki on the battlefield, the \"legend rule\" doesn't apply to them"; } @@ -91,17 +89,16 @@ class BrothersYamazakiIgnoreLegendRuleEffectEffect extends ContinuousRuleModifyi } @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DESTROY_PERMANENT_BY_LEGENDARY_RULE; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getName().equals("Brothers Yamazaki")) { - return game.getBattlefield().count(filter, source.getControllerId(), source, game) == 2; + public boolean apply(Game game, Ability source) { + List permanents = game.getBattlefield().getActivePermanents( + filter, source.getControllerId(), source, game + ); + if (permanents.size() != 2) { + return false; } - return false; + for (Permanent permanent : permanents) { + permanent.setLegendRuleApplies(false); + } + return true; } - } diff --git a/Mage.Sets/src/mage/cards/c/CadricSoulKindler.java b/Mage.Sets/src/mage/cards/c/CadricSoulKindler.java index 4437637fad..3bdbbac784 100644 --- a/Mage.Sets/src/mage/cards/c/CadricSoulKindler.java +++ b/Mage.Sets/src/mage/cards/c/CadricSoulKindler.java @@ -5,11 +5,11 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenCopyTargetEffect; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.ruleModifying.LegendRuleDoesntApplyEffect; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -19,9 +19,7 @@ import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentToken; import mage.target.targetpointer.FixedTargets; import java.util.UUID; @@ -33,11 +31,14 @@ public final class CadricSoulKindler extends CardImpl { private static final FilterPermanent filter = new FilterControlledPermanent("another nontoken legendary permanent"); + private static final FilterPermanent filter2 + = new FilterControlledPermanent("tokens you control"); static { filter.add(TokenPredicate.FALSE); filter.add(AnotherPredicate.instance); filter.add(SuperType.LEGENDARY.getPredicate()); + filter2.add(TokenPredicate.TRUE); } public CadricSoulKindler(UUID ownerId, CardSetInfo setInfo) { @@ -50,7 +51,7 @@ public final class CadricSoulKindler extends CardImpl { this.toughness = new MageInt(3); // The "legend rule" doesn't apply to tokens you control. - this.addAbility(new SimpleStaticAbility(new CadricSoulKindlerLegendEffect())); + this.addAbility(new SimpleStaticAbility(new LegendRuleDoesntApplyEffect(filter2))); // Whenever another nontoken legendary permanent enters the battlefield under your control, you may pay {1}. If you do, create a token that's a copy of it. That token gains haste. Sacrifice it at the beginning of the next end step. this.addAbility(new EntersBattlefieldControlledTriggeredAbility( @@ -68,34 +69,6 @@ public final class CadricSoulKindler extends CardImpl { } } -class CadricSoulKindlerLegendEffect extends ContinuousRuleModifyingEffectImpl { - - public CadricSoulKindlerLegendEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment, false, false); - staticText = "the \"legend rule\" doesn't apply to tokens you control"; - } - - public CadricSoulKindlerLegendEffect(final CadricSoulKindlerLegendEffect effect) { - super(effect); - } - - @Override - public CadricSoulKindlerLegendEffect copy() { - return new CadricSoulKindlerLegendEffect(this); - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DESTROY_PERMANENT_BY_LEGENDARY_RULE; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - Permanent permanent = game.getPermanent(event.getTargetId()); - return permanent instanceof PermanentToken && permanent.isControlledBy(source.getControllerId()); - } -} - class CadricSoulKindlerTokenEffect extends OneShotEffect { CadricSoulKindlerTokenEffect() { diff --git a/Mage.Sets/src/mage/cards/m/MirrorBox.java b/Mage.Sets/src/mage/cards/m/MirrorBox.java index cd36707e73..f57231a62a 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorBox.java +++ b/Mage.Sets/src/mage/cards/m/MirrorBox.java @@ -3,18 +3,14 @@ package mage.cards.m; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.ruleModifying.LegendRuleDoesntApplyEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.FilterPermanent; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.util.CardUtil; @@ -36,7 +32,9 @@ public final class MirrorBox extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // The "legend rule" doesn't apply to permanents you control. - this.addAbility(new SimpleStaticAbility(new MirrorBoxLegendEffect())); + this.addAbility(new SimpleStaticAbility(new LegendRuleDoesntApplyEffect( + StaticFilters.FILTER_CONTROLLED_PERMANENTS + ))); // Each legendary creature you control gets +1/+1. this.addAbility(new SimpleStaticAbility(new BoostControlledEffect( @@ -57,34 +55,6 @@ public final class MirrorBox extends CardImpl { } } -class MirrorBoxLegendEffect extends ContinuousRuleModifyingEffectImpl { - - MirrorBoxLegendEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment, false, false); - staticText = "the \"legend rule\" doesn't apply to permanents you control"; - } - - private MirrorBoxLegendEffect(final MirrorBoxLegendEffect effect) { - super(effect); - } - - @Override - public MirrorBoxLegendEffect copy() { - return new MirrorBoxLegendEffect(this); - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DESTROY_PERMANENT_BY_LEGENDARY_RULE; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - Permanent permanent = game.getPermanent(event.getTargetId()); - return permanent != null && permanent.isControlledBy(source.getControllerId()); - } -} - class MirrorBoxBoostEffect extends ContinuousEffectImpl { public MirrorBoxBoostEffect() { diff --git a/Mage.Sets/src/mage/cards/m/MirrorGallery.java b/Mage.Sets/src/mage/cards/m/MirrorGallery.java index 944dbb588a..7f7994029a 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorGallery.java +++ b/Mage.Sets/src/mage/cards/m/MirrorGallery.java @@ -1,31 +1,23 @@ - package mage.cards.m; -import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.ruleModifying.LegendRuleDoesntApplyEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; -import mage.game.Game; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class MirrorGallery extends CardImpl { public MirrorGallery(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); // The "legend rule" doesn't apply. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MirrorGalleryRuleEffect())); + this.addAbility(new SimpleStaticAbility(new LegendRuleDoesntApplyEffect())); } private MirrorGallery(final MirrorGallery card) { @@ -37,36 +29,3 @@ public final class MirrorGallery extends CardImpl { return new MirrorGallery(this); } } - -class MirrorGalleryRuleEffect extends ContinuousEffectImpl { - - public MirrorGalleryRuleEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); - staticText = "The \"legend rule\" doesn't apply"; - } - - public MirrorGalleryRuleEffect(final MirrorGalleryRuleEffect effect) { - super(effect); - } - - @Override - public MirrorGalleryRuleEffect copy() { - return new MirrorGalleryRuleEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - game.getState().setLegendaryRuleActive(false); - return true; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; - } -} diff --git a/Mage.Sets/src/mage/cards/s/SakashimaOfAThousandFaces.java b/Mage.Sets/src/mage/cards/s/SakashimaOfAThousandFaces.java index 5dec8b7ed4..ddaf3a615e 100644 --- a/Mage.Sets/src/mage/cards/s/SakashimaOfAThousandFaces.java +++ b/Mage.Sets/src/mage/cards/s/SakashimaOfAThousandFaces.java @@ -5,16 +5,16 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.common.CopyPermanentEffect; +import mage.abilities.effects.common.ruleModifying.LegendRuleDoesntApplyEffect; import mage.abilities.keyword.PartnerAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.util.functions.CopyApplier; import java.util.UUID; @@ -39,7 +39,7 @@ public final class SakashimaOfAThousandFaces extends CardImpl { ).setText("as a copy of another creature you control, except it has {this}'s other abilities"), true)); // The "legend rule" doesn't apply to permanents you control. - this.addAbility(new SimpleStaticAbility(new SakashimaOfAThousandFacesEffect())); + this.addAbility(new SimpleStaticAbility(new LegendRuleDoesntApplyEffect(StaticFilters.FILTER_CONTROLLED_PERMANENTS))); // Partner this.addAbility(PartnerAbility.getInstance()); @@ -59,36 +59,8 @@ class SakashimaOfAThousandFacesCopyApplier extends CopyApplier { @Override public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { - blueprint.getAbilities().add(new SimpleStaticAbility(new SakashimaOfAThousandFacesEffect())); + blueprint.getAbilities().add(new SimpleStaticAbility(new LegendRuleDoesntApplyEffect(StaticFilters.FILTER_CONTROLLED_PERMANENTS))); blueprint.getAbilities().add(PartnerAbility.getInstance()); return true; } } - -class SakashimaOfAThousandFacesEffect extends ContinuousRuleModifyingEffectImpl { - - SakashimaOfAThousandFacesEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment, false, false); - staticText = "the \"legend rule\" doesn't apply to permanents you control"; - } - - private SakashimaOfAThousandFacesEffect(final SakashimaOfAThousandFacesEffect effect) { - super(effect); - } - - @Override - public SakashimaOfAThousandFacesEffect copy() { - return new SakashimaOfAThousandFacesEffect(this); - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DESTROY_PERMANENT_BY_LEGENDARY_RULE; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - Permanent permanent = game.getPermanent(event.getTargetId()); - return permanent != null && permanent.isControlledBy(source.getControllerId()); - } -} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java index 41eebc4326..a390ef48ff 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java @@ -144,7 +144,7 @@ public class CleverImpersonatorTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clever Impersonator"); setChoice(playerA, "Jace, Vryn's Prodigy"); - addTarget(playerA, "Jace, Vryn's Prodigy[only copy]"); // keep the copied Jace + setChoice(playerA, "Jace, Vryn's Prodigy[only copy]"); // keep the copied Jace activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Draw a card"); setChoice(playerA, "Pillarfield Ox"); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/SharuumTheHegemonTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/SharuumTheHegemonTest.java index af4ebcf8d0..1f44f95f17 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/SharuumTheHegemonTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/SharuumTheHegemonTest.java @@ -55,25 +55,25 @@ public class SharuumTheHegemonTest extends CardTestPlayerBase { setChoice(playerA, true); setChoice(playerA, "Sharuum the Hegemon"); // what creature to clone - addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep + setChoice(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep setChoice(playerA, "Whenever {this} or another creature dies"); // blood first addTarget(playerA, playerB); // damage by blood setChoice(playerA, true); // return // addTarget(playerA, "Sharuum the Hegemon"); // return real sharuum (Autochosen, only target) - addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep + setChoice(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep setChoice(playerA, "Whenever {this} or another creature dies"); // blood first addTarget(playerA, playerB); // damage by blood setChoice(playerA, true); // return // addTarget(playerA, "Sharuum the Hegemon"); // return real sharuum (Autochosen, only target - addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep + setChoice(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep setChoice(playerA, "Whenever {this} or another creature dies"); // blood first addTarget(playerA, playerB); // damage by blood setChoice(playerA, true); // return // addTarget(playerA, "Sharuum the Hegemon"); // return real sharuum (Autochosen, only target) - addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep + setChoice(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep setChoice(playerA, "Whenever {this} or another creature dies"); // blood first addTarget(playerA, playerB); // damage by blood setChoice(playerA, false); // Don't use it anymore diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/rules/LegendRuleTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/rules/LegendRuleTest.java new file mode 100644 index 0000000000..88776dc3fa --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/rules/LegendRuleTest.java @@ -0,0 +1,32 @@ +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 TheElk801 + */ +public class LegendRuleTest extends CardTestPlayerBase { + + private static final String isamaru = "Isamaru, Hound of Konda"; + + @Test + public void testRegular() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + addCard(Zone.HAND, playerA, isamaru, 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, isamaru); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, isamaru); + + setChoice(playerA, isamaru); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, isamaru, 1); + assertPermanentCount(playerA, isamaru, 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/CadricSoulKindlerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/CadricSoulKindlerTest.java new file mode 100644 index 0000000000..1c93a61452 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/CadricSoulKindlerTest.java @@ -0,0 +1,53 @@ +package org.mage.test.cards.single.dmc; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author TheElk801 + */ +public class CadricSoulKindlerTest extends CardTestPlayerBase { + + private static final String cadric = "Cadric, Soul Kindler"; + private static final String isamaru = "Isamaru, Hound of Konda"; + + @Test + public void testOneCopy() { + addCard(Zone.BATTLEFIELD, playerA, cadric); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + addCard(Zone.HAND, playerA, isamaru); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, isamaru); + setChoice(playerA, true); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + setStrictChooseMode(true); + execute(); + + assertPermanentCount(playerA, isamaru, 2); + assertGraveyardCount(playerA, isamaru, 0); + } + + @Test + public void testTwoCopies() { + addCard(Zone.BATTLEFIELD, playerA, cadric); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 4); + addCard(Zone.HAND, playerA, isamaru, 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, isamaru); + setChoice(playerA, true); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, isamaru); + setChoice(playerA, true); + setChoice(playerA, isamaru); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + setStrictChooseMode(true); + execute(); + + assertPermanentCount(playerA, isamaru, 3); + assertGraveyardCount(playerA, isamaru, 1); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/LegendRuleDoesntApplyEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/LegendRuleDoesntApplyEffect.java new file mode 100644 index 0000000000..3091128919 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/LegendRuleDoesntApplyEffect.java @@ -0,0 +1,51 @@ +package mage.abilities.effects.common.ruleModifying; + +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * @author TheElk801 + */ +public class LegendRuleDoesntApplyEffect extends ContinuousEffectImpl { + + private final FilterPermanent filter; + + public LegendRuleDoesntApplyEffect() { + this(StaticFilters.FILTER_PERMANENTS); + this.staticText = "the \"legend rule\" doesn't apply"; + } + + public LegendRuleDoesntApplyEffect(FilterPermanent filter) { + super(Duration.WhileOnBattlefield, Layer.RulesEffects, SubLayer.NA, Outcome.Detriment); + staticText = "the \"legend rule\" doesn't apply to " + filter.getMessage(); + this.filter = filter; + } + + private LegendRuleDoesntApplyEffect(final LegendRuleDoesntApplyEffect effect) { + super(effect); + this.filter = effect.filter; + } + + @Override + public LegendRuleDoesntApplyEffect copy() { + return new LegendRuleDoesntApplyEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Permanent permanent : game.getBattlefield().getActivePermanents( + filter, source.getControllerId(), source, game + )) { + permanent.setLegendRuleApplies(false); + } + return true; + } +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/LegendRuleAppliesPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/LegendRuleAppliesPredicate.java new file mode 100644 index 0000000000..3af90fa75e --- /dev/null +++ b/Mage/src/main/java/mage/filter/predicate/permanent/LegendRuleAppliesPredicate.java @@ -0,0 +1,17 @@ +package mage.filter.predicate.permanent; + +import mage.filter.predicate.Predicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * @author TheElk801 + */ +public enum LegendRuleAppliesPredicate implements Predicate { + instance; + + @Override + public boolean apply(Permanent input, Game game) { + return input.legendRuleApplies(); + } +} diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 1d1f901b81..4bbc70ed1b 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -36,6 +36,7 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.NamePredicate; import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.filter.predicate.permanent.LegendRuleAppliesPredicate; import mage.game.combat.Combat; import mage.game.command.*; import mage.game.command.dungeons.UndercityDungeon; @@ -2478,7 +2479,7 @@ public abstract class GameImpl implements Game { somethingHappened = true; } } - if (this.getState().isLegendaryRuleActive() && StaticFilters.FILTER_PERMANENT_LEGENDARY.match(perm, this)) { + if (perm.isLegendary() && perm.legendRuleApplies()) { legendary.add(perm); } if (StaticFilters.FILTER_PERMANENT_EQUIPMENT.match(perm, this)) { @@ -2571,22 +2572,24 @@ public abstract class GameImpl implements Game { filterLegendName.add(SuperType.LEGENDARY.getPredicate()); filterLegendName.add(new NamePredicate(legend.getName())); filterLegendName.add(new ControllerIdPredicate(legend.getControllerId())); - if (getBattlefield().contains(filterLegendName, legend.getControllerId(), null, this, 2)) { - if (!replaceEvent(GameEvent.getEvent(GameEvent.EventType.DESTROY_PERMANENT_BY_LEGENDARY_RULE, legend.getId(), legend.getControllerId()))) { - Player controller = this.getPlayer(legend.getControllerId()); - if (controller != null) { - Target targetLegendaryToKeep = new TargetPermanent(filterLegendName); - targetLegendaryToKeep.setTargetName(legend.getName() + " to keep (Legendary Rule)?"); - controller.chooseTarget(Outcome.Benefit, targetLegendaryToKeep, null, this); - for (Permanent dupLegend : getBattlefield().getActivePermanents(filterLegendName, legend.getControllerId(), this)) { - if (!targetLegendaryToKeep.getTargets().contains(dupLegend.getId())) { - movePermanentToGraveyardWithInfo(dupLegend); - } - } - } - return true; + filterLegendName.add(LegendRuleAppliesPredicate.instance); + if (!getBattlefield().contains(filterLegendName, legend.getControllerId(), null, this, 2)) { + continue; + } + Player controller = this.getPlayer(legend.getControllerId()); + if (controller == null) { + continue; + } + Target targetLegendaryToKeep = new TargetPermanent(filterLegendName); + targetLegendaryToKeep.setNotTarget(true); + targetLegendaryToKeep.setTargetName(legend.getName() + " to keep (Legendary Rule)?"); + controller.choose(Outcome.Benefit, targetLegendaryToKeep, null, this); + for (Permanent dupLegend : getBattlefield().getActivePermanents(filterLegendName, legend.getControllerId(), this)) { + if (!targetLegendaryToKeep.getTargets().contains(dupLegend.getId())) { + movePermanentToGraveyardWithInfo(dupLegend); } } + return true; } } //704.5k - World Enchantments diff --git a/Mage/src/main/java/mage/game/GameState.java b/Mage/src/main/java/mage/game/GameState.java index 19e01e8227..c6f0412d53 100644 --- a/Mage/src/main/java/mage/game/GameState.java +++ b/Mage/src/main/java/mage/game/GameState.java @@ -88,7 +88,6 @@ public class GameState implements Serializable, Copyable { private int stepNum = 0; private UUID turnId = null; private boolean extraTurn = false; - private boolean legendaryRuleActive = true; private boolean gameOver; private boolean paused; private ContinuousEffects effects; @@ -159,7 +158,6 @@ public class GameState implements Serializable, Copyable { this.turnNum = state.turnNum; this.stepNum = state.stepNum; this.extraTurn = state.extraTurn; - this.legendaryRuleActive = state.legendaryRuleActive; this.effects = state.effects.copy(); for (TriggeredAbility trigger : state.triggered) { this.triggered.add(trigger.copy()); @@ -227,7 +225,6 @@ public class GameState implements Serializable, Copyable { turnNum = 1; stepNum = 0; extraTurn = false; - legendaryRuleActive = true; gameOver = false; specialActions.clear(); cardState.clear(); @@ -264,7 +261,6 @@ public class GameState implements Serializable, Copyable { this.turnNum = state.turnNum; this.stepNum = state.stepNum; this.extraTurn = state.extraTurn; - this.legendaryRuleActive = state.legendaryRuleActive; this.effects = state.effects; this.triggered = state.triggered; this.triggers = state.triggers; @@ -1224,7 +1220,6 @@ public class GameState implements Serializable, Copyable { // All gained abilities have to be removed to prevent adding it multiple times triggers.removeAllGainedAbilities(); getContinuousEffects().removeAllTemporaryEffects(); - this.setLegendaryRuleActive(true); for (CardState state : cardState.values()) { state.clearAbilities(); } @@ -1244,14 +1239,6 @@ public class GameState implements Serializable, Copyable { return this.paused; } - public boolean isLegendaryRuleActive() { - return legendaryRuleActive; - } - - public void setLegendaryRuleActive(boolean legendaryRuleActive) { - this.legendaryRuleActive = legendaryRuleActive; - } - /** * Only used for diagnostic purposes of tests * @@ -1447,21 +1434,22 @@ public class GameState implements Serializable, Copyable { boolean isDaytime() { return isDaytime; } - + @Override public String toString() { return CardUtil.getTurnInfo(this); } - public boolean setReverseTurnOrder(boolean reverse){ - if(this.reverseTurnOrder&&reverse){ + public boolean setReverseTurnOrder(boolean reverse) { + if (this.reverseTurnOrder && reverse) { this.reverseTurnOrder = false; } else { this.reverseTurnOrder = reverse; } return this.reverseTurnOrder; } - public boolean getReverseTurnOrder(){ + + public boolean getReverseTurnOrder() { return this.reverseTurnOrder; } } diff --git a/Mage/src/main/java/mage/game/permanent/Permanent.java b/Mage/src/main/java/mage/game/permanent/Permanent.java index 89fcdc248c..7bbc6a9082 100644 --- a/Mage/src/main/java/mage/game/permanent/Permanent.java +++ b/Mage/src/main/java/mage/game/permanent/Permanent.java @@ -222,6 +222,10 @@ public interface Permanent extends Card, Controllable { boolean canLoyaltyBeUsed(Game game); + void setLegendRuleApplies(boolean legendRuleApplies); + + boolean legendRuleApplies(); + void resetControl(); boolean changeControllerId(UUID controllerId, Game game, Ability source); diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index 00861bf1c6..28229c7cf2 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -106,6 +106,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { protected int transformCount = 0; protected Map info; protected int createOrder; + protected boolean legendRuleApplies = true; private static final List emptyList = Collections.unmodifiableList(new ArrayList()); @@ -171,6 +172,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { this.bandedCards.addAll(permanent.bandedCards); this.timesLoyaltyUsed = permanent.timesLoyaltyUsed; this.loyaltyActivationsAvailable = permanent.loyaltyActivationsAvailable; + this.legendRuleApplies = permanent.legendRuleApplies; this.transformCount = permanent.transformCount; this.morphed = permanent.morphed; @@ -214,6 +216,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { this.copy = false; this.goadingPlayers.clear(); this.loyaltyActivationsAvailable = 1; + this.legendRuleApplies = true; } @Override @@ -491,6 +494,16 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { return false; } + @Override + public void setLegendRuleApplies(boolean legendRuleApplies) { + this.legendRuleApplies = legendRuleApplies; + } + + @Override + public boolean legendRuleApplies() { + return this.legendRuleApplies; + } + @Override public boolean isTapped() { return tapped;