Skip to content

Commit

Permalink
Basic Discover AI based on modified PlayAi logic (Card-Forge#4271)
Browse files Browse the repository at this point in the history
* - 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.
  • Loading branch information
Agetian authored Dec 4, 2023
1 parent 65ebceb commit c652f9c
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 1 deletion.
1 change: 1 addition & 0 deletions forge-ai/src/main/java/forge/ai/SpellApiToAi.java
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
67 changes: 67 additions & 0 deletions forge-ai/src/main/java/forge/ai/ability/DiscoverAi.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -76,14 +77,16 @@ 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<String, Object> params = new HashMap<>();
params.put("Card", found);
if (found != null) {
String prompt = Localizer.getInstance().getMessage("lblDiscoverChoice",
CardTranslation.getTranslatedName(found.getName()));
final Zone origin = found.getZone();
List<String> 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) {
Expand Down

0 comments on commit c652f9c

Please sign in to comment.