- More work on flash aura logic.

This commit is contained in:
Agetian
2018-11-22 19:06:44 +03:00
parent 0b0c08631a
commit 12ec6e24a2
7 changed files with 94 additions and 52 deletions

View File

@@ -120,10 +120,10 @@ public enum AiProps { /** */
FLASH_CHANCE_TO_CAST_FOR_ETB_BEFORE_MAIN1("10"), /** */ FLASH_CHANCE_TO_CAST_FOR_ETB_BEFORE_MAIN1("10"), /** */
FLASH_CHANCE_TO_RESPOND_TO_STACK_WITH_ETB("0"), /** */ FLASH_CHANCE_TO_RESPOND_TO_STACK_WITH_ETB("0"), /** */
FLASH_CHANCE_TO_CAST_AS_VALUABLE_BLOCKER("100"), FLASH_CHANCE_TO_CAST_AS_VALUABLE_BLOCKER("100"),
FLASH_USE_AURAS_AS_COMBAT_TRICKS("true"), FLASH_USE_BUFF_AURAS_AS_COMBAT_TRICKS("true"),
FLASH_AURA_CHANCE_TO_CAST_EARLY("0"), FLASH_BUFF_AURA_CHANCE_TO_CAST_EARLY("0"),
FLASH_AURA_CHANCE_CAST_AT_EOT("10"), FLASH_BUFF_AURA_CHANCE_CAST_AT_EOT("10"),
FLASH_AURA_CHANCE_TO_RESPOND_TO_STACK("0"); /** */ FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK("0"); /** */
// Experimental features, must be promoted or removed after extensive testing and, ideally, defaulting // Experimental features, must be promoted or removed after extensive testing and, ideally, defaulting
// <-- There are no experimental options here --> // <-- There are no experimental options here -->

View File

@@ -2,6 +2,7 @@ package forge.ai.ability;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import forge.ai.*; import forge.ai.*;
import forge.game.Game; import forge.game.Game;
import forge.game.GameObject; import forge.game.GameObject;
@@ -49,15 +50,6 @@ public class AttachAi extends SpellAbilityAi {
return false; 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) { if (abCost != null) {
// AI currently disabled for these costs // AI currently disabled for these costs
if (!ComputerUtilCost.checkSacrificeCost(ai, abCost, source, sa)) { 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")) { if (abCost.getTotalMana().countX() > 0 && source.getSVar("X").equals("Count$xPaid")) {
// Set PayX here to maximum value. (Endless Scream and Venarian // Set PayX here to maximum value. (Endless Scream and Venarian
// Gold) // Gold)
@@ -128,26 +129,72 @@ public class AttachAi extends SpellAbilityAi {
return true; return true;
} }
private boolean doAdvancedFlashAuraLogic(Player ai) { private boolean doAdvancedFlashAuraLogic(Player ai, SpellAbility sa, Card attachTarget) {
Card source = sa.getHostCard();
Game game = ai.getGame(); Game game = ai.getGame();
Combat combat = game.getCombat(); Combat combat = game.getCombat();
AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); 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; boolean canRespondToStack = false;
if (!game.getStack().isEmpty()) { if (!game.getStack().isEmpty()) {
SpellAbility peekSa = game.getStack().peekAbility(); SpellAbility peekSa = game.getStack().peekAbility();
Player activator = peekSa.getActivatingPlayer(); Player activator = peekSa.getActivatingPlayer();
if (activator != null && activator.isOpponentOf(ai) && peekSa.getApi() != ApiType.DestroyAll && if (activator != null && activator.isOpponentOf(ai)
peekSa.getApi() != ApiType.Destroy) { && (!peekSa.usesTargeting() || peekSa.getTargets().getTargetCards().contains(attachTarget))) {
// TODO: improve this so that the AI predicts how much damage will be dealt to the creature if (peekSa.getApi() == ApiType.DealDamage || peekSa.getApi() == ApiType.DamageAll) {
// so that it can try to save it (and won't bother targeting it if it can't be saved) 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; canRespondToStack = true;
} }
} }
}
}
boolean useAurasAsTricks = aic.getBooleanProperty(AiProps.FLASH_USE_AURAS_AS_COMBAT_TRICKS); int chanceToCastAtEOT = aic.getIntProperty(AiProps.FLASH_BUFF_AURA_CHANCE_CAST_AT_EOT);
int chanceToCastAtEOT = aic.getIntProperty(AiProps.FLASH_AURA_CHANCE_CAST_AT_EOT); int chanceToCastEarly = aic.getIntProperty(AiProps.FLASH_BUFF_AURA_CHANCE_TO_CAST_EARLY);
int chanceToCastEarly = aic.getIntProperty(AiProps.FLASH_AURA_CHANCE_TO_CAST_EARLY); int chanceToRespondToStack = aic.getIntProperty(AiProps.FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK);
int chanceToRespondToStack = aic.getIntProperty(AiProps.FLASH_AURA_CHANCE_TO_RESPOND_TO_STACK);
boolean hasFloatMana = ai.getManaPool().totalMana() > 0; boolean hasFloatMana = ai.getManaPool().totalMana() > 0;
boolean willDiscardNow = game.getPhaseHandler().is(PhaseType.END_OF_TURN, ai) 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 willRespondToStack = canRespondToStack && MyRandom.percentTrue(chanceToRespondToStack);
boolean willCastEarly = MyRandom.percentTrue(chanceToCastEarly); boolean willCastEarly = MyRandom.percentTrue(chanceToCastEarly);
boolean willCastAtEOT = game.getPhaseHandler().is(PhaseType.END_OF_TURN) 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; 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; return false;
} }

View File

@@ -123,7 +123,8 @@ public class PermanentCreatureAi extends PermanentAi {
if (!game.getStack().isEmpty()) { if (!game.getStack().isEmpty()) {
SpellAbility peekSa = game.getStack().peekAbility(); SpellAbility peekSa = game.getStack().peekAbility();
Player activator = peekSa.getActivatingPlayer(); 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; canRespondToStack = true;
} }
} }

View File

@@ -171,14 +171,13 @@ FLASH_CHANCE_TO_RESPOND_TO_STACK_WITH_ETB=0
FLASH_CHANCE_TO_CAST_AS_VALUABLE_BLOCKER=100 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 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. # 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 # 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 # 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 FLASH_BUFF_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 # The chance that the AI will respond to stack with a flash aura which makes sense in context
# disabled or at a low chance until improved) FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK=100
FLASH_AURA_CHANCE_TO_RESPOND_TO_STACK=0
# Scry AI toggles # Scry AI toggles
# The total number of mana-producing lands at which the AI will still consider scrying away non-lands # The total number of mana-producing lands at which the AI will still consider scrying away non-lands

View File

@@ -172,14 +172,13 @@ FLASH_CHANCE_TO_RESPOND_TO_STACK_WITH_ETB=0
FLASH_CHANCE_TO_CAST_AS_VALUABLE_BLOCKER=100 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 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. # 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 # 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 # 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 FLASH_BUFF_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 # The chance that the AI will respond to stack with a flash aura which makes sense in context
# disabled or at a low chance until improved) FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK=100
FLASH_AURA_CHANCE_TO_RESPOND_TO_STACK=0
# Scry AI toggles # Scry AI toggles
# The total number of mana-producing lands at which the AI will still consider scrying away non-lands # The total number of mana-producing lands at which the AI will still consider scrying away non-lands

View File

@@ -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 # 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. # number of attacking creatures.
FLASH_CHANCE_TO_CAST_AS_VALUABLE_BLOCKER=100 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 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. # 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 # 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 # 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 FLASH_BUFF_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 # The chance that the AI will respond to stack with a flash aura which makes sense in context
# disabled or at a low chance until improved) FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK=100
FLASH_AURA_CHANCE_TO_RESPOND_TO_STACK=100
# Scry AI toggles # Scry AI toggles
# The total number of mana-producing lands at which the AI will still consider scrying away non-lands # The total number of mana-producing lands at which the AI will still consider scrying away non-lands

View File

@@ -172,14 +172,13 @@ FLASH_CHANCE_TO_RESPOND_TO_STACK_WITH_ETB=10
FLASH_CHANCE_TO_CAST_AS_VALUABLE_BLOCKER=100 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 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. # 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 # 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 # 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 FLASH_BUFF_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 # The chance that the AI will respond to stack with a flash aura which makes sense in context
# disabled or at a low chance until improved) FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK=100
FLASH_AURA_CHANCE_TO_RESPOND_TO_STACK=10
# Scry AI toggles # Scry AI toggles
# The total number of mana-producing lands at which the AI will still consider scrying away non-lands # The total number of mana-producing lands at which the AI will still consider scrying away non-lands