diff --git a/forge-ai/src/main/java/forge/ai/SpellApiToAi.java b/forge-ai/src/main/java/forge/ai/SpellApiToAi.java index cc2dc4647d6..71fd9251221 100644 --- a/forge-ai/src/main/java/forge/ai/SpellApiToAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellApiToAi.java @@ -75,6 +75,7 @@ public enum SpellApiToAi { .put(ApiType.DigMultiple, DigMultipleAi.class) .put(ApiType.DigUntil, DigUntilAi.class) .put(ApiType.Discard, DiscardAi.class) + .put(ApiType.Discover, DiscoverAi.class) .put(ApiType.Draft, ChooseCardNameAi.class) .put(ApiType.DrainMana, DrainManaAi.class) .put(ApiType.Draw, DrawAi.class) diff --git a/forge-ai/src/main/java/forge/ai/ability/DiscoverAi.java b/forge-ai/src/main/java/forge/ai/ability/DiscoverAi.java new file mode 100644 index 00000000000..a9afdd1340d --- /dev/null +++ b/forge-ai/src/main/java/forge/ai/ability/DiscoverAi.java @@ -0,0 +1,67 @@ +package forge.ai.ability; + +import forge.ai.AiPlayDecision; +import forge.ai.ComputerUtil; +import forge.ai.PlayerControllerAi; +import forge.ai.SpellAbilityAi; +import forge.card.CardStateName; +import forge.game.ability.AbilityUtils; +import forge.game.card.Card; +import forge.game.player.Player; +import forge.game.player.PlayerActionConfirmMode; +import forge.game.spellability.LandAbility; +import forge.game.spellability.Spell; +import forge.game.spellability.SpellAbility; + +import java.util.Map; + +public class DiscoverAi extends SpellAbilityAi { + + @Override + protected boolean checkApiLogic(final Player ai, final SpellAbility sa) { + if (ComputerUtil.preventRunAwayActivations(sa)) { + return false; // prevent infinite loop + } + + return true; + } + + /** + *

+ * doTriggerAINoCost + *

+ * @param sa + * a {@link forge.game.spellability.SpellAbility} object. + * @param mandatory + * a boolean. + * + * @return a boolean. + */ + @Override + protected boolean doTriggerAINoCost(final Player ai, final SpellAbility sa, final boolean mandatory) { + return mandatory || checkApiLogic(ai, sa); + } + + @Override + public boolean confirmAction(Player ai, SpellAbility sa, PlayerActionConfirmMode mode, String message, Map params) { + Card c = (Card)params.get("Card"); + for (SpellAbility s : AbilityUtils.getBasicSpellsFromPlayEffect(c, ai, CardStateName.Original)) { // TODO: other states for split cards and MDFC? + if (s instanceof LandAbility) { + // return false or we get a ClassCastException later if the AI encounters MDFC with land backside + return false; + } + Spell spell = (Spell) s; + if (AiPlayDecision.WillPlay == ((PlayerControllerAi)ai.getController()).getAi().canPlayFromEffectAI(spell, false, true)) { + // Before accepting, see if the spell has a valid number of targets (it should at this point). + // Proceeding past this point if the spell is not correctly targeted will result + // in "Failed to add to stack" error and the card disappearing from the game completely. + if (!spell.isTargetNumberValid()) { + // if we won't be able to pay the cost, don't choose the card + return false; + } + return true; + } + } + return false; + } +} diff --git a/forge-game/src/main/java/forge/game/ability/effects/DiscoverEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DiscoverEffect.java index ca1648ba882..a8e03769fc8 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DiscoverEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DiscoverEffect.java @@ -28,6 +28,7 @@ import org.apache.commons.lang3.StringUtils; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -76,6 +77,8 @@ public void resolve(SpellAbility sa) { changeZone(exiled, ZoneType.Exile, game, sa); // Cast it without paying its mana cost or put it into your hand. + Map params = new HashMap<>(); + params.put("Card", found); if (found != null) { String prompt = Localizer.getInstance().getMessage("lblDiscoverChoice", CardTranslation.getTranslatedName(found.getName())); @@ -83,7 +86,7 @@ public void resolve(SpellAbility sa) { List options = Arrays.asList(StringUtils.capitalize(Localizer.getInstance().getMessage("lblCast")), StringUtils.capitalize(Localizer.getInstance().getMessage("lblHandZone"))); - final boolean play = p.getController().confirmAction(sa, null, prompt, options, found, null); + final boolean play = p.getController().confirmAction(sa, null, prompt, options, found, params); boolean cancel = false; if (play) {