From f57df312c0c4611d16d9ed4e7b6d46f387cb19fb Mon Sep 17 00:00:00 2001 From: Sloth Date: Sat, 29 Nov 2014 12:03:55 +0000 Subject: [PATCH] - Improved AI handling Mishra's Factory. --- .../src/main/java/forge/ai/AiController.java | 7 ++- .../java/forge/ai/ComputerUtilCombat.java | 62 +++++++++---------- .../main/java/forge/ai/ability/AnimateAi.java | 2 +- .../main/java/forge/ai/ability/PumpAi.java | 2 +- .../java/forge/ai/ability/PumpAiBase.java | 3 +- 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 0334ed72fc7..2ed7fd995ab 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -794,9 +794,9 @@ public class AiController { } // cast 0 mana cost spells first (might be a Mox) - if (a1 == 0 && b1 > 0) { + if (a1 == 0 && b1 > 0 && ApiType.Mana != a.getApi()) { return -1; - } else if (a1 > 0 && b1 == 0) { + } else if (a1 > 0 && b1 == 0 && ApiType.Mana != b.getApi()) { return 1; } @@ -836,6 +836,9 @@ public class AiController { if (ApiType.DestroyAll == sa.getApi()) { p += 4; + } + else if (ApiType.Mana == sa.getApi()) { + p -= 9; } return p; diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java index f84a30664ca..2bf6bea71e5 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java @@ -1780,7 +1780,7 @@ public class ComputerUtilCombat { *

* @param ai * - * @param defender + * @param blocker * a {@link forge.game.card.Card} object. * @param attacker * a {@link forge.game.card.Card} object. @@ -1790,7 +1790,7 @@ public class ComputerUtilCombat { * a boolean. * @return a boolean. */ - public static boolean canDestroyBlocker(Player ai, final Card defender, final Card attacker, final Combat combat, + public static boolean canDestroyBlocker(Player ai, final Card blocker, final Card attacker, final Combat combat, final boolean withoutAbilities) { final Game game = ai.getGame(); @@ -1803,76 +1803,76 @@ public class ComputerUtilCombat { } int flankingMagnitude = 0; - if (attacker.hasKeyword("Flanking") && !defender.hasKeyword("Flanking")) { + if (attacker.hasKeyword("Flanking") && !blocker.hasKeyword("Flanking")) { flankingMagnitude = attacker.getAmountOfKeyword("Flanking"); - if (flankingMagnitude >= defender.getNetToughness()) { + if (flankingMagnitude >= blocker.getNetToughness()) { return true; } - if ((flankingMagnitude >= ComputerUtilCombat.getDamageToKill(defender)) && !defender.hasKeyword("Indestructible")) { + if ((flankingMagnitude >= ComputerUtilCombat.getDamageToKill(blocker)) && !blocker.hasKeyword("Indestructible")) { return true; } } // flanking - if (((defender.hasKeyword("Indestructible") || (ComputerUtil.canRegenerate(ai, defender) && !withoutAbilities)) && !(attacker + if (((blocker.hasKeyword("Indestructible") || (ComputerUtil.canRegenerate(ai, blocker) && !withoutAbilities)) && !(attacker .hasKeyword("Wither") || attacker.hasKeyword("Infect"))) - || (defender.hasKeyword("Persist") && !defender.canReceiveCounters(CounterType.M1M1) && (defender + || (blocker.hasKeyword("Persist") && !blocker.canReceiveCounters(CounterType.M1M1) && (blocker .getCounters(CounterType.M1M1) == 0)) - || (defender.hasKeyword("Undying") && !defender.canReceiveCounters(CounterType.P1P1) && (defender + || (blocker.hasKeyword("Undying") && !blocker.canReceiveCounters(CounterType.P1P1) && (blocker .getCounters(CounterType.P1P1) == 0))) { return false; } - if (checkDestroyBlockerTrigger(attacker, defender) && !defender.hasKeyword("Indestructible")) { + if (checkDestroyBlockerTrigger(attacker, blocker) && !blocker.hasKeyword("Indestructible")) { return true; } - if (defender.isEquipped()) { - for (Card equipment : defender.getEquippedBy(false)) { + if (blocker.isEquipped()) { + for (Card equipment : blocker.getEquippedBy(false)) { if (equipment.getName().equals("Godsend")) { return false; } } } - int defenderDamage = defender.getNetPower() - + ComputerUtilCombat.predictPowerBonusOfBlocker(attacker, defender, withoutAbilities); + int defenderDamage = blocker.getNetPower() + + ComputerUtilCombat.predictPowerBonusOfBlocker(attacker, blocker, withoutAbilities); int attackerDamage = attacker.getNetPower() - + ComputerUtilCombat.predictPowerBonusOfAttacker(attacker, defender, combat, withoutAbilities); + + ComputerUtilCombat.predictPowerBonusOfAttacker(attacker, blocker, combat, withoutAbilities); if (game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.toughnessAssignsDamage)) { - defenderDamage = defender.getNetToughness() - + ComputerUtilCombat.predictToughnessBonusOfBlocker(attacker, defender, withoutAbilities); + defenderDamage = blocker.getNetToughness() + + ComputerUtilCombat.predictToughnessBonusOfBlocker(attacker, blocker, withoutAbilities); attackerDamage = attacker.getNetToughness() - + ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, defender, combat, withoutAbilities); + + ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, withoutAbilities); } int possibleDefenderPrevention = 0; int possibleAttackerPrevention = 0; if (!withoutAbilities) { - possibleDefenderPrevention = ComputerUtil.possibleDamagePrevention(defender); + possibleDefenderPrevention = ComputerUtil.possibleDamagePrevention(blocker); possibleAttackerPrevention = ComputerUtil.possibleDamagePrevention(attacker); } // consider Damage Prevention/Replacement - defenderDamage = predictDamageTo(attacker, defenderDamage, possibleAttackerPrevention, defender, true); - attackerDamage = predictDamageTo(defender, attackerDamage, possibleDefenderPrevention, attacker, true); + defenderDamage = predictDamageTo(attacker, defenderDamage, possibleAttackerPrevention, blocker, true); + attackerDamage = predictDamageTo(blocker, attackerDamage, possibleDefenderPrevention, attacker, true); if (combat != null) { - for (Card atkr : combat.getAttackersBlockedBy(defender)) { + for (Card atkr : combat.getAttackersBlockedBy(blocker)) { if (!atkr.equals(attacker)) { - attackerDamage += predictDamageTo(defender, atkr.getNetCombatDamage(), 0, atkr, true); + attackerDamage += predictDamageTo(blocker, atkr.getNetCombatDamage(), 0, atkr, true); } } } - final int defenderLife = ComputerUtilCombat.getDamageToKill(defender) - + ComputerUtilCombat.predictToughnessBonusOfBlocker(attacker, defender, withoutAbilities); + final int defenderLife = ComputerUtilCombat.getDamageToKill(blocker) + + ComputerUtilCombat.predictToughnessBonusOfBlocker(attacker, blocker, withoutAbilities); final int attackerLife = ComputerUtilCombat.getDamageToKill(attacker) - + ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, defender, combat, withoutAbilities); + + ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, withoutAbilities); if (attacker.hasKeyword("Double Strike")) { - if (attackerDamage > 0 && (hasKeyword(attacker, "Deathtouch", withoutAbilities, combat) || defender.hasSVar("DestroyWhenDamaged"))) { + if (attackerDamage > 0 && (hasKeyword(attacker, "Deathtouch", withoutAbilities, combat) || blocker.hasSVar("DestroyWhenDamaged"))) { return true; } if (attackerDamage >= defenderLife) { @@ -1881,11 +1881,11 @@ public class ComputerUtilCombat { // Attacker may kill the blocker before he can deal normal // (secondary) damage - if (dealsFirstStrikeDamage(defender, withoutAbilities, combat) && !attacker.hasKeyword("Indestructible")) { + if (dealsFirstStrikeDamage(blocker, withoutAbilities, combat) && !attacker.hasKeyword("Indestructible")) { if (defenderDamage >= attackerLife) { return false; } - if (defenderDamage > 0 && (hasKeyword(defender, "Deathtouch", withoutAbilities, combat) || attacker.hasSVar("DestroyWhenDamaged"))) { + if (defenderDamage > 0 && (hasKeyword(blocker, "Deathtouch", withoutAbilities, combat) || attacker.hasSVar("DestroyWhenDamaged"))) { return false; } } @@ -1896,18 +1896,18 @@ public class ComputerUtilCombat { else { // no double strike for attacker // Defender may kill the attacker before he can deal any damage - if (dealsFirstStrikeDamage(defender, withoutAbilities, combat) && !attacker.hasKeyword("Indestructible") + if (dealsFirstStrikeDamage(blocker, withoutAbilities, combat) && !attacker.hasKeyword("Indestructible") && !dealsFirstStrikeDamage(attacker, withoutAbilities, combat)) { if (defenderDamage >= attackerLife) { return false; } - if (defenderDamage > 0 && (hasKeyword(defender, "Deathtouch", withoutAbilities, combat) || attacker.hasSVar("DestroyWhenDamaged"))) { + if (defenderDamage > 0 && (hasKeyword(blocker, "Deathtouch", withoutAbilities, combat) || attacker.hasSVar("DestroyWhenDamaged"))) { return false; } } - if (attackerDamage > 0 && (hasKeyword(attacker, "Deathtouch", withoutAbilities, combat) || defender.hasSVar("DestroyWhenDamaged"))) { + if (attackerDamage > 0 && (hasKeyword(attacker, "Deathtouch", withoutAbilities, combat) || blocker.hasSVar("DestroyWhenDamaged"))) { return true; } diff --git a/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java b/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java index 679f7efadad..702a5522302 100644 --- a/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java @@ -152,7 +152,7 @@ public class AnimateAi extends SpellAbilityAi { boolean givesHaste = sa.hasParam("Keywords") && sa.getParam("Keywords").contains("Haste"); for (final Card c : defined) { bFlag |= !c.isCreature() && !c.isTapped() - && (c.getTurnInZone() != game.getPhaseHandler().getTurn() || givesHaste) + && (c.getTurnInZone() != ph.getTurn() || givesHaste || ph.getPlayerTurn().isOpponentOf(aiPlayer)) && !c.isEquipping(); // for creatures that could be improved (like Figure of Destiny) diff --git a/forge-ai/src/main/java/forge/ai/ability/PumpAi.java b/forge-ai/src/main/java/forge/ai/ability/PumpAi.java index 29e9d8d8e64..1c1357f4d8d 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PumpAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PumpAi.java @@ -324,7 +324,7 @@ public class PumpAi extends PumpAiBase { list.remove(sa.getHostCard()); } if (game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS) - && game.getPhaseHandler().isPlayerTurn(opp)) { + && game.getPhaseHandler().getPlayerTurn().isOpponentOf(ai)) { list.remove(sa.getHostCard()); } } diff --git a/forge-ai/src/main/java/forge/ai/ability/PumpAiBase.java b/forge-ai/src/main/java/forge/ai/ability/PumpAiBase.java index 0bbc7b6463d..c8627ff088b 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PumpAiBase.java +++ b/forge-ai/src/main/java/forge/ai/ability/PumpAiBase.java @@ -436,7 +436,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { return false; } - if ((c.getNetToughness() + defense) <= 0) { + if (c.getNetToughness() + defense <= 0) { return false; } @@ -754,6 +754,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { kws.add(kw); } } + pumped.addNewPT(c.getCurrentPower(), c.getCurrentPower(), timestamp); pumped.addTempPowerBoost(c.getTempPowerBoost() + a); pumped.addTempToughnessBoost(c.getTempToughnessBoost() + d); pumped.addChangedCardKeywords(kws, new ArrayList(), false, timestamp);