mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
- More work on flash aura logic.
This commit is contained in:
@@ -120,10 +120,10 @@ public enum AiProps { /** */
|
||||
FLASH_CHANCE_TO_CAST_FOR_ETB_BEFORE_MAIN1("10"), /** */
|
||||
FLASH_CHANCE_TO_RESPOND_TO_STACK_WITH_ETB("0"), /** */
|
||||
FLASH_CHANCE_TO_CAST_AS_VALUABLE_BLOCKER("100"),
|
||||
FLASH_USE_AURAS_AS_COMBAT_TRICKS("true"),
|
||||
FLASH_AURA_CHANCE_TO_CAST_EARLY("0"),
|
||||
FLASH_AURA_CHANCE_CAST_AT_EOT("10"),
|
||||
FLASH_AURA_CHANCE_TO_RESPOND_TO_STACK("0"); /** */
|
||||
FLASH_USE_BUFF_AURAS_AS_COMBAT_TRICKS("true"),
|
||||
FLASH_BUFF_AURA_CHANCE_TO_CAST_EARLY("0"),
|
||||
FLASH_BUFF_AURA_CHANCE_CAST_AT_EOT("10"),
|
||||
FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK("0"); /** */
|
||||
// Experimental features, must be promoted or removed after extensive testing and, ideally, defaulting
|
||||
// <-- There are no experimental options here -->
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Lists;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameObject;
|
||||
@@ -49,15 +50,6 @@ public class AttachAi extends SpellAbilityAi {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Flash logic
|
||||
boolean advancedFlash = false;
|
||||
if (ai.getController().isAI()) {
|
||||
advancedFlash = ((PlayerControllerAi)ai.getController()).getAi().getBooleanProperty(AiProps.FLASH_ENABLE_ADVANCED_LOGIC);
|
||||
}
|
||||
if (source.withFlash(ai) && source.isAura() && advancedFlash && !doAdvancedFlashAuraLogic(ai)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, abCost, source, sa)) {
|
||||
@@ -97,6 +89,15 @@ public class AttachAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
// Flash logic
|
||||
boolean advancedFlash = false;
|
||||
if (ai.getController().isAI()) {
|
||||
advancedFlash = ((PlayerControllerAi)ai.getController()).getAi().getBooleanProperty(AiProps.FLASH_ENABLE_ADVANCED_LOGIC);
|
||||
}
|
||||
if (source.withFlash(ai) && source.isAura() && advancedFlash && !doAdvancedFlashAuraLogic(ai, sa, sa.getTargetCard())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (abCost.getTotalMana().countX() > 0 && source.getSVar("X").equals("Count$xPaid")) {
|
||||
// Set PayX here to maximum value. (Endless Scream and Venarian
|
||||
// Gold)
|
||||
@@ -128,26 +129,72 @@ public class AttachAi extends SpellAbilityAi {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean doAdvancedFlashAuraLogic(Player ai) {
|
||||
private boolean doAdvancedFlashAuraLogic(Player ai, SpellAbility sa, Card attachTarget) {
|
||||
Card source = sa.getHostCard();
|
||||
Game game = ai.getGame();
|
||||
Combat combat = game.getCombat();
|
||||
AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
|
||||
|
||||
if (!aic.getBooleanProperty(AiProps.FLASH_USE_BUFF_AURAS_AS_COMBAT_TRICKS)) {
|
||||
// Currently this only works with buff auras, so if the relevant toggle is disabled, just return true
|
||||
// for instant speed use. To be improved later.
|
||||
return true;
|
||||
}
|
||||
|
||||
int power = 0, toughness = 0;
|
||||
List<String> keywords = Lists.newArrayList();
|
||||
for (StaticAbility stAb : source.getStaticAbilities()) {
|
||||
if ("Continuous".equals(stAb.getParam("Mode"))) {
|
||||
if (stAb.hasParam("AddPower")) {
|
||||
power += AbilityUtils.calculateAmount(source, stAb.getParam("AddPower"), stAb);
|
||||
}
|
||||
if (stAb.hasParam("AddToughness")) {
|
||||
toughness += AbilityUtils.calculateAmount(source, stAb.getParam("AddToughness"), stAb);
|
||||
}
|
||||
if (stAb.hasParam("AddKeyword")) {
|
||||
keywords.addAll(Lists.newArrayList(stAb.getParam("AddKeyword").split(" & ")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isBuffAura = !sa.isCurse() && (power > 0 || toughness > 0 || !keywords.isEmpty());
|
||||
if (!isBuffAura) {
|
||||
// Currently only works with buff auras, otherwise returns for instant speed use. To be improved later.
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean canRespondToStack = false;
|
||||
if (!game.getStack().isEmpty()) {
|
||||
SpellAbility peekSa = game.getStack().peekAbility();
|
||||
Player activator = peekSa.getActivatingPlayer();
|
||||
if (activator != null && activator.isOpponentOf(ai) && peekSa.getApi() != ApiType.DestroyAll &&
|
||||
peekSa.getApi() != ApiType.Destroy) {
|
||||
// TODO: improve this so that the AI predicts how much damage will be dealt to the creature
|
||||
// so that it can try to save it (and won't bother targeting it if it can't be saved)
|
||||
canRespondToStack = true;
|
||||
if (activator != null && activator.isOpponentOf(ai)
|
||||
&& (!peekSa.usesTargeting() || peekSa.getTargets().getTargetCards().contains(attachTarget))) {
|
||||
if (peekSa.getApi() == ApiType.DealDamage || peekSa.getApi() == ApiType.DamageAll) {
|
||||
int dmg = AbilityUtils.calculateAmount(peekSa.getHostCard(), peekSa.getParam("NumDmg"), peekSa);
|
||||
if (dmg < toughness + attachTarget.getNetToughness()) {
|
||||
canRespondToStack = true;
|
||||
}
|
||||
} else if (peekSa.getApi() == ApiType.Destroy || peekSa.getApi() == ApiType.DestroyAll) {
|
||||
if (!attachTarget.hasKeyword(Keyword.INDESTRUCTIBLE) && !ComputerUtil.canRegenerate(ai, attachTarget)
|
||||
&& keywords.contains("Indestructible")) {
|
||||
canRespondToStack = true;
|
||||
}
|
||||
} else if (peekSa.getApi() == ApiType.Pump || peekSa.getApi() == ApiType.PumpAll) {
|
||||
int p = AbilityUtils.calculateAmount(peekSa.getHostCard(), peekSa.getParam("NumAtt"), peekSa);
|
||||
int t = AbilityUtils.calculateAmount(peekSa.getHostCard(), peekSa.getParam("NumDef"), peekSa);
|
||||
if (t < 0 && toughness > 0 && attachTarget.getNetToughness() + t + toughness > 0) {
|
||||
canRespondToStack = true;
|
||||
} else if (p < 0 && power > 0 && attachTarget.getNetToughness() + t + toughness > 0) {
|
||||
// Yep, still need to ensure that the net toughness will be positive here even if buffing for power
|
||||
canRespondToStack = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean useAurasAsTricks = aic.getBooleanProperty(AiProps.FLASH_USE_AURAS_AS_COMBAT_TRICKS);
|
||||
int chanceToCastAtEOT = aic.getIntProperty(AiProps.FLASH_AURA_CHANCE_CAST_AT_EOT);
|
||||
int chanceToCastEarly = aic.getIntProperty(AiProps.FLASH_AURA_CHANCE_TO_CAST_EARLY);
|
||||
int chanceToRespondToStack = aic.getIntProperty(AiProps.FLASH_AURA_CHANCE_TO_RESPOND_TO_STACK);
|
||||
int chanceToCastAtEOT = aic.getIntProperty(AiProps.FLASH_BUFF_AURA_CHANCE_CAST_AT_EOT);
|
||||
int chanceToCastEarly = aic.getIntProperty(AiProps.FLASH_BUFF_AURA_CHANCE_TO_CAST_EARLY);
|
||||
int chanceToRespondToStack = aic.getIntProperty(AiProps.FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK);
|
||||
|
||||
boolean hasFloatMana = ai.getManaPool().totalMana() > 0;
|
||||
boolean willDiscardNow = game.getPhaseHandler().is(PhaseType.END_OF_TURN, ai)
|
||||
@@ -155,11 +202,11 @@ public class AttachAi extends SpellAbilityAi {
|
||||
boolean willRespondToStack = canRespondToStack && MyRandom.percentTrue(chanceToRespondToStack);
|
||||
boolean willCastEarly = MyRandom.percentTrue(chanceToCastEarly);
|
||||
boolean willCastAtEOT = game.getPhaseHandler().is(PhaseType.END_OF_TURN)
|
||||
&& game.getPhaseHandler().getNextTurn().equals(ai) && MyRandom.percentTrue(chanceToCastAtEOT) || !useAurasAsTricks;
|
||||
&& game.getPhaseHandler().getNextTurn().equals(ai) && MyRandom.percentTrue(chanceToCastAtEOT);
|
||||
|
||||
boolean alternativeConsiderations = hasFloatMana || willDiscardNow || willRespondToStack || willCastAtEOT || willCastEarly;
|
||||
|
||||
if (!alternativeConsiderations && (combat == null || game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS))) {
|
||||
if (!alternativeConsiderations && (combat == null || game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS)) || (!combat.isAttacking(attachTarget) && !combat.isBlocking(attachTarget))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,8 @@ public class PermanentCreatureAi extends PermanentAi {
|
||||
if (!game.getStack().isEmpty()) {
|
||||
SpellAbility peekSa = game.getStack().peekAbility();
|
||||
Player activator = peekSa.getActivatingPlayer();
|
||||
if (activator != null && activator.isOpponentOf(ai) && peekSa.getApi() != ApiType.DestroyAll) {
|
||||
if (activator != null && activator.isOpponentOf(ai) && peekSa.getApi() != ApiType.DestroyAll
|
||||
&& peekSa.getApi() != ApiType.DamageAll) {
|
||||
canRespondToStack = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,14 +171,13 @@ FLASH_CHANCE_TO_RESPOND_TO_STACK_WITH_ETB=0
|
||||
FLASH_CHANCE_TO_CAST_AS_VALUABLE_BLOCKER=100
|
||||
# If enabled, the AI will try to hold off playing auras with Flash until the declare blockers step in combat.
|
||||
# If disabled, but advanced logic is enabled, will generally try to play these auras before its own turn.
|
||||
FLASH_USE_AURAS_AS_COMBAT_TRICKS=true
|
||||
FLASH_USE_BUFF_AURAS_AS_COMBAT_TRICKS=true
|
||||
# The chance that the AI will cast a flash aura enchantment at the earliest opportunity
|
||||
FLASH_AURA_CHANCE_TO_CAST_EARLY=0
|
||||
FLASH_BUFF_AURA_CHANCE_TO_CAST_EARLY=0
|
||||
# The chance that the AI will cast a flash aura at the end of turn before its own turn
|
||||
FLASH_AURA_CHANCE_CAST_AT_EOT=5
|
||||
# The chance that the AI will respond to stack with a flash aura (may do silly things sometimes, so better left
|
||||
# disabled or at a low chance until improved)
|
||||
FLASH_AURA_CHANCE_TO_RESPOND_TO_STACK=0
|
||||
FLASH_BUFF_AURA_CHANCE_CAST_AT_EOT=5
|
||||
# The chance that the AI will respond to stack with a flash aura which makes sense in context
|
||||
FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK=100
|
||||
|
||||
# Scry AI toggles
|
||||
# The total number of mana-producing lands at which the AI will still consider scrying away non-lands
|
||||
|
||||
@@ -172,14 +172,13 @@ FLASH_CHANCE_TO_RESPOND_TO_STACK_WITH_ETB=0
|
||||
FLASH_CHANCE_TO_CAST_AS_VALUABLE_BLOCKER=100
|
||||
# If enabled, the AI will try to hold off playing auras with Flash until the declare blockers step in combat.
|
||||
# If disabled, but advanced logic is enabled, will generally try to play these auras before its own turn.
|
||||
FLASH_USE_AURAS_AS_COMBAT_TRICKS=true
|
||||
FLASH_USE_BUFF_AURAS_AS_COMBAT_TRICKS=true
|
||||
# The chance that the AI will cast a flash aura enchantment at the earliest opportunity
|
||||
FLASH_AURA_CHANCE_TO_CAST_EARLY=5
|
||||
FLASH_BUFF_AURA_CHANCE_TO_CAST_EARLY=1
|
||||
# The chance that the AI will cast a flash aura at the end of turn before its own turn
|
||||
FLASH_AURA_CHANCE_CAST_AT_EOT=10
|
||||
# The chance that the AI will respond to stack with a flash aura (may do silly things sometimes, so better left
|
||||
# disabled or at a low chance until improved)
|
||||
FLASH_AURA_CHANCE_TO_RESPOND_TO_STACK=0
|
||||
FLASH_BUFF_AURA_CHANCE_CAST_AT_EOT=5
|
||||
# The chance that the AI will respond to stack with a flash aura which makes sense in context
|
||||
FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK=100
|
||||
|
||||
# Scry AI toggles
|
||||
# The total number of mana-producing lands at which the AI will still consider scrying away non-lands
|
||||
|
||||
@@ -170,18 +170,15 @@ FLASH_CHANCE_TO_RESPOND_TO_STACK_WITH_ETB=15
|
||||
# The chance the AI will attempt to add a new blocker in combat where it's low on creature count compared to the
|
||||
# number of attacking creatures.
|
||||
FLASH_CHANCE_TO_CAST_AS_VALUABLE_BLOCKER=100
|
||||
# The chance that the AI will try to hold off playing auras with Flash until the declare blockers step in combat.
|
||||
FLASH_CHANCE_TO_USE_AURAS_AS_COMBAT_TRICKS=100
|
||||
# If enabled, the AI will try to hold off playing auras with Flash until the declare blockers step in combat.
|
||||
# If disabled, but advanced logic is enabled, will generally try to play these auras before its own turn.
|
||||
FLASH_USE_AURAS_AS_COMBAT_TRICKS=true
|
||||
FLASH_USE_BUFF_AURAS_AS_COMBAT_TRICKS=true
|
||||
# The chance that the AI will cast a flash aura enchantment at the earliest opportunity
|
||||
FLASH_AURA_CHANCE_TO_CAST_EARLY=0
|
||||
FLASH_BUFF_AURA_CHANCE_TO_CAST_EARLY=0
|
||||
# The chance that the AI will cast a flash aura at the end of turn before its own turn
|
||||
FLASH_AURA_CHANCE_CAST_AT_EOT=10
|
||||
# The chance that the AI will respond to stack with a flash aura (may do silly things sometimes, so better left
|
||||
# disabled or at a low chance until improved)
|
||||
FLASH_AURA_CHANCE_TO_RESPOND_TO_STACK=100
|
||||
FLASH_BUFF_AURA_CHANCE_CAST_AT_EOT=10
|
||||
# The chance that the AI will respond to stack with a flash aura which makes sense in context
|
||||
FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK=100
|
||||
|
||||
# Scry AI toggles
|
||||
# The total number of mana-producing lands at which the AI will still consider scrying away non-lands
|
||||
|
||||
@@ -172,14 +172,13 @@ FLASH_CHANCE_TO_RESPOND_TO_STACK_WITH_ETB=10
|
||||
FLASH_CHANCE_TO_CAST_AS_VALUABLE_BLOCKER=100
|
||||
# If enabled, the AI will try to hold off playing auras with Flash until the declare blockers step in combat.
|
||||
# If disabled, but advanced logic is enabled, will generally try to play these auras before its own turn.
|
||||
FLASH_USE_AURAS_AS_COMBAT_TRICKS=true
|
||||
FLASH_USE_BUFF_AURAS_AS_COMBAT_TRICKS=true
|
||||
# The chance that the AI will cast a flash aura enchantment at the earliest opportunity
|
||||
FLASH_AURA_CHANCE_TO_CAST_EARLY=10
|
||||
FLASH_BUFF_AURA_CHANCE_TO_CAST_EARLY=3
|
||||
# The chance that the AI will cast a flash aura at the end of turn before its own turn
|
||||
FLASH_AURA_CHANCE_CAST_AT_EOT=30
|
||||
# The chance that the AI will respond to stack with a flash aura (may do silly things sometimes, so better left
|
||||
# disabled or at a low chance until improved)
|
||||
FLASH_AURA_CHANCE_TO_RESPOND_TO_STACK=10
|
||||
FLASH_BUFF_AURA_CHANCE_CAST_AT_EOT=10
|
||||
# The chance that the AI will respond to stack with a flash aura which makes sense in context
|
||||
FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK=100
|
||||
|
||||
# Scry AI toggles
|
||||
# The total number of mana-producing lands at which the AI will still consider scrying away non-lands
|
||||
|
||||
Reference in New Issue
Block a user