diff --git a/Mage.Sets/src/mage/cards/d/DustOfMoments.java b/Mage.Sets/src/mage/cards/d/DustOfMoments.java index 3de21424f05..b88d0a1f29e 100644 --- a/Mage.Sets/src/mage/cards/d/DustOfMoments.java +++ b/Mage.Sets/src/mage/cards/d/DustOfMoments.java @@ -46,6 +46,10 @@ class DustOfMomentsEffect extends OneShotEffect { private static final FilterPermanentOrSuspendedCard filter = new FilterPermanentOrSuspendedCard(); private final boolean remove; + static { + filter.getPermanentFilter().add(CounterType.TIME.getPredicate()); + } + DustOfMomentsEffect(boolean remove) { super(Outcome.Benefit); this.remove = remove; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/NestOfScarabsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/NestOfScarabsTest.java index c0e5a4bd937..2774d27e3bc 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/NestOfScarabsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/NestOfScarabsTest.java @@ -180,7 +180,6 @@ public class NestOfScarabsTest extends CardTestPlayerBase { } /* - Reported bug: Nest of Scarabs not triggering off wither damage dealt by creatures such as Sickle Ripper */ @Test @@ -204,4 +203,48 @@ public class NestOfScarabsTest extends CardTestPlayerBase { assertCounterCount(playerB, wOmens, CounterType.M1M1, 2); assertPermanentCount(playerA, "Insect Token", 2); } + + /* + https://github.com/magefree/mage/issues/9649 + */ + @Test + public void scarabs_ETBWithCountersTriggers() { + + String hatchling = "Noxious Hatchling"; // ETB with four -1/-1 counters + + addCard(Zone.BATTLEFIELD, playerA, nestScarabs); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4); + addCard(Zone.HAND, playerA, hatchling); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hatchling); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, nestScarabs, 1); + assertPermanentCount(playerA, hatchling, 1); + assertPermanentCount(playerA, "Insect Token", 4); + } + + @Test + public void scarabs_OpponentETBWithCountersNoTriggers() { + + String hatchling = "Noxious Hatchling"; // ETB with four -1/-1 counters + + addCard(Zone.BATTLEFIELD, playerB, nestScarabs); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4); + addCard(Zone.HAND, playerA, hatchling); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hatchling); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerB, nestScarabs, 1); + assertPermanentCount(playerA, hatchling, 1); + assertPermanentCount(playerA, "Insect Token", 0); + assertPermanentCount(playerB, "Insect Token", 0); + } } diff --git a/Mage/src/main/java/mage/abilities/common/PutCounterOnCreatureTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/PutCounterOnCreatureTriggeredAbility.java index 3023d8d0633..a2c287529e8 100644 --- a/Mage/src/main/java/mage/abilities/common/PutCounterOnCreatureTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/PutCounterOnCreatureTriggeredAbility.java @@ -74,6 +74,9 @@ public class PutCounterOnCreatureTriggeredAbility extends TriggeredAbilityImpl { return false; } Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); + if (permanent == null) { + permanent = game.getPermanentEntering(event.getTargetId()); + } if (permanent == null || !filter.match(permanent, controllerId, this, game)) { return false; } diff --git a/Mage/src/main/java/mage/abilities/costs/common/RemoveCountersSourceCost.java b/Mage/src/main/java/mage/abilities/costs/common/RemoveCountersSourceCost.java index e449d1158c6..2a75d15939a 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/RemoveCountersSourceCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/RemoveCountersSourceCost.java @@ -11,7 +11,6 @@ import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.util.CardUtil; import mage.util.RandomUtil; import java.util.Iterator; @@ -27,19 +26,15 @@ public class RemoveCountersSourceCost extends CostImpl { private final String name; public RemoveCountersSourceCost() { - this((Counter) null); + this.amount = 1; + this.name = ""; + this.text = "remove a counter from {this}"; } public RemoveCountersSourceCost(Counter counter) { - this.amount = counter != null ? counter.getCount() : 1; - this.name = counter != null ? counter.getName() : ""; - this.text = new StringBuilder("remove ") - .append((amount == 1 ? CounterType.findArticle(name) : CardUtil.numberToText(amount))) - .append(name.isEmpty() ? "" : (' ' + name)) - .append(" counter") - .append((amount != 1 ? "s" : "")) - .append(" from {this}").toString(); - + this.amount = counter.getCount(); + this.name = counter.getName(); + this.text = "remove " + counter.getDescription() + " from {this}"; } private RemoveCountersSourceCost(RemoveCountersSourceCost cost) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAllEffect.java index aed21748b09..aaa44ff3f1d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAllEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common.counter; import mage.MageObject; @@ -6,14 +5,10 @@ import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.counters.Counter; -import mage.counters.CounterType; import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.util.CardUtil; - -import java.util.Locale; /** * @author North @@ -27,7 +22,7 @@ public class AddCountersAllEffect extends OneShotEffect { super(Outcome.Benefit); this.counter = counter; this.filter = filter; - setText(); + staticText = "put " + counter.getDescription() + " on each " + filter.getMessage(); } public AddCountersAllEffect(final AddCountersAllEffect effect) { @@ -45,7 +40,7 @@ public class AddCountersAllEffect extends OneShotEffect { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { permanent.addCounters(counter.copy(), source.getControllerId(), source, game); if (!game.isSimulation()) { - game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts " + counter.getCount() + ' ' + counter.getName().toLowerCase(Locale.ENGLISH) + game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts " + counter.getCount() + ' ' + counter.getName() + " counter on " + permanent.getLogName()); } } @@ -55,18 +50,6 @@ public class AddCountersAllEffect extends OneShotEffect { return false; } - private void setText() { - StringBuilder sb = new StringBuilder(); - sb.append("put "); - if (counter.getCount() > 1) { - sb.append(CardUtil.numberToText(counter.getCount(), "a")).append(' ').append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counters on each "); - } else { - sb.append(CounterType.findArticle(counter.getName())).append(' ').append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter on each "); - } - sb.append(filter.getMessage()); - staticText = sb.toString(); - } - @Override public AddCountersAllEffect copy() { return new AddCountersAllEffect(this); diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAttachedEffect.java index 0cea9db26ed..4f42f70b915 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAttachedEffect.java @@ -6,13 +6,10 @@ import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.counters.Counter; -import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.util.CardUtil; -import java.util.Locale; - /** * @author LevelX2 */ @@ -20,7 +17,6 @@ public class AddCountersAttachedEffect extends OneShotEffect { private Counter counter; private DynamicValue amount; - private String textEnchanted; public AddCountersAttachedEffect(Counter counter, String textEnchanted) { this(counter, StaticValue.get(1), textEnchanted); @@ -35,8 +31,7 @@ public class AddCountersAttachedEffect extends OneShotEffect { super(Outcome.Benefit); this.counter = counter.copy(); this.amount = amount; - this.textEnchanted = textEnchanted; - setText(); + staticText = CardUtil.getAddRemoveCountersText(amount, counter, textEnchanted, true); } public AddCountersAttachedEffect(final AddCountersAttachedEffect effect) { @@ -45,7 +40,6 @@ public class AddCountersAttachedEffect extends OneShotEffect { this.counter = effect.counter.copy(); } this.amount = effect.amount; - this.textEnchanted = effect.textEnchanted; } @Override @@ -67,38 +61,8 @@ public class AddCountersAttachedEffect extends OneShotEffect { return false; } - private void setText() { - if (!staticText.isEmpty()) { - return; - } - StringBuilder sb = new StringBuilder(); - // put a +1/+1 counter on it - sb.append("put "); - boolean plural = true; - if (amount.toString().equals("X")) { - sb.append("X "); - } else if (counter.getCount() > 1) { - sb.append(CardUtil.numberToText(counter.getCount())).append(' '); - } else { - sb.append(CounterType.findArticle(counter.getName())).append(' '); - plural = false; - } - sb.append(counter.getName().toLowerCase(Locale.ENGLISH)); - if (plural) { - sb.append(" counters on "); - } else { - sb.append(" counter on "); - } - sb.append(textEnchanted); - if (!amount.getMessage().isEmpty()) { - sb.append(" for each ").append(amount.getMessage()); - } - staticText = sb.toString(); - } - @Override public AddCountersAttachedEffect copy() { return new AddCountersAttachedEffect(this); } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersControllerEffect.java index b80cfd943f6..dd98ef0f530 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersControllerEffect.java @@ -1,11 +1,9 @@ - package mage.abilities.effects.common.counter; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.counters.Counter; -import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -30,7 +28,7 @@ public class AddCountersControllerEffect extends OneShotEffect { super(Outcome.Benefit); this.counter = counter.copy(); this.enchantedEquipped = enchantedEquipped; - setText(); + staticText = "its controller gets " + counter.getDescription(); } public AddCountersControllerEffect(final AddCountersControllerEffect effect) { @@ -66,16 +64,6 @@ public class AddCountersControllerEffect extends OneShotEffect { return false; } - private void setText() { - if (counter.getCount() > 1) { - StringBuilder sb = new StringBuilder(); - sb.append("its controller gets ").append(Integer.toString(counter.getCount())).append(' ').append(counter.getName()).append(" counters"); - staticText = sb.toString(); - } else { - staticText = "its controller gets " + CounterType.findArticle(counter.getName()) + " " + counter.getName() + " counter"; - } - } - @Override public AddCountersControllerEffect copy() { return new AddCountersControllerEffect(this); diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersSourceEffect.java index ec3357903b7..4f81d6f0562 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersSourceEffect.java @@ -8,7 +8,6 @@ import mage.cards.Card; import mage.constants.AbilityType; import mage.constants.Outcome; import mage.counters.Counter; -import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -16,7 +15,6 @@ import mage.util.CardUtil; import java.util.ArrayList; import java.util.List; -import java.util.Locale; import java.util.UUID; /** @@ -54,7 +52,7 @@ public class AddCountersSourceEffect extends OneShotEffect { this.informPlayers = informPlayers; this.amount = amount; this.putOnCard = putOnCard; - setText(); + staticText = CardUtil.getAddRemoveCountersText(amount, counter, "{this}", true); } public AddCountersSourceEffect(final AddCountersSourceEffect effect) { @@ -95,7 +93,7 @@ public class AddCountersSourceEffect extends OneShotEffect { if (informPlayers && !game.isSimulation()) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - game.informPlayers(player.getLogName() + " puts " + newCounter.getCount() + ' ' + newCounter.getName().toLowerCase(Locale.ENGLISH) + " counter on " + card.getLogName()); + game.informPlayers(player.getLogName() + " puts " + newCounter.getCount() + ' ' + newCounter.getName() + " counter on " + card.getLogName()); } } return true; @@ -124,7 +122,7 @@ public class AddCountersSourceEffect extends OneShotEffect { int amountAdded = permanent.getCounters(game).getCount(newCounter.getName()) - before; Player player = game.getPlayer(source.getControllerId()); if (player != null) { - game.informPlayers(player.getLogName() + " puts " + amountAdded + ' ' + newCounter.getName().toLowerCase(Locale.ENGLISH) + " counter on " + permanent.getLogName()); + game.informPlayers(player.getLogName() + " puts " + amountAdded + ' ' + newCounter.getName() + " counter on " + permanent.getLogName()); } } } @@ -133,32 +131,8 @@ public class AddCountersSourceEffect extends OneShotEffect { return true; } - private void setText() { - StringBuilder sb = new StringBuilder(); - sb.append("put "); - boolean plural = true; - if (counter.getCount() > 1) { - sb.append(CardUtil.numberToText(counter.getCount())).append(' '); - } else if (amount.toString().equals("X") && amount.getMessage().isEmpty()) { - sb.append("X "); - } else { - sb.append(CounterType.findArticle(counter.getName())).append(' '); - plural = false; - } - sb.append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter"); - if (plural) { - sb.append('s'); - } - sb.append(" on {this}"); - if (!amount.getMessage().isEmpty()) { - sb.append(" for each ").append(amount.getMessage()); - } - staticText = sb.toString(); - } - @Override public AddCountersSourceEffect copy() { return new AddCountersSourceEffect(this); } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java index 37f362d8998..724f665f0ae 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java @@ -13,10 +13,8 @@ import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.Target; import mage.util.CardUtil; -import java.util.Locale; import java.util.UUID; /** @@ -79,17 +77,17 @@ public class AddCountersTargetEffect extends OneShotEffect { permanent.addCounters(newCounter, source.getControllerId(), source, game); affectedTargets++; game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts " - + newCounter.getCount() + ' ' + newCounter.getName().toLowerCase(Locale.ENGLISH) + " counters on " + permanent.getLogName()); + + newCounter.getCount() + ' ' + newCounter.getName() + " counters on " + permanent.getLogName()); } else if (player != null) { player.addCounters(newCounter, source.getControllerId(), source, game); affectedTargets++; game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts " - + newCounter.getCount() + ' ' + newCounter.getName().toLowerCase(Locale.ENGLISH) + " counters on " + player.getLogName()); + + newCounter.getCount() + ' ' + newCounter.getName() + " counters on " + player.getLogName()); } else if (card != null) { card.addCounters(newCounter, source.getControllerId(), source, game); affectedTargets++; game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts " - + newCounter.getCount() + ' ' + newCounter.getName().toLowerCase(Locale.ENGLISH) + " counters on " + card.getLogName()); + + newCounter.getCount() + ' ' + newCounter.getName() + " counters on " + card.getLogName()); } } return affectedTargets > 0; @@ -102,51 +100,11 @@ public class AddCountersTargetEffect extends OneShotEffect { if (!staticText.isEmpty()) { return staticText; } - StringBuilder sb = new StringBuilder(); - sb.append("put "); - String counterName = counter.getName().toLowerCase(Locale.ENGLISH); - if (counter.getCount() > 1) { - sb.append(CardUtil.numberToText(counter.getCount())).append(' '); - } else { - sb.append(CounterType.findArticle(counterName)).append(' '); - } - sb.append(counterName).append(" counter"); - if (counter.getCount() > 1) { - sb.append('s'); - } - sb.append(" on "); - - Target target = mode.getTargets().getEffectTarget(this.targetPointer); - if (target != null) { - if (target.getNumberOfTargets() == 0) { - if (target.getMaxNumberOfTargets() > 1) { - sb.append("each of "); - } - sb.append("up to "); - } - - if (target.getMaxNumberOfTargets() > 1 || target.getNumberOfTargets() == 0) { - sb.append(CardUtil.numberToText(target.getMaxNumberOfTargets())) - .append(" target ").append(target.getTargetName()); - } else { - if (!target.getTargetName().startsWith("another")) { - sb.append("target "); - } - sb.append(target.getTargetName()); - } - } else { - sb.append("that creature"); - } - - if (!amount.getMessage().isEmpty()) { - sb.append(" for each ").append(amount.getMessage()); - } - return sb.toString(); + return CardUtil.getAddRemoveCountersText(amount, counter, getTargetPointer().describeTargets(mode.getTargets(), "that creature"), true); } @Override public AddCountersTargetEffect copy() { return new AddCountersTargetEffect(this); } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddRemoveAllTimeSuspentCountersEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddRemoveAllTimeSuspentCountersEffect.java deleted file mode 100644 index 7c5276979b1..00000000000 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddRemoveAllTimeSuspentCountersEffect.java +++ /dev/null @@ -1,101 +0,0 @@ - -package mage.abilities.effects.common.counter; - -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; -import mage.constants.Outcome; -import mage.counters.Counter; -import mage.counters.CounterType; -import mage.filter.Filter; -import mage.game.Game; -import mage.players.Player; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -/** - * @author Gal Lerman - */ -public class AddRemoveAllTimeSuspentCountersEffect extends OneShotEffect { - - private final Counter counter; - private final Filter filter; - private final boolean removeCounter; - private final String actionStr; - - public AddRemoveAllTimeSuspentCountersEffect(Counter counter, Filter filter, boolean removeCounter) { - super(Outcome.Benefit); - this.counter = counter; - this.filter = filter; - this.removeCounter = removeCounter; - actionStr = removeCounter ? " removes " : " puts "; - setText(); - } - - public AddRemoveAllTimeSuspentCountersEffect(final AddRemoveAllTimeSuspentCountersEffect effect) { - super(effect); - this.counter = effect.counter.copy(); - this.filter = effect.filter.copy(); - this.removeCounter = effect.removeCounter; - this.actionStr = effect.actionStr; - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = game.getObject(source); - if (controller != null && sourceObject != null) { - if (counter != null) { - List permanents = new ArrayList<>(game.getBattlefield().getAllActivePermanents()); - execute(game, controller, sourceObject, source, permanents, removeCounter); - final List exiledCards = game.getExile().getAllCards(game); - execute(game, controller, sourceObject, source, exiledCards, removeCounter); - } - return true; - } - return false; - } - - private void execute(final Game game, final Player controller, final MageObject sourceObject, Ability source, final List cards, final boolean removeCounter) { - for (Card card : cards) { - if (filter.match(card, game)) { - final String counterName = counter.getName(); - if (removeCounter) { - final Counter existingCounterOfSameType = card.getCounters(game).get(counterName); - final int countersToRemove = Math.min(existingCounterOfSameType.getCount(), counter.getCount()); - final Counter modifiedCounter = new Counter(counterName, countersToRemove); - card.removeCounters(modifiedCounter, source, game); - } else { - card.addCounters(counter, source.getControllerId(), source, game); - } - if (!game.isSimulation()) { - game.informPlayers(new StringBuilder(sourceObject.getName()).append(": ") - .append(controller.getLogName()).append(actionStr) - .append(counter.getCount()).append(' ').append(counterName.toLowerCase(Locale.ENGLISH)) - .append(" counter on ").append(card.getName()).toString()); - } - } - } - } - - private void setText() { - StringBuilder sb = new StringBuilder(); - final String actionsStr2 = removeCounter ? "remove " : " put "; - sb.append(actionsStr2); - if (counter.getCount() > 1) { - sb.append(Integer.toString(counter.getCount())).append(' ').append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counters on each "); - } else { - sb.append(CounterType.findArticle(counter.getName())).append(' ').append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter on each "); - } - sb.append(filter.getMessage()); - staticText = sb.toString(); - } - - @Override - public AddRemoveAllTimeSuspentCountersEffect copy() { - return new AddRemoveAllTimeSuspentCountersEffect(this); - } -} diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java index 6b604c58d3c..27e4f360778 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java @@ -5,10 +5,8 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.constants.Outcome; import mage.counters.Counter; -import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.util.CardUtil; /** * @author Loki @@ -20,7 +18,7 @@ public class RemoveCounterSourceEffect extends OneShotEffect { public RemoveCounterSourceEffect(Counter counter) { super(Outcome.UnboostCreature); this.counter = counter; - setText(); + staticText = "remove " + counter.getDescription() + " from {this}"; } public RemoveCounterSourceEffect(RemoveCounterSourceEffect effect) { @@ -63,14 +61,4 @@ public class RemoveCounterSourceEffect extends OneShotEffect { public RemoveCounterSourceEffect copy() { return new RemoveCounterSourceEffect(this); } - - private void setText() { - if (counter.getCount() > 1) { - StringBuilder sb = new StringBuilder(); - sb.append("remove ").append(CardUtil.numberToText(counter.getCount())).append(' ').append(counter.getName()).append(" counters from {this}"); - staticText = sb.toString(); - } else { - staticText = "remove " + CounterType.findArticle(counter.getName()) + " " + counter.getName() + " counter from {this}"; - } - } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterTargetEffect.java index e91877ee6ef..efd420ce5ed 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterTargetEffect.java @@ -8,11 +8,9 @@ import mage.choices.Choice; import mage.choices.ChoiceImpl; import mage.constants.Outcome; import mage.counters.Counter; -import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.util.CardUtil; import java.util.HashSet; import java.util.Set; @@ -41,7 +39,7 @@ public class RemoveCounterTargetEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent p = game.getPermanent(targetPointer.getFirst(game, source)); + Permanent p = game.getPermanent(getTargetPointer().getFirst(game, source)); if (p != null) { Counter toRemove = (counter == null ? selectCounterType(game, source, p) : counter); if (toRemove != null && p.getCounters(game).getCount(toRemove.getName()) >= toRemove.getCount()) { @@ -52,7 +50,7 @@ public class RemoveCounterTargetEffect extends OneShotEffect { } } } else { - Card c = game.getCard(targetPointer.getFirst(game, source)); + Card c = game.getCard(getTargetPointer().getFirst(game, source)); if (c != null && counter != null && c.getCounters(game).getCount(counter.getName()) >= counter.getCount()) { c.removeCounters(counter.getName(), counter.getCount(), source, game); if (!game.isSimulation()) { @@ -106,15 +104,9 @@ public class RemoveCounterTargetEffect extends OneShotEffect { if (staticText != null && !staticText.isEmpty()) { return staticText; } - - String text = "remove "; - if (counter == null) { - text += "a counter"; - } else { - text += CardUtil.numberToText(counter.getCount(), CounterType.findArticle(counter.getName())) + ' ' + counter.getName(); - text += counter.getCount() > 1 ? " counters" : " counter"; - } - text += " from target " + (mode.getTargets().isEmpty() ? " object" : mode.getTargets().get(0).getTargetName()); - return text; + return "remove " + + (counter == null ? "a counter" : counter.getDescription()) + + " from " + + getTargetPointer().describeTargets(mode.getTargets(), "that creature"); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCountersAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCountersAttachedEffect.java index c4a81872b85..8a4ecf35e5b 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCountersAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCountersAttachedEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common.counter; import mage.abilities.Ability; @@ -7,13 +6,10 @@ import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.counters.Counter; -import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.util.CardUtil; -import java.util.Locale; - /** * @author noahg */ @@ -21,7 +17,6 @@ public class RemoveCountersAttachedEffect extends OneShotEffect { private Counter counter; private DynamicValue amount; - private String textEnchanted; public RemoveCountersAttachedEffect(Counter counter, String textEnchanted) { this(counter, StaticValue.get(0), textEnchanted); @@ -36,8 +31,7 @@ public class RemoveCountersAttachedEffect extends OneShotEffect { super(Outcome.UnboostCreature); this.counter = counter.copy(); this.amount = amount; - this.textEnchanted = textEnchanted; - setText(); + this.staticText = CardUtil.getAddRemoveCountersText(amount, counter, textEnchanted, false); } public RemoveCountersAttachedEffect(final RemoveCountersAttachedEffect effect) { @@ -46,7 +40,6 @@ public class RemoveCountersAttachedEffect extends OneShotEffect { this.counter = effect.counter.copy(); } this.amount = effect.amount; - this.textEnchanted = effect.textEnchanted; } @Override @@ -64,27 +57,8 @@ public class RemoveCountersAttachedEffect extends OneShotEffect { return false; } - private void setText() { - StringBuilder sb = new StringBuilder(); - // put a +1/+1 counter on it - sb.append("remove "); - if (counter.getCount() > 1) { - sb.append(CardUtil.numberToText(counter.getCount())).append(' '); - sb.append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counters from "); - } else { - sb.append(CounterType.findArticle(counter.getName())).append(' '); - sb.append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter from "); - } - sb.append(textEnchanted); - if (!amount.getMessage().isEmpty()) { - sb.append(" for each ").append(amount.getMessage()); - } - staticText = sb.toString(); - } - @Override public RemoveCountersAttachedEffect copy() { return new RemoveCountersAttachedEffect(this); } - } diff --git a/Mage/src/main/java/mage/counters/Counter.java b/Mage/src/main/java/mage/counters/Counter.java index 1844fa5d3fa..64b6e797116 100644 --- a/Mage/src/main/java/mage/counters/Counter.java +++ b/Mage/src/main/java/mage/counters/Counter.java @@ -1,6 +1,7 @@ - package mage.counters; +import mage.util.CardUtil; + import java.io.Serializable; import org.apache.log4j.Logger; @@ -56,20 +57,6 @@ public class Counter implements Serializable { count += amount; } - /** - * Decreases the {@code count} by one. Will not allow the count to be less - * than 0. If an attempt is made to make the count be less than zero, the - * call will be logged. - */ - public void decrease() { - if (count > 0) { - count--; - } else { - logger.warn("An attempt was made to set the counter '" + name - + "' to less than 0. Setting to 0."); - } - } - /** * Decreases the {@code count} by the passed in {@code amount}. Will not * allow the count to be less than 0. If an attempt is made to make the @@ -105,6 +92,15 @@ public class Counter implements Serializable { return count; } + /** + * Returns a full description of this {@link Counter}, e.g. "a +1/+1 counter" or "two -1/-1 counters" + * + * @return a full description of this {@link Counter} + */ + public String getDescription() { + return CardUtil.numberToText(Math.max(count, 1), CounterType.findArticle(name)) + ' ' + name + (count > 1 ? " counters" : " counter"); + } + /** * Returns a deep copy of this object. * diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index 4f9b93e79a8..99210d782ef 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -5,6 +5,9 @@ import mage.cards.Card; import mage.filter.predicate.Predicate; import mage.game.Game; +import java.util.HashMap; +import java.util.Map; + /** * Enum for counters, names and instances. * @@ -205,6 +208,14 @@ public enum CounterType { private final String article; private final CounterPredicate predicate; + private static final Map counterNameMap = new HashMap<>(); + + static { + for (CounterType counter : CounterType.values()) { + counterNameMap.put(counter.name, counter); + } + } + CounterType(String name) { this(name, "aeiou".contains("" + name.charAt(0)) ? "an" : "a"); } @@ -301,12 +312,7 @@ public enum CounterType { } public static CounterType findByName(String name) { - for (CounterType counterType : values()) { - if (counterType.getName().equals(name)) { - return counterType; - } - } - return null; + return counterNameMap.get(name); } public static String findArticle(String name) { diff --git a/Mage/src/main/java/mage/target/Targets.java b/Mage/src/main/java/mage/target/Targets.java index 34f09ae4e95..7f73a9bab59 100644 --- a/Mage/src/main/java/mage/target/Targets.java +++ b/Mage/src/main/java/mage/target/Targets.java @@ -5,7 +5,6 @@ import mage.constants.Outcome; import mage.game.Game; import mage.game.events.GameEvent; import mage.target.targetpointer.*; -import org.apache.log4j.Logger; import java.util.ArrayList; import java.util.List; @@ -17,8 +16,6 @@ import java.util.stream.Collectors; */ public class Targets extends ArrayList { - private static final Logger logger = Logger.getLogger(Targets.class); - public Targets(Target... targets) { for (Target target : targets) { this.add(target); @@ -147,42 +144,6 @@ public class Targets extends ArrayList { return null; } - public Target getEffectTarget(TargetPointer targetPointer) { - boolean proccessed = false; - - if (targetPointer instanceof FirstTargetPointer) { - proccessed = true; - if (this.size() > 0) { - return this.get(0); - } - } - - if (targetPointer instanceof SecondTargetPointer) { - proccessed = true; - if (this.size() > 1) { - return this.get(1); - } - } - - if (targetPointer instanceof ThirdTargetPointer) { - proccessed = true; - if (this.size() > 2) { - return this.get(2); - } - } - - if (targetPointer instanceof FixedTarget || targetPointer instanceof FixedTargets) { - // fixed target = direct ID, you can't find target type and description - proccessed = true; - } - - if (!proccessed) { - logger.error("Unknown target pointer " + (targetPointer != null ? targetPointer : "null"), new Throwable()); - } - - return null; - } - public Targets copy() { return new Targets(this); } diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index 577bf30f95b..7eab08b4e2c 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -870,10 +870,10 @@ public final class CardUtil { String p = power.toString(); String t = toughness.toString(); if (!p.startsWith("-")) { - p = (t.startsWith("-") && p.equals("0") ? "-" : "+") + p; + p = t.startsWith("-") && p.equals("0") ? "-0" : "+" + p; } if (!t.startsWith("-")) { - t = (p.startsWith("-") && t.equals("0") ? "-" : "+") + t; + t = p.startsWith("-") && t.equals("0") ? "-0" : "+" + t; } return p + "/" + t; } @@ -889,7 +889,7 @@ public final class CardUtil { if (duration != Duration.EndOfGame) { String d = duration.toString(); if (!d.isEmpty()) { - sb.append(" ").append(d); + sb.append(' ').append(d); } } String message = power.getMessage(); @@ -912,6 +912,21 @@ public final class CardUtil { return Outcome.BoostCreature; } + public static String getAddRemoveCountersText(DynamicValue amount, Counter counter, String description, boolean add) { + StringBuilder sb = new StringBuilder(add ? "put " : "remove "); + boolean xValue = amount.toString().equals("X"); + if (xValue) { + sb.append("X ").append(counter.getName()).append(" counters"); + } else { + sb.append(counter.getDescription()); + } + sb.append(add ? " on " : " from ").append(description); + if (!amount.getMessage().isEmpty()) { + sb.append(xValue ? ", where X is " : " for each ").append(amount.getMessage()); + } + return sb.toString(); + } + public static boolean isFusedPartAbility(Ability ability, Game game) { // TODO: does it work fine with copies of spells on stack? if (!(ability instanceof SpellAbility)) {