From f76638a227c3cc3c60977c7f81fe4ace69eb4f26 Mon Sep 17 00:00:00 2001 From: Sloth Date: Sun, 21 Oct 2012 11:54:11 +0000 Subject: [PATCH] - Moved common AI functions from AbilityFactories to ComputerUtil. --- .../card/abilityfactory/AbilityFactory.java | 18 -------- .../AbilityFactoryAlterLife.java | 15 +++---- .../abilityfactory/AbilityFactoryChoose.java | 2 +- .../AbilityFactoryCounters.java | 16 +++---- .../abilityfactory/AbilityFactoryPump.java | 21 +++++----- .../AbilityFactoryStoreSVar.java | 2 +- .../abilityfactory/AbilityFactoryToken.java | 13 +++--- .../AbilityFactoryZoneAffecting.java | 6 +-- .../java/forge/game/player/ComputerUtil.java | 42 +++++++++++++++++++ 9 files changed, 82 insertions(+), 53 deletions(-) diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactory.java b/src/main/java/forge/card/abilityfactory/AbilityFactory.java index 598eb3d22e0..42df2d85c7c 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactory.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactory.java @@ -1503,24 +1503,6 @@ public class AbilityFactory { && Singletons.getModel().getGame().getPhaseHandler().isNextTurn(PlayerType.COMPUTER)); } - // returns true if it's better to wait until blockers are declared - /** - *

- * waitForBlocking. - *

- * - * @param sa - * a {@link forge.card.spellability.SpellAbility} object. - * @return a boolean. - */ - public static boolean waitForBlocking(final SpellAbility sa) { - - return (sa.getSourceCard().isCreature() - && sa.getPayCosts().getTap() - && (Singletons.getModel().getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) - || Singletons.getModel().getGame().getPhaseHandler().isNextTurn(PlayerType.HUMAN))); - } - /** *

* isSorcerySpeed. diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryAlterLife.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryAlterLife.java index 18d938ebf3d..943447f496f 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactoryAlterLife.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactoryAlterLife.java @@ -361,7 +361,7 @@ public class AbilityFactoryAlterLife { } // Don't tap creatures that may be able to block - if (AbilityFactory.waitForBlocking(sa)) { + if (ComputerUtil.waitForBlocking(sa)) { return false; } @@ -777,6 +777,10 @@ public class AbilityFactoryAlterLife { return false; } + if (ComputerUtil.preventRunAwayActivations(sa)) { + return false; + } + if (amount >= opp.getLife()) { priority = true; // killing the human should be done asap } @@ -788,13 +792,10 @@ public class AbilityFactoryAlterLife { } // Don't tap creatures that may be able to block - if (AbilityFactory.waitForBlocking(sa) && !priority) { + if (ComputerUtil.waitForBlocking(sa) && !priority) { return false; } - // prevent run-away activations - first time will always return true - final boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn()); - final Target tgt = sa.getTarget(); if (sa.getTarget() != null) { @@ -811,7 +812,7 @@ public class AbilityFactoryAlterLife { randomReturn = true; } - return (randomReturn && chance); + return (randomReturn); } /** @@ -1270,7 +1271,7 @@ public class AbilityFactoryAlterLife { } // Don't tap creatures that may be able to block - if (AbilityFactory.waitForBlocking(sa)) { + if (ComputerUtil.waitForBlocking(sa)) { return false; } diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryChoose.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryChoose.java index c5fd56af695..abb5206b408 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactoryChoose.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactoryChoose.java @@ -1532,7 +1532,7 @@ public final class AbilityFactoryChoose { if (params.containsKey("AILogic")) { // Don't tap creatures that may be able to block - if (AbilityFactory.waitForBlocking(sa)) { + if (ComputerUtil.waitForBlocking(sa)) { return false; } diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryCounters.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryCounters.java index 3bd8cf25214..e7f174bbf3f 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactoryCounters.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactoryCounters.java @@ -310,9 +310,12 @@ public class AbilityFactoryCounters { Card choice = null; final String type = params.get("CounterType"); final String amountStr = params.get("CounterNum"); - final Player player = af.isCurse() ? ai.getOpponent() : ai; + if (ComputerUtil.preventRunAwayActivations(sa)) { + return false; + } + list = player.getCardsIn(ZoneType.Battlefield); list = CardLists.filter(list, new Predicate() { @Override @@ -367,9 +370,6 @@ public class AbilityFactoryCounters { return false; } - // prevent run-away activations - first time will always return true - boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn()); - // Targeting if (abTgt != null) { abTgt.resetTargets(); @@ -430,16 +430,16 @@ public class AbilityFactoryCounters { return false; } - if (AbilityFactory.waitForBlocking(sa)) { + if (ComputerUtil.waitForBlocking(sa)) { return false; } final AbilitySub subAb = sa.getSubAbility(); - if (subAb != null) { - chance &= subAb.chkAIDrawback(); + if (subAb != null && !subAb.chkAIDrawback()) { + return false; } - return chance; + return true; } // putCanPlayAI /** diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryPump.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryPump.java index 9e573895cf8..e92c2a0d2e5 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactoryPump.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactoryPump.java @@ -845,8 +845,9 @@ public class AbilityFactoryPump { return false; } } - - final SpellAbilityRestriction restrict = sa.getRestrictions(); + if (ComputerUtil.preventRunAwayActivations(sa)) { + return false; + } // Phase Restrictions if ((Singletons.getModel().getGame().getStack().size() == 0) && ph.getPhase().isBefore(PhaseType.COMBAT_BEGIN)) { @@ -861,6 +862,7 @@ public class AbilityFactoryPump { } } + final SpellAbilityRestriction restrict = sa.getRestrictions(); final int activations = restrict.getNumberTurnActivations(); final int sacActivations = restrict.getActivationNumberSacrifice(); // don't risk sacrificing a creature just to pump it @@ -915,7 +917,6 @@ public class AbilityFactoryPump { if (cards.size() == 0) { return false; } - final Random r = MyRandom.getRandom(); // when this happens we need to expand AI to consider if its ok for // everything? @@ -929,10 +930,10 @@ public class AbilityFactoryPump { continue; } - return r.nextFloat() <= Math.pow(.9, activations); + return true; } if (shouldPumpCard(ai, sa, card)) { - return r.nextFloat() <= Math.pow(.9, activations); + return true; } } return false; @@ -1714,15 +1715,15 @@ public class AbilityFactoryPump { */ private boolean pumpAllCanPlayAI(final Player ai, final SpellAbility sa) { String valid = ""; - final Random r = MyRandom.getRandom(); final Card source = sa.getSourceCard(); this.params = this.abilityFactory.getMapParams(); final int power = this.getNumAttack(sa); final int defense = this.getNumDefense(sa); final PhaseType phase = Singletons.getModel().getGame().getPhaseHandler().getPhase(); - // prevent runaway activations - final boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn()); // to + if (ComputerUtil.preventRunAwayActivations(sa)) { + return false; + } if (this.params.containsKey("ValidCards")) { valid = this.params.get("ValidCards"); @@ -1794,7 +1795,7 @@ public class AbilityFactoryPump { if ((CardFactoryUtil.evaluateCreatureList(comp) + 200) >= CardFactoryUtil.evaluateCreatureList(human)) { return false; } - return chance; + return true; } // end Curse // don't use non curse PumpAll after Combat_Begin until AI is improved @@ -1823,7 +1824,7 @@ public class AbilityFactoryPump { return false; } - return chance; + return true; } // pumpAllCanPlayAI() /** diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryStoreSVar.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryStoreSVar.java index 80003e986a6..82c9875d0b5 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactoryStoreSVar.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactoryStoreSVar.java @@ -246,7 +246,7 @@ public class AbilityFactoryStoreSVar { //Tree of Redemption final Player ai = sa.getActivatingPlayer(); final Card source = sa.getSourceCard(); - if (AbilityFactory.waitForBlocking(sa) || ai.getLife() + 1 >= source.getNetDefense() + if (ComputerUtil.waitForBlocking(sa) || ai.getLife() + 1 >= source.getNetDefense() || (ai.getLife() > 5 && !CombatUtil.lifeInSeriousDanger(ai, Singletons.getModel().getGame().getCombat()))) { return false; } diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryToken.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryToken.java index 5881e9532c3..217116e6f41 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactoryToken.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactoryToken.java @@ -295,6 +295,10 @@ public class AbilityFactoryToken extends AbilityFactory { final AbilityFactory af = sa.getAbilityFactory(); final HashMap mapParams = af.getMapParams(); + if (ComputerUtil.preventRunAwayActivations(sa)) { + return false; + } + Player opp = ai.getOpponent(); for (final String type : this.tokenTypes) { if (type.equals("Legendary")) { @@ -340,7 +344,6 @@ public class AbilityFactoryToken extends AbilityFactory { // prevent run-away activations - first time will always return true final Random r = MyRandom.getRandom(); final Card source = sa.getSourceCard(); - final boolean chance = r.nextFloat() <= Math.pow(.9, sa.getActivationsThisTurn()); final Target tgt = sa.getTarget(); if (tgt != null) { @@ -383,17 +386,17 @@ public class AbilityFactoryToken extends AbilityFactory { } if (AbilityFactory.playReusable(sa)) { - return chance; + return true; } if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)) { - return ((r.nextFloat() < .95) && chance); + return true; } if (sa.isAbility()) { - return ((r.nextFloat() < .9) && chance); + return (r.nextFloat() < .9); } - return ((r.nextFloat() < .8) && chance); + return (r.nextFloat() < .8); } /** diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryZoneAffecting.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryZoneAffecting.java index c1029777ed5..722a43490ed 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactoryZoneAffecting.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactoryZoneAffecting.java @@ -351,7 +351,7 @@ public class AbilityFactoryZoneAffecting { } // Don't tap creatures that may be able to block - if (AbilityFactory.waitForBlocking(sa)) { + if (ComputerUtil.waitForBlocking(sa)) { return false; } @@ -906,7 +906,7 @@ public class AbilityFactoryZoneAffecting { } // Don't tap creatures that may be able to block - if (AbilityFactory.waitForBlocking(sa)) { + if (ComputerUtil.waitForBlocking(sa)) { return false; } @@ -1688,7 +1688,7 @@ public class AbilityFactoryZoneAffecting { } // Don't tap creatures that may be able to block - if (AbilityFactory.waitForBlocking(sa) && !params.containsKey("ActivationPhases")) { + if (ComputerUtil.waitForBlocking(sa) && !params.containsKey("ActivationPhases")) { return false; } diff --git a/src/main/java/forge/game/player/ComputerUtil.java b/src/main/java/forge/game/player/ComputerUtil.java index 70864996592..4beaae9be7a 100644 --- a/src/main/java/forge/game/player/ComputerUtil.java +++ b/src/main/java/forge/game/player/ComputerUtil.java @@ -22,6 +22,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; +import java.util.Random; import com.google.common.base.Predicate; import com.google.common.base.Predicates; @@ -54,10 +55,12 @@ import forge.control.input.InputPayManaCostUtil; import forge.error.ErrorViewer; import forge.game.phase.Combat; import forge.game.phase.CombatUtil; +import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; import forge.util.Aggregates; +import forge.util.MyRandom; /** @@ -2179,4 +2182,43 @@ public class ComputerUtil { sa.setTargetPlayer(human); return true; } + + // returns true if it's better to wait until blockers are declared + /** + *

+ * waitForBlocking. + *

+ * + * @param sa + * a {@link forge.card.spellability.SpellAbility} object. + * @return a boolean (returns true if it's better to wait until blockers are declared). + */ + public static boolean waitForBlocking(final SpellAbility sa) { + final PhaseHandler ph = Singletons.getModel().getGame().getPhaseHandler(); + + return (sa.getSourceCard().isCreature() + && sa.getPayCosts().getTap() + && (ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) + || !ph.getNextTurn().equals(sa.getActivatingPlayer()))); + } + + // returns true if the AI should stop using the ability + /** + *

+ * preventRunAwayActivations. + *

+ * + * @param sa + * a {@link forge.card.spellability.SpellAbility} object. + * @return a boolean (returns true if the AI should stop using the ability). + */ + public static boolean preventRunAwayActivations(final SpellAbility sa) { + final int activations = sa.getRestrictions().getNumberTurnActivations(); + if (activations < 10) { //10 activations per turn should still be acceptable + return false; + } + final Random r = MyRandom.getRandom(); + + return r.nextFloat() <= Math.pow(.95, activations); + } }