diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index 311fa30f69..c8da4b693b 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -113,7 +113,7 @@ public class ComputerPlayer extends PlayerImpl implements Player { if (hand.size() < 6 || isTestsMode() // ignore mulligan in tests || game.getClass().getName().contains("Momir") // ignore mulligan in Momir games - ) { + ) { return false; } Set<Card> lands = hand.getCards(new FilterLandCard(), game); @@ -540,6 +540,58 @@ public class ComputerPlayer extends PlayerImpl implements Player { return setTargetPlayer(outcome, target, source, sourceId, abilityControllerId, randomOpponentId, game, required); } + // Angel of Serenity trigger + if (target.getOriginalTarget() instanceof TargetCardInGraveyardOrBattlefield) { + Cards cards = new CardsImpl(possibleTargets); + List<Card> possibleCards = new ArrayList<>(cards.getCards(game)); + for (Card card : possibleCards) { + // check permanents first; they have more intrinsic worth + if (card instanceof Permanent) { + Permanent p = ((Permanent) card); + if (outcome.isGood() + && p.isControlledBy(abilityControllerId)) { + if (target.canTarget(abilityControllerId, p.getId(), source, game)) { + if (target.getTargets().size() >= target.getMaxNumberOfTargets()) { + break; + } + target.addTarget(p.getId(), source, game); + } + } + if (!outcome.isGood() + && !p.isControlledBy(abilityControllerId)) { + if (target.canTarget(abilityControllerId, p.getId(), source, game)) { + if (target.getTargets().size() >= target.getMaxNumberOfTargets()) { + break; + } + target.addTarget(p.getId(), source, game); + } + } + } + // check the graveyards last + if (game.getState().getZone(card.getId()) == Zone.GRAVEYARD) { + if (outcome.isGood() + && card.isOwnedBy(abilityControllerId)) { + if (target.canTarget(abilityControllerId, card.getId(), source, game)) { + if (target.getTargets().size() >= target.getMaxNumberOfTargets()) { + break; + } + target.addTarget(card.getId(), source, game); + } + } + if (!outcome.isGood() + && !card.isOwnedBy(abilityControllerId)) { + if (target.canTarget(abilityControllerId, card.getId(), source, game)) { + if (target.getTargets().size() >= target.getMaxNumberOfTargets()) { + break; + } + target.addTarget(card.getId(), source, game); + } + } + } + } + return target.isChosen(); + } + if (target.getOriginalTarget() instanceof TargetDiscard || target.getOriginalTarget() instanceof TargetCardInHand) { if (outcome.isGood()) { @@ -2659,7 +2711,7 @@ public class ComputerPlayer extends PlayerImpl implements Player { } protected void findBestPermanentTargets(Outcome outcome, UUID abilityControllerId, UUID sourceId, FilterPermanent filter, Game game, Target target, - List<Permanent> goodList, List<Permanent> badList, List<Permanent> allList) { + List<Permanent> goodList, List<Permanent> badList, List<Permanent> allList) { // searching for most valuable/powerfull permanents goodList.clear(); badList.clear(); diff --git a/Mage.Sets/src/mage/cards/a/AngelOfSerenity.java b/Mage.Sets/src/mage/cards/a/AngelOfSerenity.java index 9c03356a16..57d4f57045 100644 --- a/Mage.Sets/src/mage/cards/a/AngelOfSerenity.java +++ b/Mage.Sets/src/mage/cards/a/AngelOfSerenity.java @@ -12,13 +12,12 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.FilterPermanent; -import mage.filter.StaticFilters; -import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.target.common.TargetCardInGraveyardOrBattlefield; import java.util.UUID; +import mage.filter.common.FilterCreatureCard; +import mage.filter.common.FilterCreaturePermanent; /** * @author LevelX2 @@ -27,10 +26,13 @@ public final class AngelOfSerenity extends CardImpl { private static final String rule = "you may exile up to three other target creatures " + "from the battlefield and/or creature cards from graveyards."; - private static final FilterPermanent filter = new FilterCreaturePermanent("other target creatures"); - + + private static final FilterCreatureCard filterCreatureCard = new FilterCreatureCard("creature card in a graveyard"); + + private static final FilterCreaturePermanent filterCreaturePermanent = new FilterCreaturePermanent("other target creature"); + static { - filter.add(AnotherPredicate.instance); + filterCreaturePermanent.add(AnotherPredicate.instance); } public AngelOfSerenity(UUID ownerId, CardSetInfo setInfo) { @@ -48,7 +50,7 @@ public final class AngelOfSerenity extends CardImpl { new ExileTargetForSourceEffect().setText(rule), true ); ability.addTarget(new TargetCardInGraveyardOrBattlefield( - 0, 3, StaticFilters.FILTER_CARD_CREATURE, filter + 0, 3, filterCreatureCard, filterCreaturePermanent )); this.addAbility(ability); diff --git a/Mage/src/main/java/mage/target/TargetImpl.java b/Mage/src/main/java/mage/target/TargetImpl.java index 8d14e2f703..0e1100e5b4 100644 --- a/Mage/src/main/java/mage/target/TargetImpl.java +++ b/Mage/src/main/java/mage/target/TargetImpl.java @@ -14,6 +14,7 @@ import mage.util.CardUtil; import mage.util.RandomUtil; import java.util.*; +import mage.game.permanent.Permanent; /** * @author BetaSteward_at_googlemail.com @@ -332,7 +333,16 @@ public abstract class TargetImpl implements Target { for (UUID targetId : targets.keySet()) { Card card = game.getCard(targetId); if (card != null) { - if (zoneChangeCounters.containsKey(targetId) && zoneChangeCounters.get(targetId) != card.getZoneChangeCounter(game)) { + // if a permanent, verify it is phased in, otherwise it is illegal + Permanent p = game.getPermanent(targetId); + if (p != null + && !p.isPhasedIn()) { + illegalTargets.add(targetId); + continue; // it's not legal so continue to have a look at other targeted objects + } + // check if the card moved to another zone + if (zoneChangeCounters.containsKey(targetId) + && zoneChangeCounters.get(targetId) != card.getZoneChangeCounter(game)) { illegalTargets.add(targetId); continue; // it's not legal so continue to have a look at other targeted objects }