diff --git a/Mage.Sets/src/mage/cards/a/AuramancersGuise.java b/Mage.Sets/src/mage/cards/a/AuramancersGuise.java index a63e6660004..c2f037a973d 100644 --- a/Mage.Sets/src/mage/cards/a/AuramancersGuise.java +++ b/Mage.Sets/src/mage/cards/a/AuramancersGuise.java @@ -1,4 +1,3 @@ - package mage.cards.a; import mage.abilities.Ability; @@ -18,11 +17,11 @@ import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -import java.util.List; +import java.util.Objects; +import java.util.Optional; import java.util.UUID; /** - * * @author spjspj */ public final class AuramancersGuise extends CardImpl { @@ -36,16 +35,16 @@ public final class AuramancersGuise extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Enchanted creature gets +2/+2 for each Aura attached to it and has vigilance. - DynamicValue ptBoost = new EnchantedCreatureAurasCount(); - BoostEnchantedEffect effect = new BoostEnchantedEffect(ptBoost, ptBoost, Duration.WhileOnBattlefield); - effect.setText("Enchanted creature gets +2/+2 for each Aura attached to it"); - SimpleStaticAbility ability2 = new SimpleStaticAbility(effect); - ability2.addEffect(new GainAbilityAttachedEffect(VigilanceAbility.getInstance(), AttachmentType.AURA).setText("and has vigilance")); - this.addAbility(ability2); + Ability ability = new SimpleStaticAbility(new BoostEnchantedEffect( + AuramancersGuiseValue.instance, AuramancersGuiseValue.instance, Duration.WhileOnBattlefield + )); + ability.addEffect(new GainAbilityAttachedEffect( + VigilanceAbility.getInstance(), AttachmentType.AURA + ).setText("and has vigilance")); + this.addAbility(ability); } private AuramancersGuise(final AuramancersGuise card) { @@ -58,48 +57,40 @@ public final class AuramancersGuise extends CardImpl { } } -class EnchantedCreatureAurasCount implements DynamicValue { - - public EnchantedCreatureAurasCount() { - } - - private EnchantedCreatureAurasCount(final EnchantedCreatureAurasCount dynamicValue) { - } +enum AuramancersGuiseValue implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - int count = 0; - Permanent aura = game.getPermanent(sourceAbility.getSourceId()); - if (aura != null) { - Permanent permanent = game.getPermanent(aura.getAttachedTo()); - if (permanent != null) { - List attachments = permanent.getAttachments(); - for (UUID attachmentId : attachments) { - Permanent attached = game.getPermanent(attachmentId); - if (attached != null && attached.hasSubtype(SubType.AURA, game)) { - count++; - } - - } - return 2 * count; - } - } - return count; + Permanent permanent = Optional + .ofNullable(sourceAbility.getSourcePermanentIfItStillExists(game)) + .map(Permanent::getAttachedTo) + .map(game::getPermanent) + .orElse(null); + return permanent != null + ? 2 * permanent + .getAttachments() + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .filter(p -> p.hasSubtype(SubType.AURA, game)) + .mapToInt(x -> 1) + .sum() + : 0; } @Override - public EnchantedCreatureAurasCount copy() { - return new EnchantedCreatureAurasCount(this); - } - - @Override - public String toString() { - return "1"; + public AuramancersGuiseValue copy() { + return this; } @Override public String getMessage() { - return "of its auras"; + return "for each Aura attached to it"; } + @Override + public String toString() { + return "2"; + } } diff --git a/Mage.Sets/src/mage/cards/b/BountyOfSkemfar.java b/Mage.Sets/src/mage/cards/b/BountyOfSkemfar.java index 03729cb3666..f364d7ddfaa 100644 --- a/Mage.Sets/src/mage/cards/b/BountyOfSkemfar.java +++ b/Mage.Sets/src/mage/cards/b/BountyOfSkemfar.java @@ -48,8 +48,8 @@ class BountyOfSkemfarEffect extends OneShotEffect { BountyOfSkemfarEffect() { super(Outcome.Benefit); - staticText = "reveal the top six cards of your library. You may put a land card from among them " + - "onto the battlefield tapped and an Elf card from among them into your hand. " + + staticText = "reveal the top six cards of your library. You may put up to one land card from among them " + + "onto the battlefield tapped and up to one Elf card from among them into your hand. " + "Put the rest on the bottom of your library in a random order"; } diff --git a/Mage.Sets/src/mage/cards/f/FaithfulPikemaster.java b/Mage.Sets/src/mage/cards/f/FaithfulPikemaster.java index a990fe5b854..7ec554a3515 100644 --- a/Mage.Sets/src/mage/cards/f/FaithfulPikemaster.java +++ b/Mage.Sets/src/mage/cards/f/FaithfulPikemaster.java @@ -37,7 +37,7 @@ public final class FaithfulPikemaster extends CardImpl { // As long as it's your turn, Faithful Pikemaster has first strike. this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield), - MyTurnCondition.instance, "during your turn, {this} has first strike." + MyTurnCondition.instance, "as long as it's your turn, {this} has first strike." )).addHint(MyTurnHint.instance)); } diff --git a/Mage.Sets/src/mage/cards/g/Godsend.java b/Mage.Sets/src/mage/cards/g/Godsend.java index 7f07da8d55c..ccf9d841a03 100644 --- a/Mage.Sets/src/mage/cards/g/Godsend.java +++ b/Mage.Sets/src/mage/cards/g/Godsend.java @@ -167,7 +167,7 @@ class GodsendRuleModifyingEffect extends ContinuousRuleModifyingEffectImpl { GodsendRuleModifyingEffect() { super(Duration.WhileOnBattlefield, Outcome.Detriment); - staticText = "Your opponents can't cast cards with the same name as cards exiled with {this}"; + staticText = "Your opponents can't cast spells with the same name as a card exiled with {this}"; } private GodsendRuleModifyingEffect(final GodsendRuleModifyingEffect effect) { diff --git a/Mage.Sets/src/mage/cards/l/Lightwalker.java b/Mage.Sets/src/mage/cards/l/Lightwalker.java index 3ddc8f25aef..c6877f09737 100644 --- a/Mage.Sets/src/mage/cards/l/Lightwalker.java +++ b/Mage.Sets/src/mage/cards/l/Lightwalker.java @@ -1,9 +1,8 @@ - package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; @@ -12,26 +11,29 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.counters.CounterType; +import java.util.UUID; + /** - * * @author fireshoes */ public final class Lightwalker extends CardImpl { + private static final Condition condition = new SourceHasCounterCondition(CounterType.P1P1); + public Lightwalker(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WARRIOR); this.power = new MageInt(2); this.toughness = new MageInt(1); - // Lightwalker has flying as long as it has a +1/+1 counter on it. - this.addAbility(new SimpleStaticAbility( - new ConditionalContinuousEffect(new GainAbilitySourceEffect(FlyingAbility.getInstance()), - new SourceHasCounterCondition(CounterType.P1P1),"Lightwalker has flying as long as it has a +1/+1 counter on it"))); + // Lightwalker has flying as long as it has a +1/+1 counter on it. + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + new GainAbilitySourceEffect(FlyingAbility.getInstance()), condition, + "{this} has flying as long as it has a +1/+1 counter on it" + ))); } private Lightwalker(final Lightwalker card) { diff --git a/Mage.Sets/src/mage/cards/n/NabanDeanOfIteration.java b/Mage.Sets/src/mage/cards/n/NabanDeanOfIteration.java index 4f2707720d2..8061511e12c 100644 --- a/Mage.Sets/src/mage/cards/n/NabanDeanOfIteration.java +++ b/Mage.Sets/src/mage/cards/n/NabanDeanOfIteration.java @@ -52,7 +52,7 @@ class NabanDeanOfIterationEffect extends ReplacementEffectImpl { NabanDeanOfIterationEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "If a Wizard entering under your control causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time"; + staticText = "if a Wizard you control entering causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time"; } private NabanDeanOfIterationEffect(final NabanDeanOfIterationEffect effect) { diff --git a/Mage.Sets/src/mage/cards/p/PadeemConsulOfInnovation.java b/Mage.Sets/src/mage/cards/p/PadeemConsulOfInnovation.java index e9e39dc8b95..d7b4ed5f466 100644 --- a/Mage.Sets/src/mage/cards/p/PadeemConsulOfInnovation.java +++ b/Mage.Sets/src/mage/cards/p/PadeemConsulOfInnovation.java @@ -1,18 +1,28 @@ package mage.cards.p; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.MageObject; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; -import mage.abilities.condition.common.ControlsPermanentGreatestCMCCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; import mage.abilities.keyword.HexproofAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.predicate.Predicate; +import mage.game.Game; +import mage.game.permanent.Permanent; import java.util.UUID; @@ -21,8 +31,16 @@ import java.util.UUID; */ public final class PadeemConsulOfInnovation extends CardImpl { - private static final Condition condition - = new ControlsPermanentGreatestCMCCondition(StaticFilters.FILTER_PERMANENT_ARTIFACT); + private static final FilterPermanent filter = new FilterControlledArtifactPermanent( + "you control the artifact with the greatest mana value or tied for the greatest mana value" + ); + + static { + filter.add(PadeemConsulOfInnovationPredicate.instance); + } + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + private static final Hint hint = new ConditionHint(condition); public PadeemConsulOfInnovation(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); @@ -39,12 +57,7 @@ public final class PadeemConsulOfInnovation extends CardImpl { ))); // At the beginning of your upkeep, if you control the artifact with the highest converted mana cost or tied for the highest converted mana cost, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - new DrawCardSourceControllerEffect(1), false - ), condition, "At the beginning of your upkeep, if you control the artifact " + - "with the highest mana value or tied for the highest mana value, draw a card." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(1)).withInterveningIf(condition).addHint(hint)); } private PadeemConsulOfInnovation(final PadeemConsulOfInnovation card) { @@ -56,3 +69,18 @@ public final class PadeemConsulOfInnovation extends CardImpl { return new PadeemConsulOfInnovation(this); } } + +enum PadeemConsulOfInnovationPredicate implements Predicate { + instance; + + @Override + public boolean apply(Permanent input, Game game) { + return input.getManaValue() >= game + .getBattlefield() + .getActivePermanents(StaticFilters.FILTER_PERMANENT_ARTIFACT, input.getControllerId(), game) + .stream() + .mapToInt(MageObject::getManaValue) + .max() + .orElse(-1); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PriestOfForgottenGods.java b/Mage.Sets/src/mage/cards/p/PriestOfForgottenGods.java index a91a681c5ab..bb7fc2f8436 100644 --- a/Mage.Sets/src/mage/cards/p/PriestOfForgottenGods.java +++ b/Mage.Sets/src/mage/cards/p/PriestOfForgottenGods.java @@ -51,7 +51,7 @@ public final class PriestOfForgottenGods extends CardImpl { ); ability.addEffect( new SacrificeEffect(StaticFilters.FILTER_PERMANENT_CREATURE, 1, "") - .setText("and sacrifice a creature") + .setText("and sacrifice a creature of their choice") ); ability.addCost(new SacrificeTargetCost(2, filter)); ability.addEffect(new BasicManaEffect(Mana.BlackMana(2)).setText("You add {B}{B}")); diff --git a/Mage.Sets/src/mage/cards/r/RevTitheExtractor.java b/Mage.Sets/src/mage/cards/r/RevTitheExtractor.java index 0de610319c9..d0e5830262f 100644 --- a/Mage.Sets/src/mage/cards/r/RevTitheExtractor.java +++ b/Mage.Sets/src/mage/cards/r/RevTitheExtractor.java @@ -42,7 +42,7 @@ public final class RevTitheExtractor extends CardImpl { ); ability.addEffect(new ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect(true, CastManaAdjustment.NONE) .setText(", then look at the top card of that player's library and exile it face down. " - + "You may play that card for as long as it remains exiled")); + + "You may cast that card for as long as it remains exiled")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/ScreamingSwarm.java b/Mage.Sets/src/mage/cards/s/ScreamingSwarm.java index 4a3fed21002..249cb4fbc23 100644 --- a/Mage.Sets/src/mage/cards/s/ScreamingSwarm.java +++ b/Mage.Sets/src/mage/cards/s/ScreamingSwarm.java @@ -86,7 +86,7 @@ class ScreamingSwarmEffect extends OneShotEffect { ScreamingSwarmEffect() { super(Outcome.Benefit); - staticText = "put {this} from your graveyard into your library second from the top"; + staticText = "put this card from your graveyard into your library second from the top"; } private ScreamingSwarmEffect(final ScreamingSwarmEffect effect) { diff --git a/Mage.Sets/src/mage/cards/s/ShieldMare.java b/Mage.Sets/src/mage/cards/s/ShieldMare.java index 1a88cd50c2b..47f62ceef21 100644 --- a/Mage.Sets/src/mage/cards/s/ShieldMare.java +++ b/Mage.Sets/src/mage/cards/s/ShieldMare.java @@ -45,7 +45,7 @@ public final class ShieldMare extends CardImpl { // When Shield Mare enters the battlefield or becomes the target of a spell or ability and opponent controls, you gain 3 life. this.addAbility(new OrTriggeredAbility(Zone.ALL, new GainLifeEffect(3), false, - "Whenever {this} enters or becomes the target of a spell or ability an opponent controls, ", + "When {this} enters or becomes the target of a spell or ability an opponent controls, ", new EntersBattlefieldTriggeredAbility(null), new BecomesTargetSourceTriggeredAbility(null, StaticFilters.FILTER_SPELL_OR_ABILITY_OPPONENTS))); } diff --git a/Mage.Sets/src/mage/cards/t/ToughCookie.java b/Mage.Sets/src/mage/cards/t/ToughCookie.java index e7ef120c870..3acbd41f706 100644 --- a/Mage.Sets/src/mage/cards/t/ToughCookie.java +++ b/Mage.Sets/src/mage/cards/t/ToughCookie.java @@ -48,10 +48,10 @@ public final class ToughCookie extends CardImpl { // {2}{G}: Target noncreature artifact you control becomes a 4/4 artifact creature until end of turn. Ability ability = new SimpleActivatedAbility(new AddCardTypeTargetEffect( Duration.EndOfTurn, CardType.ARTIFACT, CardType.CREATURE - ).setText("target noncreature artifact you control becomes"), new ManaCostsImpl<>("{2}{G}")); + ).setText("until end of turn, target noncreature artifact you control becomes"), new ManaCostsImpl<>("{2}{G}")); ability.addEffect(new SetBasePowerToughnessTargetEffect( 4, 4, Duration.EndOfTurn - ).setText(" a 4/4 artifact creature until end of turn")); + ).setText(" a 4/4 artifact creature")); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/w/WoodlandChampion.java b/Mage.Sets/src/mage/cards/w/WoodlandChampion.java index 7ccea61836b..50f57ff6a06 100644 --- a/Mage.Sets/src/mage/cards/w/WoodlandChampion.java +++ b/Mage.Sets/src/mage/cards/w/WoodlandChampion.java @@ -89,7 +89,7 @@ class WoodlandChampionTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever one or more tokens enter the battlefield under your control, " + + return "Whenever one or more tokens you control enter, " + "put that many +1/+1 counters on {this}."; } } diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index 9fb178911de..2e837b19464 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -75,7 +75,7 @@ public class VerifyCardDataTest { private static final Logger logger = Logger.getLogger(VerifyCardDataTest.class); - private static final String FULL_ABILITIES_CHECK_SET_CODES = "ODY,TOR,JUD,ONS,LGN,SCG"; // check ability text due mtgjson, can use multiple sets like MAT;CMD or * for all + private static final String FULL_ABILITIES_CHECK_SET_CODES = "J25"; // check ability text due mtgjson, can use multiple sets like MAT;CMD or * for all private static final boolean CHECK_ONLY_ABILITIES_TEXT = false; // use when checking text locally, suppresses unnecessary checks and output messages private static final boolean CHECK_COPYABLE_FIELDS = true; // disable for better verify test performance diff --git a/Mage/src/main/java/mage/abilities/condition/common/ControlsPermanentGreatestCMCCondition.java b/Mage/src/main/java/mage/abilities/condition/common/ControlsPermanentGreatestCMCCondition.java deleted file mode 100644 index 92a533b372e..00000000000 --- a/Mage/src/main/java/mage/abilities/condition/common/ControlsPermanentGreatestCMCCondition.java +++ /dev/null @@ -1,54 +0,0 @@ -package mage.abilities.condition.common; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.condition.Condition; -import mage.filter.FilterPermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; - -/** - * - * @author LevelX2 - */ -public class ControlsPermanentGreatestCMCCondition implements Condition { - - private final FilterPermanent filter; - - public ControlsPermanentGreatestCMCCondition() { - this(new FilterPermanent()); - } - - public ControlsPermanentGreatestCMCCondition(FilterPermanent filter) { - super(); - this.filter = filter; - } - - @Override - public boolean apply(Game game, Ability source) { - Set controllers = new HashSet<>(); - Integer maxCMC = null; - - List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game); - for (Permanent permanent : permanents) { - int cmc = permanent.getManaCost().manaValue(); - if (maxCMC == null || cmc > maxCMC) { - maxCMC = cmc; - controllers.clear(); - } - if (cmc == maxCMC) { - controllers.add(permanent.getControllerId()); - } - } - return controllers.contains(source.getControllerId()); - } - - @Override - public String toString() { - return "you control the " + filter.getMessage() + " with the highest mana value or tied for the highest mana value"; - } - -} diff --git a/Mage/src/main/java/mage/game/permanent/token/FishToken.java b/Mage/src/main/java/mage/game/permanent/token/FishToken.java index 89c2170c151..38b409c0851 100644 --- a/Mage/src/main/java/mage/game/permanent/token/FishToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/FishToken.java @@ -11,14 +11,14 @@ import mage.constants.SubType; public final class FishToken extends TokenImpl { public FishToken() { - super("Fish Token", "1/1 blue Fish creature token with \"This creature can't be blocked.\""); + super("Fish Token", "1/1 blue Fish creature token with \"This token can't be blocked.\""); cardType.add(CardType.CREATURE); subtype.add(SubType.FISH); color.setBlue(true); power = new MageInt(1); toughness = new MageInt(1); - addAbility(new CantBeBlockedSourceAbility("this creature can't be blocked")); + addAbility(new CantBeBlockedSourceAbility("this token can't be blocked")); } private FishToken(final FishToken token) { diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index f1073e32c4c..e22531ea3d9 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -980,7 +980,7 @@ public final class CardUtil { } if (!targetPlayerGets) { sb.append(add ? " on " : " from "); - if (description.contains("up to")) { + if (description.contains("up to") && !description.contains("up to one")) { sb.append("each of "); } sb.append(description);