From 091fe36b2bc313d7848afa30cb6635d3dfc10f9a Mon Sep 17 00:00:00 2001 From: Agetian Date: Fri, 14 Dec 2018 13:51:23 +0300 Subject: [PATCH] - Basic logic to try not to be very wasteful with X-based direct damage spells (and the AI properties for it). Currently in Experimental profile. --- forge-ai/src/main/java/forge/ai/AiProps.java | 6 ++++-- .../java/forge/ai/ability/DamageDealAi.java | 17 ++++++++++++++++- forge-gui/res/ai/Experimental.ai | 15 ++++++++++++--- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiProps.java b/forge-ai/src/main/java/forge/ai/AiProps.java index 5e976bbfbb0..26ff72aeb7a 100644 --- a/forge-ai/src/main/java/forge/ai/AiProps.java +++ b/forge-ai/src/main/java/forge/ai/AiProps.java @@ -127,9 +127,11 @@ public enum AiProps { /** */ FLASH_USE_BUFF_AURAS_AS_COMBAT_TRICKS("true"), FLASH_BUFF_AURA_CHANCE_TO_CAST_EARLY("1"), FLASH_BUFF_AURA_CHANCE_CAST_AT_EOT("5"), - FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK("100"); /** */ + FLASH_BUFF_AURA_CHANCE_TO_RESPOND_TO_STACK("100"), /** */ // Experimental features, must be promoted or removed after extensive testing and, ideally, defaulting - // <-- There are no experimental options here --> + HOLD_X_DAMAGE_SPELLS_FOR_MORE_DAMAGE_CHANCE("0"), + HOLD_X_DAMAGE_SPELLS_THRESHOLD("0"); /** */ + // <-- There are no other experimental options here --> private final String strDefaultVal; diff --git a/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java b/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java index 08b8ea6b888..74e8b285728 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java @@ -97,8 +97,23 @@ public class DamageDealAi extends DamageAiBase { if (damage.equals("X")) { if (sa.getSVar(damage).equals("Count$xPaid") || sourceName.equals("Crater's Claws")) { - // Set PayX here to maximum value. dmg = ComputerUtilMana.determineLeftoverMana(sa, ai); + + // Try not to waste spells like Blaze or Fireball on early targets, try to do more damage with them if possible + if (ai.getController().isAI()) { + AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); + int holdChance = aic.getIntProperty(AiProps.HOLD_X_DAMAGE_SPELLS_FOR_MORE_DAMAGE_CHANCE); + if (MyRandom.percentTrue(holdChance)) { + int threshold = aic.getIntProperty(AiProps.HOLD_X_DAMAGE_SPELLS_THRESHOLD); + boolean inDanger = ComputerUtil.aiLifeInDanger(ai, false, 0); + boolean isLethal = sa.getTargetRestrictions().canTgtPlayer() && dmg >= ai.getWeakestOpponent().getLife() && !ai.getWeakestOpponent().cantLoseForZeroOrLessLife(); + if (dmg < threshold && ai.getGame().getPhaseHandler().getTurn() / 2 < threshold && !inDanger && !isLethal) { + return false; + } + } + } + + // Set PayX here to maximum value. It will be adjusted later depending on the target. source.setSVar("PayX", Integer.toString(dmg)); } else if (sa.getSVar(damage).contains("InYourHand") && source.getZone().is(ZoneType.Hand)) { dmg = CardFactoryUtil.xCount(source, sa.getSVar(damage)) - 1; // the card will be spent casting the spell, so actual damage is 1 less diff --git a/forge-gui/res/ai/Experimental.ai b/forge-gui/res/ai/Experimental.ai index e7ea101aaba..80306b55205 100644 --- a/forge-gui/res/ai/Experimental.ai +++ b/forge-gui/res/ai/Experimental.ai @@ -222,10 +222,10 @@ SURVEIL_NUM_CARDS_IN_LIBRARY_TO_BAIL=8 SURVEIL_LIFEPERC_AFTER_PAYING_LIFE=50 # Attempt to predict the number of potential blockers with various forms of evasion when -# deciding to do an all-in assault attack (Experimental!) +# deciding to do an all-in assault attack COMBAT_ASSAULT_ATTACK_EVASION_PREDICTION=true # Attempt to predict the number of potential blockers with various forms of evasion when -# deciding to do an attrition race attack (Experimental!) +# deciding to do an attrition race attack COMBAT_ATTRITION_ATTACK_EVASION_PREDICTION=true # AILogic$ PayEnergyConservatively (used for Britsling Hydra and Longtusk Cub) will only @@ -281,4 +281,13 @@ MOJHOSTO_CHANCE_TO_USE_JHOIRA_COPY_INSTANT=20 # -- features is over. These toggles will be removed later, or may be reintroduced under a -- # -- different name if necessary -- -# <-- there are no experimental options here at the moment --> +# The chance that the AI will try to hold on to a direct damage spell with X in its cost (e.g. Blaze, Fireball, etc.) +# so that it doesn't cast it too early in the game against an early game target. Note that when in danger or when the +# AI has a chance to finish the opponent off with such a spell, it will not hold back the spells. +HOLD_X_DAMAGE_SPELLS_FOR_MORE_DAMAGE_CHANCE=100 +# This threshold defines the minimum amount of damage *or* the minimum number of the AI's turn in order to play a +# direct damage spell with X without holding it back. For example, if set to 5, the AI will prefer to hold the spell +# back (unless lethal/in danger) unless it can deal 5 or more damage with it or unless it's the AI's 5th turn or later. +HOLD_X_DAMAGE_SPELLS_THRESHOLD=5 + +# <-- there are no other experimental options here at the moment -->