mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-12 00:38:44 +00:00
Basic Discover AI based on modified PlayAi logic (#4271)
* - Basic Discover AI. * - Remove some unused code. * - Remove some more unused code. * - Fix imports * - Return false for LandAbility to avoid a potential CTD * - Minor comment tweak.
This commit is contained in:
@@ -75,6 +75,7 @@ public enum SpellApiToAi {
|
|||||||
.put(ApiType.DigMultiple, DigMultipleAi.class)
|
.put(ApiType.DigMultiple, DigMultipleAi.class)
|
||||||
.put(ApiType.DigUntil, DigUntilAi.class)
|
.put(ApiType.DigUntil, DigUntilAi.class)
|
||||||
.put(ApiType.Discard, DiscardAi.class)
|
.put(ApiType.Discard, DiscardAi.class)
|
||||||
|
.put(ApiType.Discover, DiscoverAi.class)
|
||||||
.put(ApiType.Draft, ChooseCardNameAi.class)
|
.put(ApiType.Draft, ChooseCardNameAi.class)
|
||||||
.put(ApiType.DrainMana, DrainManaAi.class)
|
.put(ApiType.DrainMana, DrainManaAi.class)
|
||||||
.put(ApiType.Draw, DrawAi.class)
|
.put(ApiType.Draw, DrawAi.class)
|
||||||
|
|||||||
67
forge-ai/src/main/java/forge/ai/ability/DiscoverAi.java
Normal file
67
forge-ai/src/main/java/forge/ai/ability/DiscoverAi.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* doTriggerAINoCost
|
||||||
|
* </p>
|
||||||
|
* @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<String, Object> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ import forge.util.Localizer;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -76,6 +77,8 @@ public class DiscoverEffect extends SpellAbilityEffect {
|
|||||||
changeZone(exiled, ZoneType.Exile, game, sa);
|
changeZone(exiled, ZoneType.Exile, game, sa);
|
||||||
|
|
||||||
// Cast it without paying its mana cost or put it into your hand.
|
// Cast it without paying its mana cost or put it into your hand.
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.put("Card", found);
|
||||||
if (found != null) {
|
if (found != null) {
|
||||||
String prompt = Localizer.getInstance().getMessage("lblDiscoverChoice",
|
String prompt = Localizer.getInstance().getMessage("lblDiscoverChoice",
|
||||||
CardTranslation.getTranslatedName(found.getName()));
|
CardTranslation.getTranslatedName(found.getName()));
|
||||||
@@ -83,7 +86,7 @@ public class DiscoverEffect extends SpellAbilityEffect {
|
|||||||
List<String> options =
|
List<String> options =
|
||||||
Arrays.asList(StringUtils.capitalize(Localizer.getInstance().getMessage("lblCast")),
|
Arrays.asList(StringUtils.capitalize(Localizer.getInstance().getMessage("lblCast")),
|
||||||
StringUtils.capitalize(Localizer.getInstance().getMessage("lblHandZone")));
|
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;
|
boolean cancel = false;
|
||||||
|
|
||||||
if (play) {
|
if (play) {
|
||||||
|
|||||||
Reference in New Issue
Block a user