mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
- Moved all AI related functions in CombatUtil to the new class ComputerUtilCombat.
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -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/AiInputCommon.java svneol=native#text/plain
|
||||||
src/main/java/forge/game/ai/ComputerUtil.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/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/ComputerUtilCost.java -text
|
||||||
src/main/java/forge/game/ai/ComputerUtilMana.java -text
|
src/main/java/forge/game/ai/ComputerUtilMana.java -text
|
||||||
src/main/java/forge/game/event/BlockerAssignedEvent.java -text
|
src/main/java/forge/game/event/BlockerAssignedEvent.java -text
|
||||||
|
|||||||
@@ -30,12 +30,12 @@ import forge.card.spellability.SpellAbility;
|
|||||||
import forge.card.spellability.SpellPermanent;
|
import forge.card.spellability.SpellPermanent;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
import forge.game.GlobalRuleChange;
|
import forge.game.GlobalRuleChange;
|
||||||
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.ai.ComputerUtil;
|
import forge.game.ai.ComputerUtil;
|
||||||
import forge.game.ai.ComputerUtilBlock;
|
import forge.game.ai.ComputerUtilBlock;
|
||||||
import forge.game.ai.ComputerUtilCost;
|
import forge.game.ai.ComputerUtilCost;
|
||||||
import forge.game.ai.ComputerUtilMana;
|
import forge.game.ai.ComputerUtilMana;
|
||||||
import forge.game.phase.Combat;
|
import forge.game.phase.Combat;
|
||||||
import forge.game.phase.CombatUtil;
|
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -495,7 +495,7 @@ public class ChangeZoneAi extends SpellAiLogic {
|
|||||||
}
|
}
|
||||||
combat = ComputerUtilBlock.getBlockers(ai, combat, ai.getCreaturesInPlay());
|
combat = ComputerUtilBlock.getBlockers(ai, combat, ai.getCreaturesInPlay());
|
||||||
|
|
||||||
if (CombatUtil.lifeInDanger(ai, combat)) {
|
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||||
// need something AI can cast now
|
// need something AI can cast now
|
||||||
CardLists.sortByEvaluateCreature(list);
|
CardLists.sortByEvaluateCreature(list);
|
||||||
for (Card c : list) {
|
for (Card c : list) {
|
||||||
@@ -741,7 +741,7 @@ public class ChangeZoneAi extends SpellAiLogic {
|
|||||||
CardLists.sortByEvaluateCreature(combatants);
|
CardLists.sortByEvaluateCreature(combatants);
|
||||||
|
|
||||||
for (final Card c : 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);
|
tgt.addTarget(c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import forge.card.abilityfactory.SpellAiLogic;
|
|||||||
import forge.card.cost.Cost;
|
import forge.card.cost.Cost;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.ai.ComputerUtilCost;
|
import forge.game.ai.ComputerUtilCost;
|
||||||
import forge.game.phase.CombatUtil;
|
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -112,7 +112,7 @@ public class ChooseSourceAi extends SpellAiLogic {
|
|||||||
if (!c.isAttacking(ai) || !Singletons.getModel().getGame().getCombat().isUnblocked(c)) {
|
if (!c.isAttacking(ai) || !Singletons.getModel().getGame().getCombat().isUnblocked(c)) {
|
||||||
return false;
|
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()) {
|
if (choices.isEmpty()) {
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import forge.card.cardfactory.CardFactoryUtil;
|
|||||||
import forge.card.cost.Cost;
|
import forge.card.cost.Cost;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.ai.ComputerUtilCost;
|
import forge.game.ai.ComputerUtilCost;
|
||||||
import forge.game.phase.CombatUtil;
|
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -68,13 +68,13 @@ public class DamagePreventAi extends SpellAiLogic {
|
|||||||
for (final Object o : objects) {
|
for (final Object o : objects) {
|
||||||
if (o instanceof Card) {
|
if (o instanceof Card) {
|
||||||
final Card c = (Card) o;
|
final Card c = (Card) o;
|
||||||
flag |= CombatUtil.combatantWouldBeDestroyed(c);
|
flag |= ComputerUtilCombat.combatantWouldBeDestroyed(c);
|
||||||
} else if (o instanceof Player) {
|
} else if (o instanceof Player) {
|
||||||
// Don't need to worry about Combat Damage during AI's turn
|
// Don't need to worry about Combat Damage during AI's turn
|
||||||
final Player p = (Player) o;
|
final Player p = (Player) o;
|
||||||
if (!handler.isPlayerTurn(p)) {
|
if (!handler.isPlayerTurn(p)) {
|
||||||
flag |= (p.isComputer() && ((CombatUtil.wouldLoseLife(ai, Singletons.getModel().getGame().getCombat()) && sa
|
flag |= (p.isComputer() && ((ComputerUtilCombat.wouldLoseLife(ai, Singletons.getModel().getGame().getCombat()) && sa
|
||||||
.isAbility()) || CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())));
|
.isAbility()) || ComputerUtilCombat.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,8 +117,8 @@ public class DamagePreventAi extends SpellAiLogic {
|
|||||||
|
|
||||||
} // Protect combatants
|
} // Protect combatants
|
||||||
else if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
|
else if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
|
||||||
if (sa.canTarget(ai) && CombatUtil.wouldLoseLife(ai, Singletons.getModel().getGame().getCombat())
|
if (sa.canTarget(ai) && ComputerUtilCombat.wouldLoseLife(ai, Singletons.getModel().getGame().getCombat())
|
||||||
&& (CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat()) || sa.isAbility())
|
&& (ComputerUtilCombat.lifeInDanger(ai, Singletons.getModel().getGame().getCombat()) || sa.isAbility())
|
||||||
&& Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(ai.getOpponent())) {
|
&& Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(ai.getOpponent())) {
|
||||||
tgt.addTarget(ai);
|
tgt.addTarget(ai);
|
||||||
chance = true;
|
chance = true;
|
||||||
@@ -134,7 +134,7 @@ public class DamagePreventAi extends SpellAiLogic {
|
|||||||
CardLists.sortByEvaluateCreature(combatants);
|
CardLists.sortByEvaluateCreature(combatants);
|
||||||
|
|
||||||
for (final Card c : combatants) {
|
for (final Card c : combatants) {
|
||||||
if (CombatUtil.combatantWouldBeDestroyed(c)) {
|
if (ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
|
||||||
tgt.addTarget(c);
|
tgt.addTarget(c);
|
||||||
chance = true;
|
chance = true;
|
||||||
break;
|
break;
|
||||||
@@ -195,7 +195,7 @@ public class DamagePreventAi extends SpellAiLogic {
|
|||||||
CardLists.sortByEvaluateCreature(combatants);
|
CardLists.sortByEvaluateCreature(combatants);
|
||||||
if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
|
if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
|
||||||
for (final Card c : combatants) {
|
for (final Card c : combatants) {
|
||||||
if (CombatUtil.combatantWouldBeDestroyed(c)) {
|
if (ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
|
||||||
tgt.addTarget(c);
|
tgt.addTarget(c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import forge.card.cardfactory.CardFactoryUtil;
|
|||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
import forge.game.GameState;
|
import forge.game.GameState;
|
||||||
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.phase.CombatUtil;
|
import forge.game.phase.CombatUtil;
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
@@ -50,7 +51,7 @@ public class EffectAi extends SpellAiLogic {
|
|||||||
if (game.getPhaseHandler().isPreventCombatDamageThisTurn()) {
|
if (game.getPhaseHandler().isPreventCombatDamageThisTurn()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!CombatUtil.lifeInDanger(ai, game.getCombat())) {
|
if (!ComputerUtilCombat.lifeInDanger(ai, game.getCombat())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final Target tgt = sa.getTarget();
|
final Target tgt = sa.getTarget();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ package forge.card.abilityfactory.ai;
|
|||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.abilityfactory.SpellAiLogic;
|
import forge.card.abilityfactory.SpellAiLogic;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.game.phase.CombatUtil;
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ public class FogAi extends SpellAiLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cast it if life is in danger
|
// Cast it if life is in danger
|
||||||
return CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat());
|
return ComputerUtilCombat.lifeInDanger(ai, Singletons.getModel().getGame().getCombat());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import forge.card.cost.Cost;
|
|||||||
import forge.card.spellability.AbilitySub;
|
import forge.card.spellability.AbilitySub;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.ai.ComputerUtil;
|
import forge.game.ai.ComputerUtil;
|
||||||
import forge.game.ai.ComputerUtilCost;
|
import forge.game.ai.ComputerUtilCost;
|
||||||
import forge.game.ai.ComputerUtilMana;
|
import forge.game.ai.ComputerUtilMana;
|
||||||
import forge.game.phase.CombatUtil;
|
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
@@ -67,7 +67,7 @@ public class LifeGainAi extends SpellAiLogic {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean lifeCritical = life <= 5;
|
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()));
|
.lifeInDanger(ai, Singletons.getModel().getGame().getCombat()));
|
||||||
|
|
||||||
if (abCost != null && !lifeCritical) {
|
if (abCost != null && !lifeCritical) {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import forge.card.abilityfactory.SpellAiLogic;
|
|||||||
import forge.card.cardfactory.CardFactoryUtil;
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.phase.CombatUtil;
|
import forge.game.phase.CombatUtil;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -72,10 +73,10 @@ public class MustBlockAi extends SpellAiLogic {
|
|||||||
if (!CombatUtil.canBlock(definedAttacker, c)) {
|
if (!CombatUtil.canBlock(definedAttacker, c)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (CombatUtil.canDestroyAttacker(definedAttacker, c, null, false)) {
|
if (ComputerUtilCombat.canDestroyAttacker(definedAttacker, c, null, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!CombatUtil.canDestroyBlocker(c, definedAttacker, null, false)) {
|
if (!ComputerUtilCombat.canDestroyBlocker(c, definedAttacker, null, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
c.setTapped(tapped);
|
c.setTapped(tapped);
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ import forge.card.cardfactory.CardFactoryUtil;
|
|||||||
import forge.card.cost.Cost;
|
import forge.card.cost.Cost;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.ai.ComputerUtilCost;
|
import forge.game.ai.ComputerUtilCost;
|
||||||
import forge.game.phase.CombatUtil;
|
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -90,14 +90,14 @@ public class ProtectAi extends SpellAiLogic {
|
|||||||
// is the creature blocking and unable to destroy the attacker
|
// is the creature blocking and unable to destroy the attacker
|
||||||
// or would be destroyed itself?
|
// or would be destroyed itself?
|
||||||
if (c.isBlocking()
|
if (c.isBlocking()
|
||||||
&& (CombatUtil.blockerWouldBeDestroyed(c))) {
|
&& (ComputerUtilCombat.blockerWouldBeDestroyed(c))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// is the creature in blocked and the blocker would survive
|
// is the creature in blocked and the blocker would survive
|
||||||
if (Singletons.getModel().getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)
|
if (Singletons.getModel().getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)
|
||||||
&& Singletons.getModel().getGame().getCombat().isAttacking(c) && Singletons.getModel().getGame().getCombat().isBlocked(c)
|
&& 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import forge.card.abilityfactory.AbilityFactory;
|
|||||||
import forge.card.abilityfactory.SpellAiLogic;
|
import forge.card.abilityfactory.SpellAiLogic;
|
||||||
import forge.card.cardfactory.CardFactoryUtil;
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.phase.Combat;
|
import forge.game.phase.Combat;
|
||||||
import forge.game.phase.CombatUtil;
|
import forge.game.phase.CombatUtil;
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
@@ -180,7 +181,7 @@ public abstract class PumpAiBase extends SpellAiLogic {
|
|||||||
&& !CardLists.getKeyword(Singletons.getModel().getGame().getCombat().getAttackerList(), "Flying").isEmpty()
|
&& !CardLists.getKeyword(Singletons.getModel().getGame().getCombat().getAttackerList(), "Flying").isEmpty()
|
||||||
&& !card.hasKeyword("Reach")
|
&& !card.hasKeyword("Reach")
|
||||||
&& CombatUtil.canBlock(card)
|
&& CombatUtil.canBlock(card)
|
||||||
&& CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())) {
|
&& ComputerUtilCombat.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Predicate<Card> flyingOrReach = Predicates.or(CardPredicates.hasKeyword("Flying"), CardPredicates.hasKeyword("Reach"));
|
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)
|
&& ph.getPhase().equals(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)
|
||||||
&& !CardLists.getKeyword(Singletons.getModel().getGame().getCombat().getAttackerList(), "Horsemanship").isEmpty()
|
&& !CardLists.getKeyword(Singletons.getModel().getGame().getCombat().getAttackerList(), "Horsemanship").isEmpty()
|
||||||
&& CombatUtil.canBlock(card)
|
&& CombatUtil.canBlock(card)
|
||||||
&& CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())) {
|
&& ComputerUtilCombat.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
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();
|
List<Card> attackers = combat.getAttackers();
|
||||||
for (Card attacker : attackers) {
|
for (Card attacker : attackers) {
|
||||||
if (CombatUtil.canBlock(attacker, card, combat)
|
if (CombatUtil.canBlock(attacker, card, combat)
|
||||||
&& !CombatUtil.canDestroyAttacker(attacker, card, combat, false)) {
|
&& !ComputerUtilCombat.canDestroyAttacker(attacker, card, combat, false)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,7 +232,7 @@ public abstract class PumpAiBase extends SpellAiLogic {
|
|||||||
List<Card> blockers = opp.getCreaturesInPlay();
|
List<Card> blockers = opp.getCreaturesInPlay();
|
||||||
for (Card blocker : blockers) {
|
for (Card blocker : blockers) {
|
||||||
if (CombatUtil.canBlock(card, blocker, combat)
|
if (CombatUtil.canBlock(card, blocker, combat)
|
||||||
&& !CombatUtil.canDestroyBlocker(blocker, card, combat, false)) {
|
&& !ComputerUtilCombat.canDestroyBlocker(blocker, card, combat, false)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -407,13 +408,13 @@ public abstract class PumpAiBase extends SpellAiLogic {
|
|||||||
// is the creature blocking and unable to destroy the attacker
|
// is the creature blocking and unable to destroy the attacker
|
||||||
// or would be destroyed itself?
|
// or would be destroyed itself?
|
||||||
if (phase.is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) && c.isBlocking()) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
List<Card> blockedBy = Singletons.getModel().getGame().getCombat().getAttackersBlockedBy(c);
|
List<Card> blockedBy = Singletons.getModel().getGame().getCombat().getAttackersBlockedBy(c);
|
||||||
// For now, Only care the first creature blocked by a card.
|
// For now, Only care the first creature blocked by a card.
|
||||||
// TODO Add in better BlockAdditional support
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -431,7 +432,7 @@ public abstract class PumpAiBase extends SpellAiLogic {
|
|||||||
&& Singletons.getModel().getGame().getCombat().isBlocked(c)
|
&& Singletons.getModel().getGame().getCombat().isBlocked(c)
|
||||||
&& Singletons.getModel().getGame().getCombat().getBlockers(c) != null
|
&& Singletons.getModel().getGame().getCombat().getBlockers(c) != null
|
||||||
&& !Singletons.getModel().getGame().getCombat().getBlockers(c).isEmpty()
|
&& !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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,7 +448,7 @@ public abstract class PumpAiBase extends SpellAiLogic {
|
|||||||
&& c.isBlocking()
|
&& c.isBlocking()
|
||||||
&& defense > 0
|
&& defense > 0
|
||||||
&& attackerHasTrample
|
&& attackerHasTrample
|
||||||
&& (sa.isAbility() || CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat()))) {
|
&& (sa.isAbility() || ComputerUtilCombat.lifeInDanger(ai, Singletons.getModel().getGame().getCombat()))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import forge.card.abilityfactory.AbilityFactory;
|
|||||||
import forge.card.cardfactory.CardFactoryUtil;
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.ai.ComputerUtil;
|
import forge.game.ai.ComputerUtil;
|
||||||
import forge.game.phase.CombatUtil;
|
import forge.game.phase.CombatUtil;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
@@ -90,7 +91,7 @@ public class PumpAllAi extends PumpAiBase {
|
|||||||
totalPower += Math.min(c.getNetAttack(), power * -1);
|
totalPower += Math.min(c.getNetAttack(), power * -1);
|
||||||
if (phase == PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY
|
if (phase == PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY
|
||||||
&& Singletons.getModel().getGame().getCombat().getUnblockedAttackers().contains(c)) {
|
&& 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;
|
return true;
|
||||||
}
|
}
|
||||||
totalPower += Math.min(c.getNetAttack(), power * -1);
|
totalPower += Math.min(c.getNetAttack(), power * -1);
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ import forge.card.cardfactory.CardFactoryUtil;
|
|||||||
import forge.card.cost.Cost;
|
import forge.card.cost.Cost;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.ai.ComputerUtilCost;
|
import forge.game.ai.ComputerUtilCost;
|
||||||
import forge.game.phase.CombatUtil;
|
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -95,7 +95,7 @@ public class RegenerateAi extends SpellAiLogic {
|
|||||||
|
|
||||||
for (final Card c : list) {
|
for (final Card c : list) {
|
||||||
if (c.getShield() == 0) {
|
if (c.getShield() == 0) {
|
||||||
flag |= CombatUtil.combatantWouldBeDestroyed(c);
|
flag |= ComputerUtilCombat.combatantWouldBeDestroyed(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ public class RegenerateAi extends SpellAiLogic {
|
|||||||
CardLists.sortByEvaluateCreature(combatants);
|
CardLists.sortByEvaluateCreature(combatants);
|
||||||
|
|
||||||
for (final Card c : combatants) {
|
for (final Card c : combatants) {
|
||||||
if ((c.getShield() == 0) && CombatUtil.combatantWouldBeDestroyed(c)) {
|
if ((c.getShield() == 0) && ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
|
||||||
tgt.addTarget(c);
|
tgt.addTarget(c);
|
||||||
chance = true;
|
chance = true;
|
||||||
break;
|
break;
|
||||||
@@ -190,7 +190,7 @@ public class RegenerateAi extends SpellAiLogic {
|
|||||||
CardLists.sortByEvaluateCreature(combatants);
|
CardLists.sortByEvaluateCreature(combatants);
|
||||||
if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
|
if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
|
||||||
for (final Card c : combatants) {
|
for (final Card c : combatants) {
|
||||||
if ((c.getShield() == 0) && CombatUtil.combatantWouldBeDestroyed(c)) {
|
if ((c.getShield() == 0) && ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
|
||||||
tgt.addTarget(c);
|
tgt.addTarget(c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import forge.card.abilityfactory.AbilityFactory;
|
|||||||
import forge.card.abilityfactory.SpellAiLogic;
|
import forge.card.abilityfactory.SpellAiLogic;
|
||||||
import forge.card.cost.Cost;
|
import forge.card.cost.Cost;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.ai.ComputerUtilCost;
|
import forge.game.ai.ComputerUtilCost;
|
||||||
import forge.game.phase.CombatUtil;
|
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -68,7 +68,7 @@ public class RegenerateAllAi extends SpellAiLogic {
|
|||||||
final List<Card> combatants = CardLists.filter(list, CardPredicates.Presets.CREATURES);
|
final List<Card> combatants = CardLists.filter(list, CardPredicates.Presets.CREATURES);
|
||||||
|
|
||||||
for (final Card c : combatants) {
|
for (final Card c : combatants) {
|
||||||
if (c.getShield() == 0 && CombatUtil.combatantWouldBeDestroyed(c)) {
|
if (c.getShield() == 0 && ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
|
||||||
numSaved++;
|
numSaved++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import forge.Card;
|
|||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.abilityfactory.SpellAiLogic;
|
import forge.card.abilityfactory.SpellAiLogic;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.ai.ComputerUtil;
|
import forge.game.ai.ComputerUtil;
|
||||||
import forge.game.phase.CombatUtil;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
|
||||||
public class StoreSVarAi extends SpellAiLogic {
|
public class StoreSVarAi extends SpellAiLogic {
|
||||||
@@ -16,7 +16,7 @@ public class StoreSVarAi extends SpellAiLogic {
|
|||||||
|
|
||||||
final Card source = sa.getSourceCard();
|
final Card source = sa.getSourceCard();
|
||||||
if (ComputerUtil.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()))) {
|
|| (ai.getLife() > 5 && !ComputerUtilCombat.lifeInSeriousDanger(ai, Singletons.getModel().getGame().getCombat()))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import forge.card.cardfactory.CardFactoryUtil;
|
|||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.spellability.SpellAbilityStackInstance;
|
import forge.card.spellability.SpellAbilityStackInstance;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
import forge.game.phase.CombatUtil;
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.GuiChoose;
|
import forge.gui.GuiChoose;
|
||||||
@@ -178,7 +178,7 @@ public class ChooseSourceEffect extends SpellEffect {
|
|||||||
if (!c.isAttacking(ai) || !Singletons.getModel().getGame().getCombat().isUnblocked(c)) {
|
if (!c.isAttacking(ai) || !Singletons.getModel().getGame().getCombat().isUnblocked(c)) {
|
||||||
return false;
|
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));
|
chosen.add(CardFactoryUtil.getBestCreatureAI(sourcesToChooseFrom));
|
||||||
|
|||||||
@@ -140,15 +140,15 @@ public class AiAttackController {
|
|||||||
public final boolean isEffectiveAttacker(final Player ai, final Card attacker, final Combat combat) {
|
public final boolean isEffectiveAttacker(final Player ai, final Card attacker, final Combat combat) {
|
||||||
|
|
||||||
// if the attacker will die when attacking don't attack
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Player opp = ai.getOpponent();
|
final Player opp = ai.getOpponent();
|
||||||
if (CombatUtil.damageIfUnblocked(attacker, opp, combat) > 0) {
|
if (ComputerUtilCombat.damageIfUnblocked(attacker, opp, combat) > 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (CombatUtil.poisonIfUnblocked(attacker, opp) > 0) {
|
if (ComputerUtilCombat.poisonIfUnblocked(attacker, opp) > 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (this.attackers.size() == 1 && attacker.hasKeyword("Exalted")) {
|
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);
|
final List<Card> controlledByCompy = ai.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES);
|
||||||
for (final Card c : controlledByCompy) {
|
for (final Card c : controlledByCompy) {
|
||||||
for (final Trigger trigger : c.getTriggers()) {
|
for (final Trigger trigger : c.getTriggers()) {
|
||||||
if (CombatUtil.combatTriggerWillTrigger(attacker, null, trigger, combat)) {
|
if (ComputerUtilCombat.combatTriggerWillTrigger(attacker, null, trigger, combat)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,8 +350,8 @@ public class AiAttackController {
|
|||||||
blockersLeft--;
|
blockersLeft--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
totalAttack += CombatUtil.damageIfUnblocked(attacker, ai, null);
|
totalAttack += ComputerUtilCombat.damageIfUnblocked(attacker, ai, null);
|
||||||
totalPoison += CombatUtil.poisonIfUnblocked(attacker, ai);
|
totalPoison += ComputerUtilCombat.poisonIfUnblocked(attacker, ai);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalAttack > 0 && ai.getLife() <= totalAttack
|
if (totalAttack > 0 && ai.getLife() <= totalAttack
|
||||||
@@ -425,12 +425,12 @@ public class AiAttackController {
|
|||||||
}
|
}
|
||||||
unblockedAttackers.addAll(remainingAttackers);
|
unblockedAttackers.addAll(remainingAttackers);
|
||||||
|
|
||||||
if ((CombatUtil.sumDamageIfUnblocked(remainingAttackers, opp) >= opp.getLife())
|
if ((ComputerUtilCombat.sumDamageIfUnblocked(remainingAttackers, opp) >= opp.getLife())
|
||||||
&& !((opp.cantLoseForZeroOrLessLife() || ai.cantWin()) && (opp.getLife() < 1))) {
|
&& !((opp.cantLoseForZeroOrLessLife() || ai.cantWin()) && (opp.getLife() < 1))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CombatUtil.sumPoisonIfUnblocked(remainingAttackers, opp) >= (10 - opp.getPoisonCounters())) {
|
if (ComputerUtilCombat.sumPoisonIfUnblocked(remainingAttackers, opp) >= (10 - opp.getPoisonCounters())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -621,7 +621,7 @@ public class AiAttackController {
|
|||||||
if (CombatUtil.canAttackNextTurn(pCard)) {
|
if (CombatUtil.canAttackNextTurn(pCard)) {
|
||||||
candidateAttackers.add(pCard);
|
candidateAttackers.add(pCard);
|
||||||
if (pCard.getNetCombatDamage() > 0) {
|
if (pCard.getNetCombatDamage() > 0) {
|
||||||
candidateUnblockedDamage += CombatUtil.damageIfUnblocked(pCard, opp, null);
|
candidateUnblockedDamage += ComputerUtilCombat.damageIfUnblocked(pCard, opp, null);
|
||||||
computerForces += 1;
|
computerForces += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -717,7 +717,7 @@ public class AiAttackController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isUnblockableCreature) {
|
if (isUnblockableCreature) {
|
||||||
unblockableDamage += CombatUtil.damageIfUnblocked(attacker, opp, combat);
|
unblockableDamage += ComputerUtilCombat.damageIfUnblocked(attacker, opp, combat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (final Card attacker : nextTurnAttackers) {
|
for (final Card attacker : nextTurnAttackers) {
|
||||||
@@ -731,7 +731,7 @@ public class AiAttackController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isUnblockableCreature) {
|
if (isUnblockableCreature) {
|
||||||
nextUnblockableDamage += CombatUtil.damageIfUnblocked(attacker, opp, null);
|
nextUnblockableDamage += ComputerUtilCombat.damageIfUnblocked(attacker, opp, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (unblockableDamage > 0 && !opp.cantLoseForZeroOrLessLife()
|
if (unblockableDamage > 0 && !opp.cantLoseForZeroOrLessLife()
|
||||||
@@ -785,7 +785,7 @@ public class AiAttackController {
|
|||||||
for (int i = 0; i < attackersLeft.size(); i++) {
|
for (int i = 0; i < attackersLeft.size(); i++) {
|
||||||
final Card attacker = attackersLeft.get(i);
|
final Card attacker = attackersLeft.get(i);
|
||||||
if (this.aiAggression < 5 && !attacker.hasFirstStrike() && !attacker.hasDoubleStrike()
|
if (this.aiAggression < 5 && !attacker.hasFirstStrike() && !attacker.hasDoubleStrike()
|
||||||
&& CombatUtil.getTotalFirstStrikeBlockPower(attacker, ai.getOpponent())
|
&& ComputerUtilCombat.getTotalFirstStrikeBlockPower(attacker, ai.getOpponent())
|
||||||
>= attacker.getKillDamage()) {
|
>= attacker.getKillDamage()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -803,7 +803,7 @@ public class AiAttackController {
|
|||||||
CardLists.sortAttackLowFirst(attacking);
|
CardLists.sortAttackLowFirst(attacking);
|
||||||
for (Card atta : attacking) {
|
for (Card atta : attacking) {
|
||||||
if (attackNum >= blockNum || !CombatUtil.canBeBlocked(attacker, this.blockers)) {
|
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)) {
|
} else if (CombatUtil.canBeBlocked(attacker, this.blockers)) {
|
||||||
attackNum++;
|
attackNum++;
|
||||||
}
|
}
|
||||||
@@ -901,7 +901,7 @@ public class AiAttackController {
|
|||||||
if ((isWorthLessThanAllKillers || canKillAllDangerous || numberOfPossibleBlockers < 2)
|
if ((isWorthLessThanAllKillers || canKillAllDangerous || numberOfPossibleBlockers < 2)
|
||||||
&& CombatUtil.canBlock(attacker, defender)) {
|
&& CombatUtil.canBlock(attacker, defender)) {
|
||||||
numberOfPossibleBlockers += 1;
|
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)) {
|
&& !(attacker.hasKeyword("Undying") && attacker.getCounters(CounterType.P1P1) == 0)) {
|
||||||
canBeKilledByOne = true; // there is a single creature on
|
canBeKilledByOne = true; // there is a single creature on
|
||||||
// the battlefield that can kill
|
// the battlefield that can kill
|
||||||
@@ -915,7 +915,7 @@ public class AiAttackController {
|
|||||||
}
|
}
|
||||||
// see if this attacking creature can destroy this defender, if
|
// see if this attacking creature can destroy this defender, if
|
||||||
// not record that it can't kill everything
|
// 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;
|
canKillAll = false;
|
||||||
if (!canKillAllDangerous) {
|
if (!canKillAllDangerous) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -1006,7 +1006,7 @@ public class ComputerUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
combat = ComputerUtilBlock.getBlockers(ai, combat, ai.getCreaturesInPlay());
|
combat = ComputerUtilBlock.getBlockers(ai, combat, ai.getCreaturesInPlay());
|
||||||
if (!CombatUtil.lifeInDanger(ai, combat)) {
|
if (!ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||||
// Otherwise, return false. Do not play now.
|
// Otherwise, return false. Do not play now.
|
||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ public class ComputerUtilBlock {
|
|||||||
final List<Card> blockers = new ArrayList<Card>();
|
final List<Card> blockers = new ArrayList<Card>();
|
||||||
|
|
||||||
for (final Card b : blockersLeft) {
|
for (final Card b : blockersLeft) {
|
||||||
if (!CombatUtil.canDestroyBlocker(b, attacker, combat, false)) {
|
if (!ComputerUtilCombat.canDestroyBlocker(b, attacker, combat, false)) {
|
||||||
blockers.add(b);
|
blockers.add(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,7 +259,7 @@ public class ComputerUtilBlock {
|
|||||||
final List<Card> blockers = new ArrayList<Card>();
|
final List<Card> blockers = new ArrayList<Card>();
|
||||||
|
|
||||||
for (final Card b : blockersLeft) {
|
for (final Card b : blockersLeft) {
|
||||||
if (CombatUtil.canDestroyAttacker(attacker, b, combat, false)) {
|
if (ComputerUtilCombat.canDestroyAttacker(attacker, b, combat, false)) {
|
||||||
blockers.add(b);
|
blockers.add(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,7 +293,7 @@ public class ComputerUtilBlock {
|
|||||||
return firstAttacker;
|
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
|
// TODO Add creatures attacking Planeswalkers in order of which we want
|
||||||
// to protect
|
// to protect
|
||||||
@@ -427,14 +427,14 @@ public class ComputerUtilBlock {
|
|||||||
CardLists.sortAttack(firstStrikeBlockers);
|
CardLists.sortAttack(firstStrikeBlockers);
|
||||||
for (final Card blocker : firstStrikeBlockers) {
|
for (final Card blocker : firstStrikeBlockers) {
|
||||||
final int damageNeeded = attacker.getKillDamage()
|
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
|
// if the total damage of the blockgang was not enough
|
||||||
// without but is enough with this blocker finish the
|
// without but is enough with this blocker finish the
|
||||||
// blockgang
|
// blockgang
|
||||||
if (CombatUtil.totalDamageOfBlockers(attacker, blockGang) < damageNeeded
|
if (ComputerUtilCombat.totalDamageOfBlockers(attacker, blockGang) < damageNeeded
|
||||||
|| CombatUtil.needsBlockers(attacker) > blockGang.size()) {
|
|| CombatUtil.needsBlockers(attacker) > blockGang.size()) {
|
||||||
blockGang.add(blocker);
|
blockGang.add(blocker);
|
||||||
if (CombatUtil.totalDamageOfBlockers(attacker, blockGang) >= damageNeeded) {
|
if (ComputerUtilCombat.totalDamageOfBlockers(attacker, blockGang) >= damageNeeded) {
|
||||||
currentAttackers.remove(attacker);
|
currentAttackers.remove(attacker);
|
||||||
for (final Card b : blockGang) {
|
for (final Card b : blockGang) {
|
||||||
if (CombatUtil.canBlock(attacker, blocker, combat)) {
|
if (CombatUtil.canBlock(attacker, blocker, combat)) {
|
||||||
@@ -488,13 +488,13 @@ public class ComputerUtilBlock {
|
|||||||
for (final Card blocker : usableBlockers) {
|
for (final Card blocker : usableBlockers) {
|
||||||
// Add an additional blocker if the current blockers are not
|
// Add an additional blocker if the current blockers are not
|
||||||
// enough and the new one would deal the remaining damage
|
// enough and the new one would deal the remaining damage
|
||||||
final int currentDamage = CombatUtil.totalDamageOfBlockers(attacker, blockGang);
|
final int currentDamage = ComputerUtilCombat.totalDamageOfBlockers(attacker, blockGang);
|
||||||
final int additionalDamage = CombatUtil.dealsDamageAsBlocker(attacker, blocker);
|
final int additionalDamage = ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker);
|
||||||
final int absorbedDamage2 = blocker
|
final int absorbedDamage2 = blocker
|
||||||
.getEnoughDamageToKill(attacker.getNetCombatDamage(), attacker, true);
|
.getEnoughDamageToKill(attacker.getNetCombatDamage(), attacker, true);
|
||||||
final int addedValue = CardFactoryUtil.evaluateCreature(blocker);
|
final int addedValue = CardFactoryUtil.evaluateCreature(blocker);
|
||||||
final int damageNeeded = attacker.getKillDamage()
|
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())
|
if ((damageNeeded > currentDamage || CombatUtil.needsBlockers(attacker) > blockGang.size())
|
||||||
&& !(damageNeeded > currentDamage + additionalDamage)
|
&& !(damageNeeded > currentDamage + additionalDamage)
|
||||||
// The attacker will be killed
|
// The attacker will be killed
|
||||||
@@ -502,7 +502,7 @@ public class ComputerUtilBlock {
|
|||||||
// only one blocker can be killed
|
// only one blocker can be killed
|
||||||
|| currentValue + addedValue - 50 <= CardFactoryUtil.evaluateCreature(attacker)
|
|| currentValue + addedValue - 50 <= CardFactoryUtil.evaluateCreature(attacker)
|
||||||
// or attacker is worth more
|
// or attacker is worth more
|
||||||
|| (lifeInDanger && CombatUtil.lifeInDanger(ai, combat)))
|
|| (lifeInDanger && ComputerUtilCombat.lifeInDanger(ai, combat)))
|
||||||
// or life is in danger
|
// or life is in danger
|
||||||
&& CombatUtil.canBlock(attacker, blocker, combat)) {
|
&& CombatUtil.canBlock(attacker, blocker, combat)) {
|
||||||
// this is needed for attackers that can't be blocked by
|
// this is needed for attackers that can't be blocked by
|
||||||
@@ -545,7 +545,7 @@ public class ComputerUtilBlock {
|
|||||||
killingBlockers = ComputerUtilBlock.getKillingBlockers(attacker,
|
killingBlockers = ComputerUtilBlock.getKillingBlockers(attacker,
|
||||||
ComputerUtilBlock.getPossibleBlockers(attacker, ComputerUtilBlock.getBlockersLeft(), combat, true),
|
ComputerUtilBlock.getPossibleBlockers(attacker, ComputerUtilBlock.getBlockersLeft(), combat, true),
|
||||||
combat);
|
combat);
|
||||||
if ((killingBlockers.size() > 0) && CombatUtil.lifeInDanger(ai, combat)) {
|
if ((killingBlockers.size() > 0) && ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||||
final Card blocker = CardFactoryUtil.getWorstCreatureAI(killingBlockers);
|
final Card blocker = CardFactoryUtil.getWorstCreatureAI(killingBlockers);
|
||||||
combat.addBlocker(attacker, blocker);
|
combat.addBlocker(attacker, blocker);
|
||||||
currentAttackers.remove(attacker);
|
currentAttackers.remove(attacker);
|
||||||
@@ -579,7 +579,7 @@ public class ComputerUtilBlock {
|
|||||||
|
|
||||||
chumpBlockers = ComputerUtilBlock
|
chumpBlockers = ComputerUtilBlock
|
||||||
.getPossibleBlockers(attacker, ComputerUtilBlock.getBlockersLeft(), combat, true);
|
.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);
|
final Card blocker = CardFactoryUtil.getWorstCreatureAI(chumpBlockers);
|
||||||
combat.addBlocker(attacker, blocker);
|
combat.addBlocker(attacker, blocker);
|
||||||
currentAttackers.remove(attacker);
|
currentAttackers.remove(attacker);
|
||||||
@@ -626,9 +626,9 @@ public class ComputerUtilBlock {
|
|||||||
for (final Card blocker : chumpBlockers) {
|
for (final Card blocker : chumpBlockers) {
|
||||||
// Add an additional blocker if the current blockers are not
|
// Add an additional blocker if the current blockers are not
|
||||||
// enough and the new one would suck some of the damage
|
// enough and the new one would suck some of the damage
|
||||||
if (CombatUtil.getAttack(attacker) > CombatUtil.totalShieldDamage(attacker, combat.getBlockers(attacker))
|
if (ComputerUtilCombat.getAttack(attacker) > ComputerUtilCombat.totalShieldDamage(attacker, combat.getBlockers(attacker))
|
||||||
&& CombatUtil.shieldDamage(attacker, blocker) > 0
|
&& ComputerUtilCombat.shieldDamage(attacker, blocker) > 0
|
||||||
&& CombatUtil.canBlock(attacker, blocker, combat) && CombatUtil.lifeInDanger(ai, combat)) {
|
&& CombatUtil.canBlock(attacker, blocker, combat) && ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||||
combat.addBlocker(attacker, blocker);
|
combat.addBlocker(attacker, blocker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -667,11 +667,11 @@ public class ComputerUtilBlock {
|
|||||||
safeBlockers = ComputerUtilBlock.getSafeBlockers(attacker, blockers, combat);
|
safeBlockers = ComputerUtilBlock.getSafeBlockers(attacker, blockers, combat);
|
||||||
for (final Card blocker : safeBlockers) {
|
for (final Card blocker : safeBlockers) {
|
||||||
final int damageNeeded = attacker.getKillDamage()
|
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
|
// Add an additional blocker if the current blockers are not
|
||||||
// enough and the new one would deal additional damage
|
// enough and the new one would deal additional damage
|
||||||
if ((damageNeeded > CombatUtil.totalDamageOfBlockers(attacker, combat.getBlockers(attacker)))
|
if ((damageNeeded > ComputerUtilCombat.totalDamageOfBlockers(attacker, combat.getBlockers(attacker)))
|
||||||
&& (CombatUtil.dealsDamageAsBlocker(attacker, blocker) > 0)
|
&& ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker) > 0
|
||||||
&& CombatUtil.canBlock(attacker, blocker, combat)) {
|
&& CombatUtil.canBlock(attacker, blocker, combat)) {
|
||||||
combat.addBlocker(attacker, blocker);
|
combat.addBlocker(attacker, blocker);
|
||||||
}
|
}
|
||||||
@@ -691,11 +691,11 @@ public class ComputerUtilBlock {
|
|||||||
|
|
||||||
for (final Card blocker : safeBlockers) {
|
for (final Card blocker : safeBlockers) {
|
||||||
final int damageNeeded = attacker.getKillDamage()
|
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
|
// Add an additional blocker if the current blockers are not
|
||||||
// enough and the new one would deal the remaining damage
|
// enough and the new one would deal the remaining damage
|
||||||
final int currentDamage = CombatUtil.totalDamageOfBlockers(attacker, combat.getBlockers(attacker));
|
final int currentDamage = ComputerUtilCombat.totalDamageOfBlockers(attacker, combat.getBlockers(attacker));
|
||||||
final int additionalDamage = CombatUtil.dealsDamageAsBlocker(attacker, blocker);
|
final int additionalDamage = ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker);
|
||||||
if ((damageNeeded > currentDamage)
|
if ((damageNeeded > currentDamage)
|
||||||
&& !(damageNeeded > (currentDamage + additionalDamage))
|
&& !(damageNeeded > (currentDamage + additionalDamage))
|
||||||
&& ((CardFactoryUtil.evaluateCreature(blocker) + ComputerUtilBlock.getDiff()) < CardFactoryUtil
|
&& ((CardFactoryUtil.evaluateCreature(blocker) + ComputerUtilBlock.getDiff()) < CardFactoryUtil
|
||||||
@@ -810,13 +810,13 @@ public class ComputerUtilBlock {
|
|||||||
// == 1. choose best blocks first ==
|
// == 1. choose best blocks first ==
|
||||||
combat = ComputerUtilBlock.makeGoodBlocks(combat);
|
combat = ComputerUtilBlock.makeGoodBlocks(combat);
|
||||||
combat = ComputerUtilBlock.makeGangBlocks(ai, combat);
|
combat = ComputerUtilBlock.makeGangBlocks(ai, combat);
|
||||||
if (CombatUtil.lifeInDanger(ai, combat)) {
|
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||||
combat = ComputerUtilBlock.makeTradeBlocks(ai, combat); // choose
|
combat = ComputerUtilBlock.makeTradeBlocks(ai, combat); // choose
|
||||||
// necessary
|
// necessary
|
||||||
// trade blocks
|
// trade blocks
|
||||||
}
|
}
|
||||||
// if life is in danger
|
// if life is in danger
|
||||||
if (CombatUtil.lifeInDanger(ai, combat)) {
|
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||||
combat = ComputerUtilBlock.makeChumpBlocks(ai, combat); // choose
|
combat = ComputerUtilBlock.makeChumpBlocks(ai, combat); // choose
|
||||||
// necessary
|
// necessary
|
||||||
// chump blocks
|
// chump blocks
|
||||||
@@ -824,18 +824,18 @@ public class ComputerUtilBlock {
|
|||||||
// if life is still in danger
|
// if life is still in danger
|
||||||
// Reinforce blockers blocking attackers with trample if life is still
|
// Reinforce blockers blocking attackers with trample if life is still
|
||||||
// in danger
|
// in danger
|
||||||
if (CombatUtil.lifeInDanger(ai, combat)) {
|
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||||
combat = ComputerUtilBlock.reinforceBlockersAgainstTrample(ai, combat);
|
combat = ComputerUtilBlock.reinforceBlockersAgainstTrample(ai, combat);
|
||||||
}
|
}
|
||||||
// Support blockers not destroying the attacker with more blockers to
|
// Support blockers not destroying the attacker with more blockers to
|
||||||
// try to kill the attacker
|
// try to kill the attacker
|
||||||
if (!CombatUtil.lifeInDanger(ai, combat)) {
|
if (!ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||||
combat = ComputerUtilBlock.reinforceBlockersToKill(combat);
|
combat = ComputerUtilBlock.reinforceBlockersToKill(combat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// == 2. If the AI life would still be in danger make a safer approach
|
// == 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;
|
lifeInDanger = true;
|
||||||
combat = ComputerUtilBlock.resetBlockers(combat, possibleBlockers); // reset
|
combat = ComputerUtilBlock.resetBlockers(combat, possibleBlockers); // reset
|
||||||
// every
|
// every
|
||||||
@@ -846,7 +846,7 @@ public class ComputerUtilBlock {
|
|||||||
// trade blocks
|
// trade blocks
|
||||||
// if life is in danger
|
// if life is in danger
|
||||||
combat = ComputerUtilBlock.makeGoodBlocks(combat);
|
combat = ComputerUtilBlock.makeGoodBlocks(combat);
|
||||||
if (CombatUtil.lifeInDanger(ai, combat)) {
|
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||||
combat = ComputerUtilBlock.makeChumpBlocks(ai, combat); // choose
|
combat = ComputerUtilBlock.makeChumpBlocks(ai, combat); // choose
|
||||||
// necessary
|
// necessary
|
||||||
// chump
|
// chump
|
||||||
@@ -855,7 +855,7 @@ public class ComputerUtilBlock {
|
|||||||
// danger
|
// danger
|
||||||
// Reinforce blockers blocking attackers with trample if life is
|
// Reinforce blockers blocking attackers with trample if life is
|
||||||
// still in danger
|
// still in danger
|
||||||
if (CombatUtil.lifeInDanger(ai, combat)) {
|
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||||
combat = ComputerUtilBlock.reinforceBlockersAgainstTrample(ai, combat);
|
combat = ComputerUtilBlock.reinforceBlockersAgainstTrample(ai, combat);
|
||||||
}
|
}
|
||||||
combat = ComputerUtilBlock.makeGangBlocks(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
|
// == 3. If the AI life would be in serious danger make an even safer
|
||||||
// approach ==
|
// approach ==
|
||||||
if (CombatUtil.lifeInSeriousDanger(ai, combat)) {
|
if (ComputerUtilCombat.lifeInSeriousDanger(ai, combat)) {
|
||||||
combat = ComputerUtilBlock.resetBlockers(combat, possibleBlockers); // reset
|
combat = ComputerUtilBlock.resetBlockers(combat, possibleBlockers); // reset
|
||||||
// every
|
// every
|
||||||
// block
|
// block
|
||||||
// assignment
|
// assignment
|
||||||
combat = ComputerUtilBlock.makeChumpBlocks(ai, combat); // choose chump
|
combat = ComputerUtilBlock.makeChumpBlocks(ai, combat); // choose chump
|
||||||
// blocks
|
// blocks
|
||||||
if (CombatUtil.lifeInDanger(ai, combat)) {
|
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||||
combat = ComputerUtilBlock.makeTradeBlocks(ai, combat); // choose
|
combat = ComputerUtilBlock.makeTradeBlocks(ai, combat); // choose
|
||||||
// necessary
|
// necessary
|
||||||
// trade
|
// trade
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CombatUtil.lifeInDanger(ai, combat)) {
|
if (!ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||||
combat = ComputerUtilBlock.makeGoodBlocks(combat);
|
combat = ComputerUtilBlock.makeGoodBlocks(combat);
|
||||||
}
|
}
|
||||||
// Reinforce blockers blocking attackers with trample if life is
|
// Reinforce blockers blocking attackers with trample if life is
|
||||||
|
|||||||
1624
src/main/java/forge/game/ai/ComputerUtilCombat.java
Normal file
1624
src/main/java/forge/game/ai/ComputerUtilCombat.java
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user