diff --git a/Mage.Sets/src/mage/cards/b/BarterInBlood.java b/Mage.Sets/src/mage/cards/b/BarterInBlood.java index 097e78cf27..e908356168 100644 --- a/Mage.Sets/src/mage/cards/b/BarterInBlood.java +++ b/Mage.Sets/src/mage/cards/b/BarterInBlood.java @@ -4,7 +4,8 @@ import mage.abilities.effects.common.SacrificeAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; import java.util.UUID; @@ -13,14 +14,13 @@ import java.util.UUID; */ public final class BarterInBlood extends CardImpl { + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("creatures"); + public BarterInBlood(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}{B}"); - // Each player sacrifices two creatures. - this.getSpellAbility().addEffect(new SacrificeAllEffect( - 2, StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT - )); + this.getSpellAbility().addEffect(new SacrificeAllEffect(2, filter)); } public BarterInBlood(final BarterInBlood card) { diff --git a/Mage.Sets/src/mage/cards/e/EsikaGodOfTheTree.java b/Mage.Sets/src/mage/cards/e/EsikaGodOfTheTree.java index ce3a18c632..c0783491ad 100644 --- a/Mage.Sets/src/mage/cards/e/EsikaGodOfTheTree.java +++ b/Mage.Sets/src/mage/cards/e/EsikaGodOfTheTree.java @@ -1,6 +1,5 @@ package mage.cards.e; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.CompoundAbility; @@ -8,16 +7,17 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.VigilanceAbility; import mage.abilities.mana.AnyColorManaAbility; import mage.cards.*; import mage.constants.*; -import mage.abilities.keyword.VigilanceAbility; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class EsikaGodOfTheTree extends ModalDoubleFacesCard { @@ -50,7 +50,7 @@ public final class EsikaGodOfTheTree extends ModalDoubleFacesCard { this.getLeftHalfCard().addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( new CompoundAbility(VigilanceAbility.getInstance(), new AnyColorManaAbility()), Duration.WhileOnBattlefield, filter, true - ))); + ).setText("other legendary creatures you control have vigilance and \"{T}: Add one mana of any color.\""))); // 2. // The Prismatic Bridge diff --git a/Mage.Sets/src/mage/cards/f/FirjasRetribution.java b/Mage.Sets/src/mage/cards/f/FirjasRetribution.java index 4c82271963..56f0adbfbf 100644 --- a/Mage.Sets/src/mage/cards/f/FirjasRetribution.java +++ b/Mage.Sets/src/mage/cards/f/FirjasRetribution.java @@ -32,7 +32,7 @@ import mage.target.common.TargetCreaturePermanent; public final class FirjasRetribution extends CardImpl { private static final FilterCreaturePermanent filter - = new FilterCreaturePermanent("creature with less power than this creature's power"); + = new FilterCreaturePermanent("creature with power less than this creature's power"); private static final FilterControlledPermanent filter2 = new FilterControlledPermanent(SubType.ANGEL, "Angels you control"); @@ -56,7 +56,7 @@ public final class FirjasRetribution extends CardImpl { ability.addTarget(new TargetCreaturePermanent(filter)); sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_II, new GainAbilityAllEffect( ability, Duration.EndOfTurn, filter2 - )); + ).setText("until end of turn, Angels you control gain \"{T}: Destroy target creature with power less than this creature's power.\"")); // III — Angels you control gain double strike until end of turn. sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, new GainAbilityAllEffect( diff --git a/Mage.Sets/src/mage/cards/g/GlimpseTheCosmos.java b/Mage.Sets/src/mage/cards/g/GlimpseTheCosmos.java index 2435a15c2f..63b3a44559 100644 --- a/Mage.Sets/src/mage/cards/g/GlimpseTheCosmos.java +++ b/Mage.Sets/src/mage/cards/g/GlimpseTheCosmos.java @@ -9,7 +9,6 @@ import mage.abilities.costs.Costs; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.Effect; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; import mage.cards.Card; @@ -32,9 +31,12 @@ public class GlimpseTheCosmos extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}"); // Look at the top three cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order. - Effect glimpseTheCosmosEffect = new LookLibraryAndPickControllerEffect(StaticValue.get(3), false, StaticValue.get(1), - StaticFilters.FILTER_CARD, Zone.LIBRARY, false, false, false, Zone.HAND, false); - this.getSpellAbility().addEffect(glimpseTheCosmosEffect); + this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect( + StaticValue.get(3), false, StaticValue.get(1), + StaticFilters.FILTER_CARD, Zone.LIBRARY, false, + false, false, Zone.HAND, false + ).setText("look at the top three cards of your library. " + + "Put one of them into your hand and the rest on the bottom of your library in any order")); //As long as you control a Giant, you may cast Glimpse the Cosmos from your graveyard by paying {U} rather than paying its mana cost. If you cast Glimpse the Cosmos this way and it would be put into your graveyard, exile it instead. this.addAbility(new GlimpseTheCosmosAbility(new ManaCostsImpl("{U}"))); @@ -80,7 +82,7 @@ class GlimpseTheCosmosAbility extends SpellAbility { } //Must control a giant - Condition controlGiantCondition = new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(SubType.GIANT, "you control a Giant")); + Condition controlGiantCondition = new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(SubType.GIANT, "you control a Giant")); if (!controlGiantCondition.apply(game, this)) { return ActivationStatus.getFalse(); } diff --git a/Mage.Sets/src/mage/cards/t/TergridsShadow.java b/Mage.Sets/src/mage/cards/t/TergridsShadow.java index 01f6ee495d..cc6d9e88f0 100644 --- a/Mage.Sets/src/mage/cards/t/TergridsShadow.java +++ b/Mage.Sets/src/mage/cards/t/TergridsShadow.java @@ -5,7 +5,8 @@ import mage.abilities.keyword.ForetellAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; import java.util.UUID; @@ -14,13 +15,13 @@ import java.util.UUID; */ public final class TergridsShadow extends CardImpl { + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("creatures"); + public TergridsShadow(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}{B}"); // Each player sacrifices two creatures. - this.getSpellAbility().addEffect(new SacrificeAllEffect( - 2, StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT - )); + this.getSpellAbility().addEffect(new SacrificeAllEffect(2, filter)); // Foretell {2}{B}{B} this.addAbility(new ForetellAbility(this, "{2}{B}{B}")); diff --git a/Mage.Sets/src/mage/cards/t/TheThreeSeasons.java b/Mage.Sets/src/mage/cards/t/TheThreeSeasons.java index 25f92d698b..855c213076 100644 --- a/Mage.Sets/src/mage/cards/t/TheThreeSeasons.java +++ b/Mage.Sets/src/mage/cards/t/TheThreeSeasons.java @@ -1,24 +1,28 @@ package mage.cards.t; -import java.util.*; - import mage.abilities.Ability; import mage.abilities.common.SagaAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.MillCardsControllerEffect; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; -import mage.cards.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; import mage.constants.*; -import mage.filter.FilterCard; +import mage.filter.StaticFilters; import mage.filter.common.FilterPermanentCard; import mage.game.Game; -import mage.game.events.TargetEvent; import mage.players.Player; import mage.target.TargetCard; +import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCardInYourGraveyard; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class TheThreeSeasons extends CardImpl { @@ -63,12 +67,12 @@ public final class TheThreeSeasons extends CardImpl { class TheThreeSeasonsEffect extends OneShotEffect { - public TheThreeSeasonsEffect() { + TheThreeSeasonsEffect() { super(Outcome.Neutral); - staticText = "Choose up to three cards in each graveyard. Their owners shuffle those cards into their libraries"; + staticText = "Choose three cards in each graveyard. Their owners shuffle those cards into their libraries"; } - private TheThreeSeasonsEffect (final TheThreeSeasonsEffect effect) { + private TheThreeSeasonsEffect(final TheThreeSeasonsEffect effect) { super(effect); } @@ -80,83 +84,27 @@ class TheThreeSeasonsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Map playerCardsMap = new LinkedHashMap<>(); - for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { - Player player = game.getPlayer(playerId); - if (player != null) { - TheThreeSeasonsTarget target = new TheThreeSeasonsTarget(player); - controller.chooseTarget(outcome, target, source, game); - playerCardsMap.put(player, new CardsImpl(target.getTargets())); - } - } - for (Map.Entry entry : playerCardsMap.entrySet()) { - entry.getKey().shuffleCardsToLibrary(entry.getValue(), game, source); - } - return true; + if (controller == null) { + return false; } - return false; - } -} - -class TheThreeSeasonsTarget extends TargetCard { - - private final Player player; - - public TheThreeSeasonsTarget(Player player) { - super(0, 3, Zone.GRAVEYARD, new FilterCard( - "cards in " + player.getLogName() + "'s graveyard" - )); - this.setNotTarget(true); - this.player = player; - } - - private TheThreeSeasonsTarget(final TheThreeSeasonsTarget target) { - super(target); - this.player = target.player; - } - - @Override - public TheThreeSeasonsTarget copy() { - return new TheThreeSeasonsTarget(this); - } - - @Override - public boolean canTarget(UUID id, Game game) { - Card card = game.getCard(id); - return card != null && game.getState().getZone(card.getId()) == Zone.GRAVEYARD - && player.getGraveyard().contains(id) && filter.match(card, game); - } - - @Override - public boolean canTarget(UUID id, Ability source, Game game) { - return this.canTarget(id, game); - } - - @Override - public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) { - return this.canTarget(id, game); - } - - @Override - public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { - Set possibleTargets = new HashSet<>(); - for (Card card : player.getGraveyard().getCards(filter, game)) { - if (sourceId == null || isNotTarget() || !game.replaceEvent(new TargetEvent(card, sourceId, sourceControllerId))) { - possibleTargets.add(card.getId()); - } - } - return possibleTargets; - } - - @Override - public Set possibleTargets(UUID sourceControllerId, Cards cards, Game game) { - Set possibleTargets = new HashSet<>(); - for (Card card : cards.getCards(filter, game)) { - if (player.getGraveyard().getCards(game).contains(card)) { - possibleTargets.add(card.getId()); - } - } - return possibleTargets; + Map playerCardsMap = new LinkedHashMap<>(); + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player == null) { + continue; + } + int cardCount = Math.min(player.getGraveyard().size(), 3); + if (cardCount < 1) { + continue; + } + TargetCard target = new TargetCardInGraveyard(cardCount, StaticFilters.FILTER_CARD); + target.setNotTarget(true); + controller.chooseTarget(outcome, player.getGraveyard(), target, source, game); + playerCardsMap.put(player, new CardsImpl(target.getTargets())); + } + for (Map.Entry entry : playerCardsMap.entrySet()) { + entry.getKey().shuffleCardsToLibrary(entry.getValue(), game, source); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/t/TheTricksterGodsHeist.java b/Mage.Sets/src/mage/cards/t/TheTricksterGodsHeist.java index a0c8ccd13d..792b4b43a4 100644 --- a/Mage.Sets/src/mage/cards/t/TheTricksterGodsHeist.java +++ b/Mage.Sets/src/mage/cards/t/TheTricksterGodsHeist.java @@ -45,7 +45,7 @@ public final class TheTricksterGodsHeist extends CardImpl { // II — You may exchange control of two target nonbasic, noncreature permanents that share a card type. sagaAbility.addChapterEffect( - this, SagaChapter.CHAPTER_I, SagaChapter.CHAPTER_I, + this, SagaChapter.CHAPTER_II, SagaChapter.CHAPTER_II, new ExchangeControlTargetEffect( Duration.EndOfGame, "exchange control of two target nonbasic, " + "noncreature permanents that share a card type" diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index e0f7db91dd..8107047ccd 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -4,7 +4,6 @@ import com.google.common.base.CharMatcher; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.effects.keyword.ScryEffect; -import mage.abilities.keyword.ChangelingAbility; import mage.abilities.keyword.MenaceAbility; import mage.abilities.keyword.MultikickerAbility; import mage.cards.*; @@ -1497,7 +1496,7 @@ public class VerifyCardDataTest { } // mana ability fix for (String s : refText.split("[\\$\\\n]")) { - if (!s.startsWith("{T}: Add {") || !s.contains("} or {")) { + if (!(s.startsWith("{T}: Add {") || s.startsWith("({T}: Add {")) || !s.contains("} or {")) { continue; } String newStr = ""; diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java index 6ba358ddc0..992567d5af 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java @@ -121,6 +121,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge || ruleLow.startsWith("put") || ruleLow.startsWith("remove") || ruleLow.startsWith("counter") + || ruleLow.startsWith("exchange") || ruleLow.startsWith("goad")) { sb.append("you may "); } else if (!ruleLow.startsWith("its controller may")) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java index 1dfa390013..7db27d84c6 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java @@ -103,6 +103,9 @@ public class BoostTargetEffect extends ContinuousEffectImpl { } sb.append(CardUtil.numberToText(target.getMaxNumberOfTargets())).append(" target ").append(target.getTargetName()).append(" get "); } else { + if (target.getNumberOfTargets() < target.getMaxNumberOfTargets()) { + sb.append("up to ").append(CardUtil.numberToText(target.getMaxNumberOfTargets())).append(' '); + } if (!target.getTargetName().toLowerCase(Locale.ENGLISH).startsWith("another")) { sb.append("target "); }