diff --git a/Mage.Sets/src/mage/cards/a/AltarOfTheGoyf.java b/Mage.Sets/src/mage/cards/a/AltarOfTheGoyf.java index a02b4b0a826..6e44a81f7ac 100644 --- a/Mage.Sets/src/mage/cards/a/AltarOfTheGoyf.java +++ b/Mage.Sets/src/mage/cards/a/AltarOfTheGoyf.java @@ -3,9 +3,9 @@ package mage.cards.a; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.hint.common.CardTypesInGraveyardHint; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -14,6 +14,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.events.GameEvent; import mage.target.targetpointer.FixedTarget; @@ -23,15 +24,10 @@ import java.util.UUID; /** * @author jmharmon */ - public final class AltarOfTheGoyf extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("Lhurgoyf creatures"); - - static { - filter.add(CardType.CREATURE.getPredicate()); - filter.add(SubType.LHURGOYF.getPredicate()); - } + private static final FilterPermanent filter + = new FilterCreaturePermanent(SubType.LHURGOYF, "Lhurgoyf creatures"); public AltarOfTheGoyf(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.TRIBAL, CardType.ARTIFACT}, "{5}"); @@ -39,10 +35,12 @@ public final class AltarOfTheGoyf extends CardImpl { this.subtype.add(SubType.LHURGOYF); // Whenever a creature you control attacks alone, it gets +X/+X until end of turn, where X is the number of card types among cards in all graveyard. - this.addAbility(new AltarOfTheGoyfAbility().addHint(CardTypesInGraveyardCount.ALL)); + this.addAbility(new AltarOfTheGoyfAbility()); // Lhurgoyf creatures you control have trample. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.WhileOnBattlefield, filter))); + this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), Duration.WhileOnBattlefield, filter + ))); } private AltarOfTheGoyf(final AltarOfTheGoyf card) { @@ -55,11 +53,13 @@ public final class AltarOfTheGoyf extends CardImpl { } } -class AltarOfTheGoyfAbility extends TriggeredAbilityImpl{ +class AltarOfTheGoyfAbility extends TriggeredAbilityImpl { public AltarOfTheGoyfAbility() { super(Zone.BATTLEFIELD, new BoostTargetEffect( - CardTypesInGraveyardCount.instance, CardTypesInGraveyardCount.instance, Duration.EndOfTurn, true), false); + CardTypesInGraveyardCount.ALL, CardTypesInGraveyardCount.ALL, Duration.EndOfTurn, true + ), false); + this.addHint(CardTypesInGraveyardHint.ALL); } public AltarOfTheGoyfAbility(final AltarOfTheGoyfAbility ability) { @@ -78,13 +78,9 @@ class AltarOfTheGoyfAbility extends TriggeredAbilityImpl{ @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.isActivePlayer(this.controllerId)) { - if (game.getCombat().attacksAlone()) { - this.getEffects().setTargetPointer(new - FixedTarget(game.getCombat().getAttackers().get(0), game)); { - } - return true; - } + if (game.isActivePlayer(this.controllerId) && game.getCombat().attacksAlone()) { + this.getEffects().setTargetPointer(new FixedTarget(game.getCombat().getAttackers().get(0), game)); + return true; } return false; } @@ -93,6 +89,6 @@ class AltarOfTheGoyfAbility extends TriggeredAbilityImpl{ public String getRule() { return "Whenever a creature you control attacks alone, " + "it gets +X/+X until end of turn, " + - "where X is the number of card types among cards in all graveyard."; + "where X is the number of card types among cards in all graveyards."; } } diff --git a/Mage.Sets/src/mage/cards/l/LucidDreams.java b/Mage.Sets/src/mage/cards/l/LucidDreams.java index ba3e23a2b50..b4385afb815 100644 --- a/Mage.Sets/src/mage/cards/l/LucidDreams.java +++ b/Mage.Sets/src/mage/cards/l/LucidDreams.java @@ -1,20 +1,13 @@ package mage.cards.l; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.hint.common.CardTypesInGraveyardHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.game.Game; -import mage.players.Player; -import java.util.Collection; import java.util.UUID; -import java.util.stream.Collectors; /** * @author TheElk801 @@ -25,7 +18,7 @@ public final class LucidDreams extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}{U}"); // Draw X cards, where X is the number of card types among cards in your graveyard. - this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(LucidDreamsValue.instance) + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(CardTypesInGraveyardCount.YOU) .setText("draw X cards, where X is the number of card types among cards in your graveyard")); this.getSpellAbility().addHint(CardTypesInGraveyardHint.YOU); } @@ -39,29 +32,3 @@ public final class LucidDreams extends CardImpl { return new LucidDreams(this); } } - -enum LucidDreamsValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - Player player = game.getPlayer(sourceAbility.getControllerId()); - return player == null ? 0 : player.getGraveyard() - .getCards(game) - .stream() - .map(MageObject::getCardType) - .flatMap(Collection::stream) - .collect(Collectors.toSet()) - .size(); - } - - @Override - public LucidDreamsValue copy() { - return instance; - } - - @Override - public String getMessage() { - return ""; - } -} diff --git a/Mage.Sets/src/mage/cards/n/NighthawkScavenger.java b/Mage.Sets/src/mage/cards/n/NighthawkScavenger.java index f9ba6a04566..75eaa65edef 100644 --- a/Mage.Sets/src/mage/cards/n/NighthawkScavenger.java +++ b/Mage.Sets/src/mage/cards/n/NighthawkScavenger.java @@ -1,11 +1,11 @@ package mage.cards.n; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.AdditiveDynamicValue; import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; +import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.continuous.SetPowerSourceEffect; import mage.abilities.hint.common.CardTypesInGraveyardHint; import mage.abilities.keyword.DeathtouchAbility; @@ -17,19 +17,18 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; -import mage.game.Game; -import mage.players.Player; -import java.util.Collection; -import java.util.Objects; import java.util.UUID; -import java.util.stream.Collectors; /** * @author TheElk801 */ public final class NighthawkScavenger extends CardImpl { + private static final DynamicValue xValue = new AdditiveDynamicValue( + CardTypesInGraveyardCount.OPPONENTS, StaticValue.get(1) + ); + public NighthawkScavenger(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}"); @@ -49,10 +48,9 @@ public final class NighthawkScavenger extends CardImpl { // Nighthawk Scavenger's power is equal to 1 plus the number of card types among cards in your opponents' graveyards. this.addAbility(new SimpleStaticAbility( - Zone.ALL, - new SetPowerSourceEffect( - NighthawkScavengerValue.instance, Duration.EndOfGame - ).setText("{this}'s power is equal to 1 plus the number of card types among cards in your opponents' graveyards.") + Zone.ALL, new SetPowerSourceEffect(xValue, Duration.EndOfGame) + .setText("{this}'s power is equal to 1 plus the number of " + + "card types among cards in your opponents' graveyards.") ).addHint(CardTypesInGraveyardHint.OPPONENTS)); } @@ -65,33 +63,3 @@ public final class NighthawkScavenger extends CardImpl { return new NighthawkScavenger(this); } } - -enum NighthawkScavengerValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return 1 + game.getOpponents(sourceAbility.getControllerId()) - .stream() - .map(game::getPlayer) - .filter(Objects::nonNull) - .map(Player::getGraveyard) - .map(g -> g.getCards(game)) - .flatMap(Collection::stream) - .filter(Objects::nonNull) - .map(MageObject::getCardType) - .flatMap(Collection::stream) - .collect(Collectors.toSet()) - .size(); - } - - @Override - public NighthawkScavengerValue copy() { - return instance; - } - - @Override - public String getMessage() { - return ""; - } -} diff --git a/Mage.Sets/src/mage/cards/t/Tarmogoyf.java b/Mage.Sets/src/mage/cards/t/Tarmogoyf.java index fb8fbfac836..546ec948bc5 100644 --- a/Mage.Sets/src/mage/cards/t/Tarmogoyf.java +++ b/Mage.Sets/src/mage/cards/t/Tarmogoyf.java @@ -4,17 +4,14 @@ import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.hint.common.CardTypesInGraveyardHint; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.game.Game; -import mage.players.Player; -import java.util.EnumSet; -import java.util.Set; import java.util.UUID; /** @@ -61,27 +58,13 @@ class TarmogoyfEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - MageObject target = game.getObject(source.getSourceId()); - if (target != null) { - Set foundCardTypes = EnumSet.noneOf(CardType.class); - for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { - Player player = game.getPlayer(playerId); - if (player != null) { - for (Card card : player.getGraveyard().getCards(game)) { - foundCardTypes.addAll(card.getCardType()); - } - } - } - int number = foundCardTypes.size(); - - target.getPower().setValue(number); - target.getToughness().setValue(number + 1); - return true; - } + MageObject target = source.getSourceObject(game); + if (target == null) { + return false; } - return false; + int number = CardTypesInGraveyardCount.ALL.calculate(game, source, this); + target.getPower().setValue(number); + target.getToughness().setValue(number + 1); + return true; } - } diff --git a/Mage/src/main/java/mage/abilities/condition/common/DeliriumCondition.java b/Mage/src/main/java/mage/abilities/condition/common/DeliriumCondition.java index 370a2a30201..4e45afbc2b5 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/DeliriumCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/DeliriumCondition.java @@ -14,7 +14,7 @@ public enum DeliriumCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - return CardTypesInGraveyardCount.instance.calculate(game, source, null) >= 4; + return CardTypesInGraveyardCount.YOU.calculate(game, source, null) >= 4; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardTypesInGraveyardCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardTypesInGraveyardCount.java index aba073e3f76..b30958623ad 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardTypesInGraveyardCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardTypesInGraveyardCount.java @@ -1,42 +1,46 @@ package mage.abilities.dynamicvalue.common; -import java.util.HashSet; -import java.util.Set; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.cards.Card; -import mage.constants.CardType; import mage.game.Game; import mage.game.permanent.PermanentToken; import mage.players.Player; +import java.util.Collection; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Stream; + /** * @author JayDi85 */ public enum CardTypesInGraveyardCount implements DynamicValue { + YOU("your graveyard"), + ALL("all graveyards"), + OPPONENTS("your opponents' graveyards"); + private final String message; - instance; + CardTypesInGraveyardCount(String message) { + this.message = message; + } @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - Player controller = game.getPlayer(sourceAbility.getControllerId()); - if (controller != null) { - Set foundCardTypes = new HashSet<>(); - for (Card card : controller.getGraveyard().getCards(game)) { - // 4/8/2016 In some rare cases, you can have a token or a copy of a spell in your graveyard at the moment that an object’s delirium ability counts the card types among cards in your graveyard, before that token or copy ceases to exist. Because tokens and copies of spells are not cards, even if they are copies of cards, their types will never be counted. - if (!card.isCopy() && !(card instanceof PermanentToken)) { - foundCardTypes.addAll(card.getCardType()); - } - } - return foundCardTypes.size(); - } - return 0; + return getStream(game, sourceAbility) + .filter(card -> !card.isCopy() && !(card instanceof PermanentToken)) + .map(MageObject::getCardType) + .flatMap(Collection::stream) + .distinct() + .mapToInt(x -> 1) + .sum(); } @Override public CardTypesInGraveyardCount copy() { - return instance; + return this; } @Override @@ -46,6 +50,33 @@ public enum CardTypesInGraveyardCount implements DynamicValue { @Override public String getMessage() { - return "the number of opponents you attacked this turn"; + return "the number of card types in " + message; + } + + private final Stream getStream(Game game, Ability ability) { + Collection playerIds; + switch (this) { + case YOU: + Player player = game.getPlayer(ability.getControllerId()); + return player == null + ? null : player + .getGraveyard() + .getCards(game) + .stream(); + case OPPONENTS: + playerIds = game.getOpponents(ability.getControllerId()); + break; + case ALL: + playerIds = game.getState().getPlayersInRange(ability.getControllerId(), game); + break; + default: + return null; + } + return playerIds.stream() + .map(game::getPlayer) + .filter(Objects::nonNull) + .map(Player::getGraveyard) + .map(graveyard -> graveyard.getCards(game)) + .flatMap(Collection::stream); } }