- Moved all AI related functions in CombatUtil to the new class ComputerUtilCombat.

This commit is contained in:
Sloth
2013-01-26 22:06:31 +00:00
parent c0fbd16d93
commit 2d15feec8f
20 changed files with 1718 additions and 1662 deletions

1
.gitattributes vendored
View File

@@ -13855,6 +13855,7 @@ src/main/java/forge/game/ai/AiInputBlock.java -text
src/main/java/forge/game/ai/AiInputCommon.java svneol=native#text/plain
src/main/java/forge/game/ai/ComputerUtil.java svneol=native#text/plain
src/main/java/forge/game/ai/ComputerUtilBlock.java svneol=native#text/plain
src/main/java/forge/game/ai/ComputerUtilCombat.java -text
src/main/java/forge/game/ai/ComputerUtilCost.java -text
src/main/java/forge/game/ai/ComputerUtilMana.java -text
src/main/java/forge/game/event/BlockerAssignedEvent.java -text

View File

@@ -30,12 +30,12 @@ import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellPermanent;
import forge.card.spellability.Target;
import forge.game.GlobalRuleChange;
import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilBlock;
import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana;
import forge.game.phase.Combat;
import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
@@ -495,7 +495,7 @@ public class ChangeZoneAi extends SpellAiLogic {
}
combat = ComputerUtilBlock.getBlockers(ai, combat, ai.getCreaturesInPlay());
if (CombatUtil.lifeInDanger(ai, combat)) {
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
// need something AI can cast now
CardLists.sortByEvaluateCreature(list);
for (Card c : list) {
@@ -741,7 +741,7 @@ public class ChangeZoneAi extends SpellAiLogic {
CardLists.sortByEvaluateCreature(combatants);
for (final Card c : combatants) {
if (c.getShield() == 0 && CombatUtil.combatantWouldBeDestroyed(c) && !c.getOwner().isHuman() && !c.isToken()) {
if (c.getShield() == 0 && ComputerUtilCombat.combatantWouldBeDestroyed(c) && !c.getOwner().isHuman() && !c.isToken()) {
tgt.addTarget(c);
return true;
}

View File

@@ -14,8 +14,8 @@ import forge.card.abilityfactory.SpellAiLogic;
import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtilCost;
import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
@@ -112,7 +112,7 @@ public class ChooseSourceAi extends SpellAiLogic {
if (!c.isAttacking(ai) || !Singletons.getModel().getGame().getCombat().isUnblocked(c)) {
return false;
}
return CombatUtil.damageIfUnblocked(c, ai, Singletons.getModel().getGame().getCombat()) > 0;
return ComputerUtilCombat.damageIfUnblocked(c, ai, Singletons.getModel().getGame().getCombat()) > 0;
}
});
if (choices.isEmpty()) {

View File

@@ -13,8 +13,8 @@ import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtilCost;
import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
@@ -68,13 +68,13 @@ public class DamagePreventAi extends SpellAiLogic {
for (final Object o : objects) {
if (o instanceof Card) {
final Card c = (Card) o;
flag |= CombatUtil.combatantWouldBeDestroyed(c);
flag |= ComputerUtilCombat.combatantWouldBeDestroyed(c);
} else if (o instanceof Player) {
// Don't need to worry about Combat Damage during AI's turn
final Player p = (Player) o;
if (!handler.isPlayerTurn(p)) {
flag |= (p.isComputer() && ((CombatUtil.wouldLoseLife(ai, Singletons.getModel().getGame().getCombat()) && sa
.isAbility()) || CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())));
flag |= (p.isComputer() && ((ComputerUtilCombat.wouldLoseLife(ai, Singletons.getModel().getGame().getCombat()) && sa
.isAbility()) || ComputerUtilCombat.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())));
}
}
}
@@ -117,8 +117,8 @@ public class DamagePreventAi extends SpellAiLogic {
} // Protect combatants
else if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
if (sa.canTarget(ai) && CombatUtil.wouldLoseLife(ai, Singletons.getModel().getGame().getCombat())
&& (CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat()) || sa.isAbility())
if (sa.canTarget(ai) && ComputerUtilCombat.wouldLoseLife(ai, Singletons.getModel().getGame().getCombat())
&& (ComputerUtilCombat.lifeInDanger(ai, Singletons.getModel().getGame().getCombat()) || sa.isAbility())
&& Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(ai.getOpponent())) {
tgt.addTarget(ai);
chance = true;
@@ -134,7 +134,7 @@ public class DamagePreventAi extends SpellAiLogic {
CardLists.sortByEvaluateCreature(combatants);
for (final Card c : combatants) {
if (CombatUtil.combatantWouldBeDestroyed(c)) {
if (ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
tgt.addTarget(c);
chance = true;
break;
@@ -195,7 +195,7 @@ public class DamagePreventAi extends SpellAiLogic {
CardLists.sortByEvaluateCreature(combatants);
if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
for (final Card c : combatants) {
if (CombatUtil.combatantWouldBeDestroyed(c)) {
if (ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
tgt.addTarget(c);
return true;
}

View File

@@ -13,6 +13,7 @@ import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.GameState;
import forge.game.ai.ComputerUtilCombat;
import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
@@ -50,7 +51,7 @@ public class EffectAi extends SpellAiLogic {
if (game.getPhaseHandler().isPreventCombatDamageThisTurn()) {
return false;
}
if (!CombatUtil.lifeInDanger(ai, game.getCombat())) {
if (!ComputerUtilCombat.lifeInDanger(ai, game.getCombat())) {
return false;
}
final Target tgt = sa.getTarget();

View File

@@ -4,7 +4,7 @@ package forge.card.abilityfactory.ai;
import forge.Singletons;
import forge.card.abilityfactory.SpellAiLogic;
import forge.card.spellability.SpellAbility;
import forge.game.phase.CombatUtil;
import forge.game.ai.ComputerUtilCombat;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
@@ -34,7 +34,7 @@ public class FogAi extends SpellAiLogic {
}
// Cast it if life is in danger
return CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat());
return ComputerUtilCombat.lifeInDanger(ai, Singletons.getModel().getGame().getCombat());
}
@Override

View File

@@ -10,10 +10,10 @@ import forge.card.cost.Cost;
import forge.card.spellability.AbilitySub;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana;
import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.util.MyRandom;
@@ -67,7 +67,7 @@ public class LifeGainAi extends SpellAiLogic {
return false;
}
boolean lifeCritical = life <= 5;
lifeCritical |= (Singletons.getModel().getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DAMAGE) && CombatUtil
lifeCritical |= (Singletons.getModel().getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DAMAGE) && ComputerUtilCombat
.lifeInDanger(ai, Singletons.getModel().getGame().getCombat()));
if (abCost != null && !lifeCritical) {

View File

@@ -13,6 +13,7 @@ import forge.card.abilityfactory.SpellAiLogic;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCombat;
import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
@@ -72,10 +73,10 @@ public class MustBlockAi extends SpellAiLogic {
if (!CombatUtil.canBlock(definedAttacker, c)) {
return false;
}
if (CombatUtil.canDestroyAttacker(definedAttacker, c, null, false)) {
if (ComputerUtilCombat.canDestroyAttacker(definedAttacker, c, null, false)) {
return false;
}
if (!CombatUtil.canDestroyBlocker(c, definedAttacker, null, false)) {
if (!ComputerUtilCombat.canDestroyBlocker(c, definedAttacker, null, false)) {
return false;
}
c.setTapped(tapped);

View File

@@ -15,8 +15,8 @@ import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtilCost;
import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
@@ -90,14 +90,14 @@ public class ProtectAi extends SpellAiLogic {
// is the creature blocking and unable to destroy the attacker
// or would be destroyed itself?
if (c.isBlocking()
&& (CombatUtil.blockerWouldBeDestroyed(c))) {
&& (ComputerUtilCombat.blockerWouldBeDestroyed(c))) {
return true;
}
// is the creature in blocked and the blocker would survive
if (Singletons.getModel().getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)
&& Singletons.getModel().getGame().getCombat().isAttacking(c) && Singletons.getModel().getGame().getCombat().isBlocked(c)
&& CombatUtil.blockerWouldBeDestroyed(Singletons.getModel().getGame().getCombat().getBlockers(c).get(0))) {
&& ComputerUtilCombat.blockerWouldBeDestroyed(Singletons.getModel().getGame().getCombat().getBlockers(c).get(0))) {
return true;
}

View File

@@ -16,6 +16,7 @@ import forge.card.abilityfactory.AbilityFactory;
import forge.card.abilityfactory.SpellAiLogic;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility;
import forge.game.ai.ComputerUtilCombat;
import forge.game.phase.Combat;
import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseHandler;
@@ -180,7 +181,7 @@ public abstract class PumpAiBase extends SpellAiLogic {
&& !CardLists.getKeyword(Singletons.getModel().getGame().getCombat().getAttackerList(), "Flying").isEmpty()
&& !card.hasKeyword("Reach")
&& CombatUtil.canBlock(card)
&& CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())) {
&& ComputerUtilCombat.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())) {
return true;
}
Predicate<Card> flyingOrReach = Predicates.or(CardPredicates.hasKeyword("Flying"), CardPredicates.hasKeyword("Reach"));
@@ -196,7 +197,7 @@ public abstract class PumpAiBase extends SpellAiLogic {
&& ph.getPhase().equals(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)
&& !CardLists.getKeyword(Singletons.getModel().getGame().getCombat().getAttackerList(), "Horsemanship").isEmpty()
&& CombatUtil.canBlock(card)
&& CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())) {
&& ComputerUtilCombat.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())) {
return true;
}
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
@@ -222,7 +223,7 @@ public abstract class PumpAiBase extends SpellAiLogic {
List<Card> attackers = combat.getAttackers();
for (Card attacker : attackers) {
if (CombatUtil.canBlock(attacker, card, combat)
&& !CombatUtil.canDestroyAttacker(attacker, card, combat, false)) {
&& !ComputerUtilCombat.canDestroyAttacker(attacker, card, combat, false)) {
return true;
}
}
@@ -231,7 +232,7 @@ public abstract class PumpAiBase extends SpellAiLogic {
List<Card> blockers = opp.getCreaturesInPlay();
for (Card blocker : blockers) {
if (CombatUtil.canBlock(card, blocker, combat)
&& !CombatUtil.canDestroyBlocker(blocker, card, combat, false)) {
&& !ComputerUtilCombat.canDestroyBlocker(blocker, card, combat, false)) {
return true;
}
}
@@ -407,13 +408,13 @@ public abstract class PumpAiBase extends SpellAiLogic {
// is the creature blocking and unable to destroy the attacker
// or would be destroyed itself?
if (phase.is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) && c.isBlocking()) {
if (defense > 0 && CombatUtil.blockerWouldBeDestroyed(c)) {
if (defense > 0 && ComputerUtilCombat.blockerWouldBeDestroyed(c)) {
return true;
}
List<Card> blockedBy = Singletons.getModel().getGame().getCombat().getAttackersBlockedBy(c);
// For now, Only care the first creature blocked by a card.
// TODO Add in better BlockAdditional support
if (!blockedBy.isEmpty() && attack > 0 && !CombatUtil.attackerWouldBeDestroyed(blockedBy.get(0))) {
if (!blockedBy.isEmpty() && attack > 0 && !ComputerUtilCombat.attackerWouldBeDestroyed(blockedBy.get(0))) {
return true;
}
}
@@ -431,7 +432,7 @@ public abstract class PumpAiBase extends SpellAiLogic {
&& Singletons.getModel().getGame().getCombat().isBlocked(c)
&& Singletons.getModel().getGame().getCombat().getBlockers(c) != null
&& !Singletons.getModel().getGame().getCombat().getBlockers(c).isEmpty()
&& !CombatUtil.blockerWouldBeDestroyed(Singletons.getModel().getGame().getCombat().getBlockers(c).get(0))) {
&& !ComputerUtilCombat.blockerWouldBeDestroyed(Singletons.getModel().getGame().getCombat().getBlockers(c).get(0))) {
return true;
}
@@ -447,7 +448,7 @@ public abstract class PumpAiBase extends SpellAiLogic {
&& c.isBlocking()
&& defense > 0
&& attackerHasTrample
&& (sa.isAbility() || CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat()))) {
&& (sa.isAbility() || ComputerUtilCombat.lifeInDanger(ai, Singletons.getModel().getGame().getCombat()))) {
return true;
}

View File

@@ -13,6 +13,7 @@ import forge.card.abilityfactory.AbilityFactory;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtil;
import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseType;
@@ -90,7 +91,7 @@ public class PumpAllAi extends PumpAiBase {
totalPower += Math.min(c.getNetAttack(), power * -1);
if (phase == PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY
&& Singletons.getModel().getGame().getCombat().getUnblockedAttackers().contains(c)) {
if (CombatUtil.lifeInDanger(sa.getActivatingPlayer(), Singletons.getModel().getGame().getCombat())) {
if (ComputerUtilCombat.lifeInDanger(sa.getActivatingPlayer(), Singletons.getModel().getGame().getCombat())) {
return true;
}
totalPower += Math.min(c.getNetAttack(), power * -1);

View File

@@ -31,8 +31,8 @@ import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtilCost;
import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
@@ -95,7 +95,7 @@ public class RegenerateAi extends SpellAiLogic {
for (final Card c : list) {
if (c.getShield() == 0) {
flag |= CombatUtil.combatantWouldBeDestroyed(c);
flag |= ComputerUtilCombat.combatantWouldBeDestroyed(c);
}
}
@@ -139,7 +139,7 @@ public class RegenerateAi extends SpellAiLogic {
CardLists.sortByEvaluateCreature(combatants);
for (final Card c : combatants) {
if ((c.getShield() == 0) && CombatUtil.combatantWouldBeDestroyed(c)) {
if ((c.getShield() == 0) && ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
tgt.addTarget(c);
chance = true;
break;
@@ -190,7 +190,7 @@ public class RegenerateAi extends SpellAiLogic {
CardLists.sortByEvaluateCreature(combatants);
if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
for (final Card c : combatants) {
if ((c.getShield() == 0) && CombatUtil.combatantWouldBeDestroyed(c)) {
if ((c.getShield() == 0) && ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
tgt.addTarget(c);
return true;
}

View File

@@ -11,8 +11,8 @@ import forge.card.abilityfactory.AbilityFactory;
import forge.card.abilityfactory.SpellAiLogic;
import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility;
import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtilCost;
import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
@@ -68,7 +68,7 @@ public class RegenerateAllAi extends SpellAiLogic {
final List<Card> combatants = CardLists.filter(list, CardPredicates.Presets.CREATURES);
for (final Card c : combatants) {
if (c.getShield() == 0 && CombatUtil.combatantWouldBeDestroyed(c)) {
if (c.getShield() == 0 && ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
numSaved++;
}
}

View File

@@ -4,8 +4,8 @@ import forge.Card;
import forge.Singletons;
import forge.card.abilityfactory.SpellAiLogic;
import forge.card.spellability.SpellAbility;
import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtil;
import forge.game.phase.CombatUtil;
import forge.game.player.Player;
public class StoreSVarAi extends SpellAiLogic {
@@ -16,7 +16,7 @@ public class StoreSVarAi extends SpellAiLogic {
final Card source = sa.getSourceCard();
if (ComputerUtil.waitForBlocking(sa) || ai.getLife() + 1 >= source.getNetDefense()
|| (ai.getLife() > 5 && !CombatUtil.lifeInSeriousDanger(ai, Singletons.getModel().getGame().getCombat()))) {
|| (ai.getLife() > 5 && !ComputerUtilCombat.lifeInSeriousDanger(ai, Singletons.getModel().getGame().getCombat()))) {
return false;
}

View File

@@ -14,7 +14,7 @@ import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityStackInstance;
import forge.card.spellability.Target;
import forge.game.phase.CombatUtil;
import forge.game.ai.ComputerUtilCombat;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
@@ -178,7 +178,7 @@ public class ChooseSourceEffect extends SpellEffect {
if (!c.isAttacking(ai) || !Singletons.getModel().getGame().getCombat().isUnblocked(c)) {
return false;
}
return CombatUtil.damageIfUnblocked(c, ai, Singletons.getModel().getGame().getCombat()) > 0;
return ComputerUtilCombat.damageIfUnblocked(c, ai, Singletons.getModel().getGame().getCombat()) > 0;
}
});
chosen.add(CardFactoryUtil.getBestCreatureAI(sourcesToChooseFrom));

View File

@@ -140,15 +140,15 @@ public class AiAttackController {
public final boolean isEffectiveAttacker(final Player ai, final Card attacker, final Combat combat) {
// if the attacker will die when attacking don't attack
if ((attacker.getNetDefense() + CombatUtil.predictToughnessBonusOfAttacker(attacker, null, combat, true)) <= 0) {
if ((attacker.getNetDefense() + ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, null, combat, true)) <= 0) {
return false;
}
final Player opp = ai.getOpponent();
if (CombatUtil.damageIfUnblocked(attacker, opp, combat) > 0) {
if (ComputerUtilCombat.damageIfUnblocked(attacker, opp, combat) > 0) {
return true;
}
if (CombatUtil.poisonIfUnblocked(attacker, opp) > 0) {
if (ComputerUtilCombat.poisonIfUnblocked(attacker, opp) > 0) {
return true;
}
if (this.attackers.size() == 1 && attacker.hasKeyword("Exalted")) {
@@ -158,7 +158,7 @@ public class AiAttackController {
final List<Card> controlledByCompy = ai.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES);
for (final Card c : controlledByCompy) {
for (final Trigger trigger : c.getTriggers()) {
if (CombatUtil.combatTriggerWillTrigger(attacker, null, trigger, combat)) {
if (ComputerUtilCombat.combatTriggerWillTrigger(attacker, null, trigger, combat)) {
return true;
}
}
@@ -350,8 +350,8 @@ public class AiAttackController {
blockersLeft--;
continue;
}
totalAttack += CombatUtil.damageIfUnblocked(attacker, ai, null);
totalPoison += CombatUtil.poisonIfUnblocked(attacker, ai);
totalAttack += ComputerUtilCombat.damageIfUnblocked(attacker, ai, null);
totalPoison += ComputerUtilCombat.poisonIfUnblocked(attacker, ai);
}
if (totalAttack > 0 && ai.getLife() <= totalAttack
@@ -425,12 +425,12 @@ public class AiAttackController {
}
unblockedAttackers.addAll(remainingAttackers);
if ((CombatUtil.sumDamageIfUnblocked(remainingAttackers, opp) >= opp.getLife())
if ((ComputerUtilCombat.sumDamageIfUnblocked(remainingAttackers, opp) >= opp.getLife())
&& !((opp.cantLoseForZeroOrLessLife() || ai.cantWin()) && (opp.getLife() < 1))) {
return true;
}
if (CombatUtil.sumPoisonIfUnblocked(remainingAttackers, opp) >= (10 - opp.getPoisonCounters())) {
if (ComputerUtilCombat.sumPoisonIfUnblocked(remainingAttackers, opp) >= (10 - opp.getPoisonCounters())) {
return true;
}
@@ -621,7 +621,7 @@ public class AiAttackController {
if (CombatUtil.canAttackNextTurn(pCard)) {
candidateAttackers.add(pCard);
if (pCard.getNetCombatDamage() > 0) {
candidateUnblockedDamage += CombatUtil.damageIfUnblocked(pCard, opp, null);
candidateUnblockedDamage += ComputerUtilCombat.damageIfUnblocked(pCard, opp, null);
computerForces += 1;
}
@@ -717,7 +717,7 @@ public class AiAttackController {
}
}
if (isUnblockableCreature) {
unblockableDamage += CombatUtil.damageIfUnblocked(attacker, opp, combat);
unblockableDamage += ComputerUtilCombat.damageIfUnblocked(attacker, opp, combat);
}
}
for (final Card attacker : nextTurnAttackers) {
@@ -731,7 +731,7 @@ public class AiAttackController {
}
}
if (isUnblockableCreature) {
nextUnblockableDamage += CombatUtil.damageIfUnblocked(attacker, opp, null);
nextUnblockableDamage += ComputerUtilCombat.damageIfUnblocked(attacker, opp, null);
}
}
if (unblockableDamage > 0 && !opp.cantLoseForZeroOrLessLife()
@@ -785,7 +785,7 @@ public class AiAttackController {
for (int i = 0; i < attackersLeft.size(); i++) {
final Card attacker = attackersLeft.get(i);
if (this.aiAggression < 5 && !attacker.hasFirstStrike() && !attacker.hasDoubleStrike()
&& CombatUtil.getTotalFirstStrikeBlockPower(attacker, ai.getOpponent())
&& ComputerUtilCombat.getTotalFirstStrikeBlockPower(attacker, ai.getOpponent())
>= attacker.getKillDamage()) {
continue;
}
@@ -803,7 +803,7 @@ public class AiAttackController {
CardLists.sortAttackLowFirst(attacking);
for (Card atta : attacking) {
if (attackNum >= blockNum || !CombatUtil.canBeBlocked(attacker, this.blockers)) {
damage += CombatUtil.damageIfUnblocked(atta, opp, null);
damage += ComputerUtilCombat.damageIfUnblocked(atta, opp, null);
} else if (CombatUtil.canBeBlocked(attacker, this.blockers)) {
attackNum++;
}
@@ -901,7 +901,7 @@ public class AiAttackController {
if ((isWorthLessThanAllKillers || canKillAllDangerous || numberOfPossibleBlockers < 2)
&& CombatUtil.canBlock(attacker, defender)) {
numberOfPossibleBlockers += 1;
if (isWorthLessThanAllKillers && CombatUtil.canDestroyAttacker(attacker, defender, combat, false)
if (isWorthLessThanAllKillers && ComputerUtilCombat.canDestroyAttacker(attacker, defender, combat, false)
&& !(attacker.hasKeyword("Undying") && attacker.getCounters(CounterType.P1P1) == 0)) {
canBeKilledByOne = true; // there is a single creature on
// the battlefield that can kill
@@ -915,7 +915,7 @@ public class AiAttackController {
}
// see if this attacking creature can destroy this defender, if
// not record that it can't kill everything
if (canKillAllDangerous && !CombatUtil.canDestroyBlocker(defender, attacker, combat, false)) {
if (canKillAllDangerous && !ComputerUtilCombat.canDestroyBlocker(defender, attacker, combat, false)) {
canKillAll = false;
if (!canKillAllDangerous) {
continue;

View File

@@ -1006,7 +1006,7 @@ public class ComputerUtil {
}
}
combat = ComputerUtilBlock.getBlockers(ai, combat, ai.getCreaturesInPlay());
if (!CombatUtil.lifeInDanger(ai, combat)) {
if (!ComputerUtilCombat.lifeInDanger(ai, combat)) {
// Otherwise, return false. Do not play now.
ret = false;
}

View File

@@ -233,7 +233,7 @@ public class ComputerUtilBlock {
final List<Card> blockers = new ArrayList<Card>();
for (final Card b : blockersLeft) {
if (!CombatUtil.canDestroyBlocker(b, attacker, combat, false)) {
if (!ComputerUtilCombat.canDestroyBlocker(b, attacker, combat, false)) {
blockers.add(b);
}
}
@@ -259,7 +259,7 @@ public class ComputerUtilBlock {
final List<Card> blockers = new ArrayList<Card>();
for (final Card b : blockersLeft) {
if (CombatUtil.canDestroyAttacker(attacker, b, combat, false)) {
if (ComputerUtilCombat.canDestroyAttacker(attacker, b, combat, false)) {
blockers.add(b);
}
}
@@ -293,7 +293,7 @@ public class ComputerUtilBlock {
return firstAttacker;
}
final boolean bLifeInDanger = CombatUtil.lifeInDanger(ai, combat);
final boolean bLifeInDanger = ComputerUtilCombat.lifeInDanger(ai, combat);
// TODO Add creatures attacking Planeswalkers in order of which we want
// to protect
@@ -427,14 +427,14 @@ public class ComputerUtilBlock {
CardLists.sortAttack(firstStrikeBlockers);
for (final Card blocker : firstStrikeBlockers) {
final int damageNeeded = attacker.getKillDamage()
+ CombatUtil.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
+ ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
// if the total damage of the blockgang was not enough
// without but is enough with this blocker finish the
// blockgang
if (CombatUtil.totalDamageOfBlockers(attacker, blockGang) < damageNeeded
if (ComputerUtilCombat.totalDamageOfBlockers(attacker, blockGang) < damageNeeded
|| CombatUtil.needsBlockers(attacker) > blockGang.size()) {
blockGang.add(blocker);
if (CombatUtil.totalDamageOfBlockers(attacker, blockGang) >= damageNeeded) {
if (ComputerUtilCombat.totalDamageOfBlockers(attacker, blockGang) >= damageNeeded) {
currentAttackers.remove(attacker);
for (final Card b : blockGang) {
if (CombatUtil.canBlock(attacker, blocker, combat)) {
@@ -488,13 +488,13 @@ public class ComputerUtilBlock {
for (final Card blocker : usableBlockers) {
// Add an additional blocker if the current blockers are not
// enough and the new one would deal the remaining damage
final int currentDamage = CombatUtil.totalDamageOfBlockers(attacker, blockGang);
final int additionalDamage = CombatUtil.dealsDamageAsBlocker(attacker, blocker);
final int currentDamage = ComputerUtilCombat.totalDamageOfBlockers(attacker, blockGang);
final int additionalDamage = ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker);
final int absorbedDamage2 = blocker
.getEnoughDamageToKill(attacker.getNetCombatDamage(), attacker, true);
final int addedValue = CardFactoryUtil.evaluateCreature(blocker);
final int damageNeeded = attacker.getKillDamage()
+ CombatUtil.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
+ ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
if ((damageNeeded > currentDamage || CombatUtil.needsBlockers(attacker) > blockGang.size())
&& !(damageNeeded > currentDamage + additionalDamage)
// The attacker will be killed
@@ -502,7 +502,7 @@ public class ComputerUtilBlock {
// only one blocker can be killed
|| currentValue + addedValue - 50 <= CardFactoryUtil.evaluateCreature(attacker)
// or attacker is worth more
|| (lifeInDanger && CombatUtil.lifeInDanger(ai, combat)))
|| (lifeInDanger && ComputerUtilCombat.lifeInDanger(ai, combat)))
// or life is in danger
&& CombatUtil.canBlock(attacker, blocker, combat)) {
// this is needed for attackers that can't be blocked by
@@ -545,7 +545,7 @@ public class ComputerUtilBlock {
killingBlockers = ComputerUtilBlock.getKillingBlockers(attacker,
ComputerUtilBlock.getPossibleBlockers(attacker, ComputerUtilBlock.getBlockersLeft(), combat, true),
combat);
if ((killingBlockers.size() > 0) && CombatUtil.lifeInDanger(ai, combat)) {
if ((killingBlockers.size() > 0) && ComputerUtilCombat.lifeInDanger(ai, combat)) {
final Card blocker = CardFactoryUtil.getWorstCreatureAI(killingBlockers);
combat.addBlocker(attacker, blocker);
currentAttackers.remove(attacker);
@@ -579,7 +579,7 @@ public class ComputerUtilBlock {
chumpBlockers = ComputerUtilBlock
.getPossibleBlockers(attacker, ComputerUtilBlock.getBlockersLeft(), combat, true);
if ((chumpBlockers.size() > 0) && CombatUtil.lifeInDanger(ai, combat)) {
if ((chumpBlockers.size() > 0) && ComputerUtilCombat.lifeInDanger(ai, combat)) {
final Card blocker = CardFactoryUtil.getWorstCreatureAI(chumpBlockers);
combat.addBlocker(attacker, blocker);
currentAttackers.remove(attacker);
@@ -626,9 +626,9 @@ public class ComputerUtilBlock {
for (final Card blocker : chumpBlockers) {
// Add an additional blocker if the current blockers are not
// enough and the new one would suck some of the damage
if (CombatUtil.getAttack(attacker) > CombatUtil.totalShieldDamage(attacker, combat.getBlockers(attacker))
&& CombatUtil.shieldDamage(attacker, blocker) > 0
&& CombatUtil.canBlock(attacker, blocker, combat) && CombatUtil.lifeInDanger(ai, combat)) {
if (ComputerUtilCombat.getAttack(attacker) > ComputerUtilCombat.totalShieldDamage(attacker, combat.getBlockers(attacker))
&& ComputerUtilCombat.shieldDamage(attacker, blocker) > 0
&& CombatUtil.canBlock(attacker, blocker, combat) && ComputerUtilCombat.lifeInDanger(ai, combat)) {
combat.addBlocker(attacker, blocker);
}
}
@@ -667,11 +667,11 @@ public class ComputerUtilBlock {
safeBlockers = ComputerUtilBlock.getSafeBlockers(attacker, blockers, combat);
for (final Card blocker : safeBlockers) {
final int damageNeeded = attacker.getKillDamage()
+ CombatUtil.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
+ ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
// Add an additional blocker if the current blockers are not
// enough and the new one would deal additional damage
if ((damageNeeded > CombatUtil.totalDamageOfBlockers(attacker, combat.getBlockers(attacker)))
&& (CombatUtil.dealsDamageAsBlocker(attacker, blocker) > 0)
if ((damageNeeded > ComputerUtilCombat.totalDamageOfBlockers(attacker, combat.getBlockers(attacker)))
&& ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker) > 0
&& CombatUtil.canBlock(attacker, blocker, combat)) {
combat.addBlocker(attacker, blocker);
}
@@ -691,11 +691,11 @@ public class ComputerUtilBlock {
for (final Card blocker : safeBlockers) {
final int damageNeeded = attacker.getKillDamage()
+ CombatUtil.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
+ ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
// Add an additional blocker if the current blockers are not
// enough and the new one would deal the remaining damage
final int currentDamage = CombatUtil.totalDamageOfBlockers(attacker, combat.getBlockers(attacker));
final int additionalDamage = CombatUtil.dealsDamageAsBlocker(attacker, blocker);
final int currentDamage = ComputerUtilCombat.totalDamageOfBlockers(attacker, combat.getBlockers(attacker));
final int additionalDamage = ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker);
if ((damageNeeded > currentDamage)
&& !(damageNeeded > (currentDamage + additionalDamage))
&& ((CardFactoryUtil.evaluateCreature(blocker) + ComputerUtilBlock.getDiff()) < CardFactoryUtil
@@ -810,13 +810,13 @@ public class ComputerUtilBlock {
// == 1. choose best blocks first ==
combat = ComputerUtilBlock.makeGoodBlocks(combat);
combat = ComputerUtilBlock.makeGangBlocks(ai, combat);
if (CombatUtil.lifeInDanger(ai, combat)) {
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
combat = ComputerUtilBlock.makeTradeBlocks(ai, combat); // choose
// necessary
// trade blocks
}
// if life is in danger
if (CombatUtil.lifeInDanger(ai, combat)) {
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
combat = ComputerUtilBlock.makeChumpBlocks(ai, combat); // choose
// necessary
// chump blocks
@@ -824,18 +824,18 @@ public class ComputerUtilBlock {
// if life is still in danger
// Reinforce blockers blocking attackers with trample if life is still
// in danger
if (CombatUtil.lifeInDanger(ai, combat)) {
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
combat = ComputerUtilBlock.reinforceBlockersAgainstTrample(ai, combat);
}
// Support blockers not destroying the attacker with more blockers to
// try to kill the attacker
if (!CombatUtil.lifeInDanger(ai, combat)) {
if (!ComputerUtilCombat.lifeInDanger(ai, combat)) {
combat = ComputerUtilBlock.reinforceBlockersToKill(combat);
}
// == 2. If the AI life would still be in danger make a safer approach
// ==
if (CombatUtil.lifeInDanger(ai, combat)) {
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
lifeInDanger = true;
combat = ComputerUtilBlock.resetBlockers(combat, possibleBlockers); // reset
// every
@@ -846,7 +846,7 @@ public class ComputerUtilBlock {
// trade blocks
// if life is in danger
combat = ComputerUtilBlock.makeGoodBlocks(combat);
if (CombatUtil.lifeInDanger(ai, combat)) {
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
combat = ComputerUtilBlock.makeChumpBlocks(ai, combat); // choose
// necessary
// chump
@@ -855,7 +855,7 @@ public class ComputerUtilBlock {
// danger
// Reinforce blockers blocking attackers with trample if life is
// still in danger
if (CombatUtil.lifeInDanger(ai, combat)) {
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
combat = ComputerUtilBlock.reinforceBlockersAgainstTrample(ai, combat);
}
combat = ComputerUtilBlock.makeGangBlocks(ai, combat);
@@ -864,20 +864,20 @@ public class ComputerUtilBlock {
// == 3. If the AI life would be in serious danger make an even safer
// approach ==
if (CombatUtil.lifeInSeriousDanger(ai, combat)) {
if (ComputerUtilCombat.lifeInSeriousDanger(ai, combat)) {
combat = ComputerUtilBlock.resetBlockers(combat, possibleBlockers); // reset
// every
// block
// assignment
combat = ComputerUtilBlock.makeChumpBlocks(ai, combat); // choose chump
// blocks
if (CombatUtil.lifeInDanger(ai, combat)) {
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
combat = ComputerUtilBlock.makeTradeBlocks(ai, combat); // choose
// necessary
// trade
}
if (!CombatUtil.lifeInDanger(ai, combat)) {
if (!ComputerUtilCombat.lifeInDanger(ai, combat)) {
combat = ComputerUtilBlock.makeGoodBlocks(combat);
}
// Reinforce blockers blocking attackers with trample if life is

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff