diff --git a/forge-ai/src/main/java/forge/ai/SpellApiToAi.java b/forge-ai/src/main/java/forge/ai/SpellApiToAi.java index b0f70e96b60..17943ffec4c 100644 --- a/forge-ai/src/main/java/forge/ai/SpellApiToAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellApiToAi.java @@ -105,6 +105,7 @@ public enum SpellApiToAi { .put(ApiType.MultiplyCounter, CountersMultiplyAi.class) .put(ApiType.MustAttack, MustAttackAi.class) .put(ApiType.MustBlock, MustBlockAi.class) + .put(ApiType.Mutate, MutateAi.class) .put(ApiType.NameCard, ChooseCardNameAi.class) .put(ApiType.NoteCounters, AlwaysPlayAi.class) .put(ApiType.PeekAndReveal, PeekAndRevealAi.class) diff --git a/forge-ai/src/main/java/forge/ai/ability/MutateAi.java b/forge-ai/src/main/java/forge/ai/ability/MutateAi.java new file mode 100644 index 00000000000..0d31c07213a --- /dev/null +++ b/forge-ai/src/main/java/forge/ai/ability/MutateAi.java @@ -0,0 +1,62 @@ +package forge.ai.ability; + +import com.google.common.base.Predicates; +import forge.ai.ComputerUtilCard; +import forge.ai.SpellAbilityAi; +import forge.game.card.Card; +import forge.game.card.CardCollectionView; +import forge.game.card.CardLists; +import forge.game.card.CardPredicates; +import forge.game.keyword.Keyword; +import forge.game.player.Player; +import forge.game.player.PlayerActionConfirmMode; +import forge.game.spellability.SpellAbility; + +import java.util.Map; + +public class MutateAi extends SpellAbilityAi { + @Override + protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) { + CardCollectionView mutateTgts = CardLists.filter(CardLists.getTargetableCards(aiPlayer.getCreaturesInPlay(), sa), + Predicates.not(CardPredicates.isType("Human"))); + + // Filter out some abilities that are useless + // TODO: add other stuff useless for Mutate here + mutateTgts = CardLists.filter(mutateTgts, Predicates.not(Predicates.or( + CardPredicates.hasKeyword(Keyword.DEFENDER), + CardPredicates.hasKeyword("CARDNAME can't attack."), + CardPredicates.hasKeyword("CARDNAME can't block.") + ))); + + if (mutateTgts.isEmpty()) { + return false; + } + + // Choose the best target + // TODO: maybe, instead of the standard evaluator, this could inspect the abilities and decide + // which are better in context, but that's a bit complicated for the time being (not sure if necessary?). + Card mutateTgt = ComputerUtilCard.getBestCreatureAI(mutateTgts); + sa.getTargets().add(mutateTgt); + + return true; + } + + @Override + protected Card chooseSingleCard(Player ai, SpellAbility sa, Iterable options, boolean isOptional, Player targetedPlayer, Map params) { + // Decide which card goes on top here. Pretty rudimentary, feel free to improve. + Card choice = null; + + for (Card c : options) { + if (choice == null || c.getBasePower() > choice.getBasePower() || c.getBaseToughness() > choice.getBaseToughness()) { + choice = c; + } + } + + return choice; + } + + @Override + public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) { + return true; + } +}