mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 03:08:02 +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_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 -->
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user