mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
- Added global options to control the min CMC the AI would use permission against (disabled in both default profiles at the moment).
- Implemented some simple AI for Daze and Force of Will such that the AI does not waste them so much on every single opportunity (quite basic, needs further expansion). - Fixed Force of Will disappearing from the AI card pool when it was trying to cast it without having a valid blue card to exile in hand. - Marked Daze and Force of Will as AI-playable (should at least be more or less on par with other permission for the most part).
This commit is contained in:
@@ -35,6 +35,7 @@ public enum AiProps { /** */
|
||||
PREDICT_SPELLS_FOR_MAIN2 ("true"), /** */
|
||||
RESERVE_MANA_FOR_MAIN2_CHANCE ("0"), /** */
|
||||
PLAY_AGGRO ("false"), /** */
|
||||
MIN_SPELL_CMC_TO_COUNTER ("0"), /** */
|
||||
ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS ("false"); /** */
|
||||
|
||||
private final String strDefaultVal;
|
||||
|
||||
@@ -32,6 +32,7 @@ import forge.game.card.CardFactoryUtil;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.mana.ManaCostBeingPaid;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -187,6 +188,34 @@ public class SpecialCardAi {
|
||||
}
|
||||
}
|
||||
|
||||
// Force of Will
|
||||
public static class ForceOfWill {
|
||||
public static boolean consider(Player ai, SpellAbility sa) {
|
||||
CardCollection blueCards = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.isColor(MagicColor.BLUE));
|
||||
|
||||
boolean isExileMode = false;
|
||||
for (CostPart c : sa.getPayCosts().getCostParts()) {
|
||||
if (c.toString().contains("Exile")) {
|
||||
isExileMode = true; // the AI is trying to go for the "exile and pay life" alt cost
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isExileMode) {
|
||||
if (blueCards.size() < 2) {
|
||||
// Need to have something else in hand that is blue in addition to Force of Will itself,
|
||||
// otherwise the AI will fail to play the card and the card will disappear from the pool
|
||||
return false;
|
||||
} else if (CardLists.filter(blueCards, Predicates.or(CardPredicates.hasCMC(0), CardPredicates.hasCMC(1), CardPredicates.hasCMC(2), CardPredicates.hasCMC(3))).isEmpty()) {
|
||||
// We probably need a low-CMC card to exile to it, exiling a higher CMC spell may be suboptimal
|
||||
// since the AI does not prioritize/value cards vs. permission at the moment.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Living Death (and possibly other similar cards using AILogic LivingDeath)
|
||||
public static class LivingDeath {
|
||||
public static boolean consider(Player ai, SpellAbility sa) {
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import forge.ai.AiProps;
|
||||
import java.util.Iterator;
|
||||
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.card.MagicColor;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardFactoryUtil;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityStackInstance;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
@@ -26,6 +33,8 @@ public class CounterAi extends SpellAbilityAi {
|
||||
final Cost abCost = sa.getPayCosts();
|
||||
final Card source = sa.getHostCard();
|
||||
final Game game = ai.getGame();
|
||||
int tgtCMC = 0;
|
||||
|
||||
if (game.getStack().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
@@ -40,6 +49,12 @@ public class CounterAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
if ("Force of Will".equals(source.getName())) {
|
||||
if (!SpecialCardAi.ForceOfWill.consider(ai, sa)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
if (tgt != null) {
|
||||
|
||||
@@ -61,6 +76,10 @@ public class CounterAi extends SpellAbilityAi {
|
||||
sa.resetTargets();
|
||||
if (sa.canTargetSpellAbility(topSA)) {
|
||||
sa.getTargets().add(topSA);
|
||||
if (topSA.getPayCosts().getTotalMana() != null) {
|
||||
tgtCMC = topSA.getPayCosts().getTotalMana().getCMC();
|
||||
tgtCMC += topSA.getPayCosts().getTotalMana().countX() > 0 ? 3 : 0; // TODO: somehow determine the value of X paid and account for it?
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -110,10 +129,18 @@ public class CounterAi extends SpellAbilityAi {
|
||||
String logic = sa.getParam("AILogic");
|
||||
if ("Never".equals(logic)) {
|
||||
return false;
|
||||
} else if (logic.startsWith("MinCMC.")) {
|
||||
int minCMC = Integer.parseInt(logic.substring(7));
|
||||
if (tgtCMC < minCMC) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if minimum CMC to use counterspells against is specified in the AI profile, obey it
|
||||
if (tgtCMC < ((PlayerControllerAi)ai.getController()).getAi().getIntProperty(AiProps.MIN_SPELL_CMC_TO_COUNTER)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ MOVE_EQUIPMENT_TO_BETTER_CREATURES=from_useless_only
|
||||
PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS=true
|
||||
PREDICT_SPELLS_FOR_MAIN2=true
|
||||
RESERVE_MANA_FOR_MAIN2_CHANCE=100
|
||||
ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=false
|
||||
ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=true
|
||||
MIN_SPELL_CMC_TO_COUNTER=0
|
||||
PLAY_AGGRO=false
|
||||
|
||||
|
||||
@@ -8,5 +8,6 @@ MOVE_EQUIPMENT_TO_BETTER_CREATURES=always
|
||||
PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS=false
|
||||
PREDICT_SPELLS_FOR_MAIN2=true
|
||||
RESERVE_MANA_FOR_MAIN2_CHANCE=100
|
||||
ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=false
|
||||
ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=true
|
||||
MIN_SPELL_CMC_TO_COUNTER=0
|
||||
PLAY_AGGRO=true
|
||||
|
||||
@@ -2,7 +2,6 @@ Name:Daze
|
||||
ManaCost:1 U
|
||||
Types:Instant
|
||||
A:SP$ Counter | Cost$ 1 U | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | UnlessCost$ 1 | SpellDescription$ Counter target spell unless its controller pays {1}.
|
||||
A:SP$ Counter | Cost$ Return<1/Island> | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | UnlessCost$ 1 | CostDesc$ You may return an Island you control to its owner's hand | SpellDescription$ rather than pay CARDNAME's mana cost.
|
||||
SVar:RemAIDeck:True
|
||||
A:SP$ Counter | Cost$ Return<1/Island> | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | UnlessCost$ 1 | AILogic$ MinCMC.4 | CostDesc$ You may return an Island you control to its owner's hand | SpellDescription$ rather than pay CARDNAME's mana cost.
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/daze.jpg
|
||||
Oracle:You may return an Island you control to its owner's hand rather than pay Daze's mana cost.\nCounter target spell unless its controller pays {1}.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
Name:Force of Will
|
||||
ManaCost:3 U U
|
||||
Types:Instant
|
||||
A:SP$ Counter | Cost$ 3 U U | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | Destination$ Graveyard | SpellDescription$ Counter target spell.
|
||||
A:SP$ Counter | Cost$ 3 U U | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | Destination$ Graveyard | AILogic$ MinCMC.4 | SpellDescription$ Counter target spell.
|
||||
SVar:AltCost:Cost$ PayLife<1> ExileFromHand<1/Card.Blue> | Description$ You may pay 1 life and exile a blue card from your hand rather than pay CARDNAME's mana cost.
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/force_of_will.jpg
|
||||
Oracle:You may pay 1 life and exile a blue card from your hand rather than pay Force of Will's mana cost.\nCounter target spell.
|
||||
|
||||
Reference in New Issue
Block a user