diff --git a/Mage.Sets/src/mage/cards/c/ClarionUltimatum.java b/Mage.Sets/src/mage/cards/c/ClarionUltimatum.java index 8519f8cbd6a..136ae91f175 100644 --- a/Mage.Sets/src/mage/cards/c/ClarionUltimatum.java +++ b/Mage.Sets/src/mage/cards/c/ClarionUltimatum.java @@ -1,25 +1,23 @@ package mage.cards.c; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; -import mage.filter.FilterCard; import mage.filter.StaticFilters; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.NamePredicate; import mage.game.Game; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetCardWithSameNameAsPermanents; import mage.target.common.TargetControlledPermanent; -import mage.util.CardUtil; -import java.util.*; -import java.util.stream.Collectors; +import java.util.UUID; /** * @author North @@ -74,68 +72,14 @@ class ClarionUltimatumEffect extends OneShotEffect { TargetPermanent targetPermanent = new TargetControlledPermanent(Math.max(permCount, 5)); targetPermanent.withNotTarget(true); player.choose(outcome, targetPermanent, source, game); - Set names = targetPermanent - .getTargets() - .stream() - .map(game::getCard) - .filter(Objects::nonNull) - .map(MageObject::getName) - .collect(Collectors.toSet()); - TargetCardInLibrary targetCardInLibrary = new ClarionUltimatumTarget(names); - player.searchLibrary(targetCardInLibrary, source, game); - Cards cards = new CardsImpl(targetCardInLibrary.getTargets()); - player.moveCards(cards.getCards(game), Zone.BATTLEFIELD, source, game, true, false, false, null); + TargetCardInLibrary target = new TargetCardWithSameNameAsPermanents(targetPermanent.getTargets()); + player.searchLibrary(target, source, game); + Cards cards = new CardsImpl(target.getTargets()); + player.moveCards( + cards.getCards(game), Zone.BATTLEFIELD, source, game, + true, false, false, null + ); player.shuffleLibrary(source, game); return true; } } - -class ClarionUltimatumTarget extends TargetCardInLibrary { - - private final Map nameMap = new HashMap<>(); - - ClarionUltimatumTarget(Set names) { - super(0, names.size(), makeFilter(names)); - this.populateNameMap(names); - } - - private ClarionUltimatumTarget(final ClarionUltimatumTarget target) { - super(target); - this.nameMap.putAll(target.nameMap); - } - - @Override - public ClarionUltimatumTarget copy() { - return new ClarionUltimatumTarget(this); - } - - private static FilterCard makeFilter(Set names) { - FilterCard filter = new FilterCard(); - filter.add(Predicates.or(names.stream().map(name -> new NamePredicate(name)).collect(Collectors.toSet()))); - return filter; - } - - private void populateNameMap(Set names) { - names.stream().forEach(name -> this.nameMap.compute(name, CardUtil::setOrIncrementValue)); - } - - @Override - public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) { - if (!super.canTarget(playerId, id, source, game)) { - return false; - } - Card card = game.getCard(id); - if (card == null) { - return false; - } - Map alreadyChosen = new HashMap<>(); - this.getTargets() - .stream() - .map(game::getCard) - .filter(Objects::nonNull) - .map(MageObject::getName) - .forEach(name -> alreadyChosen.compute(name, CardUtil::setOrIncrementValue)); - return nameMap.getOrDefault(card.getName(), 0) - > alreadyChosen.getOrDefault(card.getName(), 0); - } -} diff --git a/Mage.Sets/src/mage/cards/d/Dichotomancy.java b/Mage.Sets/src/mage/cards/d/Dichotomancy.java index 4f492ff0b17..831bd9ffe83 100644 --- a/Mage.Sets/src/mage/cards/d/Dichotomancy.java +++ b/Mage.Sets/src/mage/cards/d/Dichotomancy.java @@ -1,25 +1,29 @@ package mage.cards.d; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.SuspendAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.TargetController; import mage.constants.Zone; -import mage.filter.FilterCard; import mage.filter.common.FilterNonlandPermanent; -import mage.filter.predicate.mageobject.NamePredicate; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetCardWithSameNameAsPermanents; import mage.target.common.TargetOpponent; +import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; /** * @author noahg @@ -29,7 +33,6 @@ public final class Dichotomancy extends CardImpl { public Dichotomancy(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{7}{U}{U}"); - // For each tapped nonland permanent target opponent controls, search that player’s library for a card with the same name as that permanent and put it onto the battlefield under your control. Then that player shuffles their library. this.getSpellAbility().addEffect(new DichotomancyEffect()); this.getSpellAbility().addTarget(new TargetOpponent()); @@ -53,6 +56,7 @@ class DichotomancyEffect extends OneShotEffect { private static final FilterNonlandPermanent filter = new FilterNonlandPermanent(); static { + filter.add(TargetController.YOU.getControllerPredicate()); filter.add(TappedPredicate.TAPPED); } @@ -69,26 +73,30 @@ class DichotomancyEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source)); Player controller = game.getPlayer(source.getControllerId()); - if (controller != null && opponent != null) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, opponent.getId(), game)) { - String name = permanent.getName(); - FilterCard filterCard = new FilterCard("card named \"" + name + '"'); - filterCard.add(new NamePredicate(name)); - TargetCardInLibrary target = new TargetCardInLibrary(0, 1, filterCard); - if (controller.searchLibrary(target, source, game, opponent.getId())) { - controller.moveCards(opponent.getLibrary().getCard(target.getFirstTarget(), game), Zone.BATTLEFIELD, source, game); - } - } - opponent.shuffleLibrary(source, game); - return true; + Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (controller == null || opponent == null) { + return false; } - return false; + Set set = game + .getBattlefield() + .getActivePermanents(filter, opponent.getId(), source, game) + .stream() + .map(MageItem::getId) + .collect(Collectors.toSet()); + TargetCardInLibrary target = new TargetCardWithSameNameAsPermanents(set); + controller.searchLibrary(target, source, game, opponent.getId()); + Cards cards = new CardsImpl(); + for (UUID targetId : target.getTargets()) { + cards.add(opponent.getLibrary().getCard(targetId, game)); + } + controller.moveCards(cards, Zone.BATTLEFIELD, source, game); + opponent.shuffleLibrary(source, game); + return true; } @Override public DichotomancyEffect copy() { return new DichotomancyEffect(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/d/DoublingChant.java b/Mage.Sets/src/mage/cards/d/DoublingChant.java index d5c1da4dac1..74bd4132e8a 100644 --- a/Mage.Sets/src/mage/cards/d/DoublingChant.java +++ b/Mage.Sets/src/mage/cards/d/DoublingChant.java @@ -1,23 +1,23 @@ package mage.cards.d; -import mage.MageObject; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; -import mage.filter.FilterCard; import mage.filter.StaticFilters; -import mage.filter.common.FilterCreatureCard; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.NamePredicate; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInLibrary; -import mage.util.CardUtil; +import mage.target.common.TargetCardWithSameNameAsPermanents; -import java.util.*; +import java.util.Set; +import java.util.UUID; import java.util.stream.Collectors; /** @@ -67,69 +67,20 @@ class DoublingChantEffect extends OneShotEffect { if (player == null) { return false; } - Set names = game.getBattlefield().getActivePermanents( - StaticFilters.FILTER_CONTROLLED_CREATURE, - source.getControllerId(), source, game - ) + Set set = game + .getBattlefield() + .getActivePermanents( + StaticFilters.FILTER_CONTROLLED_CREATURE, + source.getControllerId(), source, game + ) .stream() - .filter(Objects::nonNull) - .map(MageObject::getName) + .map(MageItem::getId) .collect(Collectors.toSet()); - TargetCardInLibrary targetCardInLibrary = new DoublingChantTarget(names); - player.searchLibrary(targetCardInLibrary, source, game); - Cards cards = new CardsImpl(targetCardInLibrary.getTargets()); - player.moveCards(cards, Zone.BATTLEFIELD, source, game); + TargetCardInLibrary target = new TargetCardWithSameNameAsPermanents(set); + player.searchLibrary(target, source, game); + Cards cards = new CardsImpl(target.getTargets()); + player.moveCards(cards.getCards(game), Zone.BATTLEFIELD, source, game); player.shuffleLibrary(source, game); return true; } } - -class DoublingChantTarget extends TargetCardInLibrary { - - private final Map nameMap = new HashMap<>(); - - DoublingChantTarget(Set names) { - super(0, names.size(), makeFilter(names)); - this.populateNameMap(names); - } - - private DoublingChantTarget(final DoublingChantTarget target) { - super(target); - this.nameMap.putAll(target.nameMap); - } - - @Override - public DoublingChantTarget copy() { - return new DoublingChantTarget(this); - } - - private static FilterCard makeFilter(Set names) { - FilterCard filter = new FilterCreatureCard(); - filter.add(Predicates.or(names.stream().map(name -> new NamePredicate(name)).collect(Collectors.toSet()))); - return filter; - } - - private void populateNameMap(Set names) { - names.stream().forEach(name -> this.nameMap.compute(name, CardUtil::setOrIncrementValue)); - } - - @Override - public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) { - if (!super.canTarget(playerId, id, source, game)) { - return false; - } - Card card = game.getCard(id); - if (card == null) { - return false; - } - Map alreadyChosen = new HashMap<>(); - this.getTargets() - .stream() - .map(game::getCard) - .filter(Objects::nonNull) - .map(MageObject::getName) - .forEach(name -> alreadyChosen.compute(name, CardUtil::setOrIncrementValue)); - return nameMap.getOrDefault(card.getName(), 0) - > alreadyChosen.getOrDefault(card.getName(), 0); - } -} diff --git a/Mage/src/main/java/mage/target/common/TargetCardWithSameNameAsPermanents.java b/Mage/src/main/java/mage/target/common/TargetCardWithSameNameAsPermanents.java new file mode 100644 index 00000000000..411b60794dc --- /dev/null +++ b/Mage/src/main/java/mage/target/common/TargetCardWithSameNameAsPermanents.java @@ -0,0 +1,76 @@ +package mage.target.common; + +import mage.MageItem; +import mage.abilities.Ability; +import mage.abilities.assignment.RoleAssignment; +import mage.cards.Card; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.filter.FilterCard; +import mage.game.Game; + +import java.util.Collection; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * @author TheElk801 + */ +public class TargetCardWithSameNameAsPermanents extends TargetCardInLibrary { + + private static final class SameNameAsPermanentAssignment extends RoleAssignment { + + public SameNameAsPermanentAssignment(UUID... uuids) { + super(uuids); + } + + @Override + protected Set makeSet(Card card, Game game) { + return attributes + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .filter(permanent -> permanent.sharesName(card, game)) + .map(MageItem::getId) + .collect(Collectors.toSet()); + } + } + + private final SameNameAsPermanentAssignment assigner; + private static final FilterCard defaultFilter = new FilterCard("cards with the same name"); + + public TargetCardWithSameNameAsPermanents(Collection uuids) { + this(uuids, defaultFilter); + } + + public TargetCardWithSameNameAsPermanents(Collection uuids, FilterCard filter) { + super(0, uuids.size(), filter); + this.assigner = new SameNameAsPermanentAssignment(uuids.toArray(new UUID[]{})); + } + + private TargetCardWithSameNameAsPermanents(final TargetCardWithSameNameAsPermanents target) { + super(target); + this.assigner = target.assigner; + } + + @Override + public TargetCardWithSameNameAsPermanents copy() { + return new TargetCardWithSameNameAsPermanents(this); + } + + @Override + public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) { + if (!super.canTarget(playerId, id, source, game)) { + return false; + } + Card card = game.getCard(id); + if (card == null) { + return false; + } + Cards cards = new CardsImpl(this.getTargets()); + cards.add(card); + return assigner.getRoleCount(cards, game) >= cards.size(); + } +}