From e94fd1b439d788135349961d66ff150a0a8fe8a0 Mon Sep 17 00:00:00 2001 From: Sloth Date: Wed, 30 Sep 2015 11:51:15 +0000 Subject: [PATCH] - Improved useRemovalNow AI function. --- .../java/forge/ai/AiAttackController.java | 4 + .../main/java/forge/ai/ComputerUtilCard.java | 86 +++++++++++++------ 2 files changed, 64 insertions(+), 26 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiAttackController.java b/forge-ai/src/main/java/forge/ai/AiAttackController.java index 4dabd497097..ed4ab8fa1db 100644 --- a/forge-ai/src/main/java/forge/ai/AiAttackController.java +++ b/forge-ai/src/main/java/forge/ai/AiAttackController.java @@ -133,6 +133,10 @@ public class AiAttackController { } return defenders; } + + public void removeBlocker(Card blocker) { + this.oppList.remove(blocker); + } /** Choose opponent for AI to attack here. Expand as necessary. */ private Player choosePreferredDefenderPlayer() { diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 672dc21848c..cbdbbc9af12 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -821,9 +821,25 @@ public class ComputerUtilCard { if (game.getPhaseHandler().getPhase().equals(PhaseType.MAIN1) && ComputerUtil.castSpellInMain1(ai, sa)) { return true; } + + //interrupt 1: Check whether a possible blocker will be killed for the AI to make a bigger attack + if (ph.is(PhaseType.MAIN1) && ph.isPlayerTurn(ai) && c.isCreature()) { + AiAttackController aiAtk = new AiAttackController(ai); + final Combat combat = new Combat(ai); + aiAtk.removeBlocker(c); + aiAtk.declareAttackers(combat); + if (!combat.getAttackers().isEmpty()) { + AiAttackController aiAtk2 = new AiAttackController(ai); + final Combat combat2 = new Combat(ai); + aiAtk2.declareAttackers(combat2); + if (combat.getAttackers().size() > combat2.getAttackers().size()) { + return true; + } + } + } - //interrupt 1:remove blocker to save my attacker - if (ph.is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { + // interrupt 2: remove blocker to save my attacker + if (ph.is(PhaseType.COMBAT_DECLARE_BLOCKERS) && !ph.isPlayerTurn(ai)) { Combat currCombat = game.getCombat(); if (currCombat != null && !currCombat.getAllBlockers().isEmpty() && currCombat.getAllBlockers().contains(c)) { for (Card attacker : currCombat.getAttackersBlockedBy(c)) { @@ -846,6 +862,29 @@ public class ComputerUtilCard { } } + // interrupt 3: two for one = good + if (c.isEnchanted()) { + boolean myEnchants = false; + for (Card enc : c.getEnchantedBy(false)) { + if (enc.getOwner().equals(ai)) { + myEnchants = true; + break; + } + } + if (!myEnchants) { + return true; //card advantage > tempo + } + } + + //interrupt 4: opponent pumping target (only works if the pump target is the chosen best target to begin with) + final MagicStack stack = game.getStack(); + if (!stack.isEmpty()) { + final SpellAbility topStack = stack.peekAbility(); + if (topStack.getActivatingPlayer().equals(opp) && c.equals(topStack.getTargetCard()) && topStack.isSpell()) { + return true; + } + } + //burn and curse spells float valueBurn = 0; if (dmg > 0) { @@ -857,6 +896,9 @@ public class ComputerUtilCard { if (sa.getTargetRestrictions().canTgtPlayer()) { valueBurn /= 2; //preserve option to burn to the face } + if (valueBurn >= 0.8 && ph.getPhase().isBefore(PhaseType.COMBAT_END)) { + return true; + } } //evaluate tempo gain @@ -880,37 +922,29 @@ public class ComputerUtilCard { if (c.isLand()) { valueTempo += 0.5f / opp.getLandsInPlay().size(); //set back opponent's mana } - if (c.isEnchanted()) { - boolean myEnchants = false; - for (Card enc : c.getEnchantedBy(false)) { - if (enc.getOwner().equals(ai)) { - myEnchants = true; - break; - } - } - if (!myEnchants) { - valueTempo += 1; //card advantage > tempo - } - } if (!ph.isPlayerTurn(ai) && ph.getPhase().equals(PhaseType.END_OF_TURN)) { valueTempo *= 2; //prefer to cast at opponent EOT } - - //interrupt 2:opponent pumping target (only works if the pump target is the chosen best target to begin with) - final MagicStack stack = ai.getGame().getStack(); - if (!stack.isEmpty()) { - final SpellAbility topStack = stack.peekAbility(); - if (topStack.getActivatingPlayer().equals(opp) && c.equals(topStack.getTargetCard()) && topStack.isSpell()) { - valueTempo += 1; - } + if (valueTempo >= 0.8 && ph.getPhase().isBefore(PhaseType.COMBAT_END)) { + return true; } //evaluate threat of targeted card float threat = 0; - if (c.isCreature() && ai.getLife() > 0) { - Combat combat = ai.getGame().getCombat(); - threat = 1.0f * ComputerUtilCombat.damageIfUnblocked(c, opp, combat, true) / ai.getLife(); - //TODO:add threat from triggers and other abilities (ie. Master of Cruelties) + if (c.isCreature()) { + // the base value for evaluate creature is 100 + threat += (-1 + 1.0f * ComputerUtilCard.evaluateCreature(c) / 100) / costRemoval; + if (ai.getLife() > 0 && ComputerUtilCombat.canAttackNextTurn(c)) { + Combat combat = game.getCombat(); + threat += 1.0f * ComputerUtilCombat.damageIfUnblocked(c, opp, combat, true) / ai.getLife(); + //TODO:add threat from triggers and other abilities (ie. Master of Cruelties) + } + if (ph.isPlayerTurn(ai) && ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)) { + threat *= 0.1; + } + if (!ph.isPlayerTurn(ai) && ph.getPhase().isBefore(PhaseType.COMBAT_BEGIN)) { + threat *= 0.1; + } } else { for (final StaticAbility stAb : c.getStaticAbilities()) { final Map params = stAb.getMapParams();