mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
- Some improvements to the Aristocrats and Electrostatic Pummeler AI logic.
This commit is contained in:
@@ -287,12 +287,11 @@ public class SpecialCardAi {
|
|||||||
|
|
||||||
// Electrostatic Pummeler
|
// Electrostatic Pummeler
|
||||||
public static class ElectrostaticPummeler {
|
public static class ElectrostaticPummeler {
|
||||||
// TODO: use getNetCombatDamage() instead of getNetPower() for cases where damage is assigned by toughness
|
|
||||||
public static boolean consider(final Player ai, final SpellAbility sa) {
|
public static boolean consider(final Player ai, final SpellAbility sa) {
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
Game game = ai.getGame();
|
Game game = ai.getGame();
|
||||||
Combat combat = game.getCombat();
|
Combat combat = game.getCombat();
|
||||||
Pair<Integer, Integer> predictedPT = getPumpedPT(ai, source.getNetPower(), source.getNetToughness());
|
Pair<Integer, Integer> predictedPT = getPumpedPT(ai, source.getNetCombatDamage(), source.getNetToughness());
|
||||||
|
|
||||||
// Try to save the Pummeler from death by pumping it if it's threatened with a damage spell
|
// Try to save the Pummeler from death by pumping it if it's threatened with a damage spell
|
||||||
if (ComputerUtil.predictThreatenedObjects(ai, null, true).contains(source)) {
|
if (ComputerUtil.predictThreatenedObjects(ai, null, true).contains(source)) {
|
||||||
@@ -330,7 +329,7 @@ public class SpecialCardAi {
|
|||||||
boolean cantDie = ComputerUtilCombat.attackerCantBeDestroyedInCombat(ai, source);
|
boolean cantDie = ComputerUtilCombat.attackerCantBeDestroyedInCombat(ai, source);
|
||||||
|
|
||||||
CardCollection opposition = isBlocking ? combat.getAttackersBlockedBy(source) : combat.getBlockers(source);
|
CardCollection opposition = isBlocking ? combat.getAttackersBlockedBy(source) : combat.getBlockers(source);
|
||||||
int oppP = Aggregates.sum(opposition, CardPredicates.Accessors.fnGetNetPower);
|
int oppP = Aggregates.sum(opposition, CardPredicates.Accessors.fnGetAttack);
|
||||||
int oppT = Aggregates.sum(opposition, CardPredicates.Accessors.fnGetNetToughness);
|
int oppT = Aggregates.sum(opposition, CardPredicates.Accessors.fnGetNetToughness);
|
||||||
|
|
||||||
boolean oppHasFirstStrike = false;
|
boolean oppHasFirstStrike = false;
|
||||||
@@ -340,7 +339,13 @@ public class SpecialCardAi {
|
|||||||
|
|
||||||
if (!isBlocking && combat.getDefenderByAttacker(source) instanceof Card) {
|
if (!isBlocking && combat.getDefenderByAttacker(source) instanceof Card) {
|
||||||
int loyalty = ((Card)combat.getDefenderByAttacker(source)).getCounters(CounterType.LOYALTY);
|
int loyalty = ((Card)combat.getDefenderByAttacker(source)).getCounters(CounterType.LOYALTY);
|
||||||
if (source.getNetPower() >= oppT + loyalty) {
|
int totalDamageToPW = 0;
|
||||||
|
for (Card atk : (combat.getAttackersOf(combat.getDefenderByAttacker(source)))) {
|
||||||
|
if (combat.isUnblocked(atk)) {
|
||||||
|
totalDamageToPW += atk.getNetCombatDamage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (totalDamageToPW >= oppT + loyalty) {
|
||||||
// Already enough damage to take care of the planeswalker
|
// Already enough damage to take care of the planeswalker
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -348,6 +353,7 @@ public class SpecialCardAi {
|
|||||||
// Can pump to kill the planeswalker, go for it
|
// Can pump to kill the planeswalker, go for it
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Card c : opposition) {
|
for (Card c : opposition) {
|
||||||
@@ -378,7 +384,7 @@ public class SpecialCardAi {
|
|||||||
// Can't pump enough to kill the blockers and survive, don't pump
|
// Can't pump enough to kill the blockers and survive, don't pump
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (source.getNetPower() > oppT && source.getNetToughness() > oppP) {
|
if (source.getNetCombatDamage() > oppT && source.getNetToughness() > oppP) {
|
||||||
// Already enough to kill the blockers and survive, don't overpump
|
// Already enough to kill the blockers and survive, don't overpump
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -405,7 +411,7 @@ public class SpecialCardAi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<Integer, Integer> predictedPT = getPumpedPT(ai, source.getNetPower(), source.getNetToughness());
|
Pair<Integer, Integer> predictedPT = getPumpedPT(ai, source.getNetCombatDamage(), source.getNetToughness());
|
||||||
int oppT = Aggregates.sum(potentialBlockers, CardPredicates.Accessors.fnGetNetToughness);
|
int oppT = Aggregates.sum(potentialBlockers, CardPredicates.Accessors.fnGetNetToughness);
|
||||||
|
|
||||||
if (potentialBlockers.isEmpty() || (sa.getHostCard().hasKeyword("Trample") && predictedPT.getLeft() - oppT >= oppLife)) {
|
if (potentialBlockers.isEmpty() || (sa.getHostCard().hasKeyword("Trample") && predictedPT.getLeft() - oppT >= oppLife)) {
|
||||||
|
|||||||
@@ -739,7 +739,6 @@ public class PumpAi extends PumpAiBase {
|
|||||||
|
|
||||||
public boolean doAristocratLogic(final SpellAbility sa, final Player ai) {
|
public boolean doAristocratLogic(final SpellAbility sa, final Player ai) {
|
||||||
// A logic for cards that say "Sacrifice a creature: CARDNAME gets +X/+X until EOT"
|
// A logic for cards that say "Sacrifice a creature: CARDNAME gets +X/+X until EOT"
|
||||||
// TODO: use getNetCombatDamage() instead of getNetPower() for cases where damage is assigned by toughness
|
|
||||||
final Game game = ai.getGame();
|
final Game game = ai.getGame();
|
||||||
final Combat combat = game.getCombat();
|
final Combat combat = game.getCombat();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
@@ -804,11 +803,11 @@ public class PumpAi extends PumpAiBase {
|
|||||||
final boolean isInfect = source.hasKeyword("Infect"); // Flesh-Eater Imp
|
final boolean isInfect = source.hasKeyword("Infect"); // Flesh-Eater Imp
|
||||||
final int lethalDmg = isInfect ? 10 - defPlayer.getPoisonCounters() : defPlayer.getLife();
|
final int lethalDmg = isInfect ? 10 - defPlayer.getPoisonCounters() : defPlayer.getLife();
|
||||||
|
|
||||||
final int numCreatsToSac = (lethalDmg - source.getNetPower()) / powerBonus;
|
final int numCreatsToSac = (lethalDmg - source.getNetCombatDamage()) / powerBonus;
|
||||||
|
|
||||||
if (defTappedOut || numCreatsToSac < numOtherCreats / 2) {
|
if (defTappedOut || numCreatsToSac < numOtherCreats / 2) {
|
||||||
return source.getNetPower() < lethalDmg
|
return source.getNetCombatDamage() < lethalDmg
|
||||||
&& source.getNetPower() + numOtherCreats * powerBonus >= lethalDmg;
|
&& source.getNetCombatDamage() + numOtherCreats * powerBonus >= lethalDmg;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -833,7 +832,7 @@ public class PumpAi extends PumpAiBase {
|
|||||||
final int DefP = Aggregates.sum(combat.getBlockers(source), CardPredicates.Accessors.fnGetNetPower);
|
final int DefP = Aggregates.sum(combat.getBlockers(source), CardPredicates.Accessors.fnGetNetPower);
|
||||||
|
|
||||||
// Make sure we don't over-sacrifice, only sac until we can survive and kill a creature
|
// Make sure we don't over-sacrifice, only sac until we can survive and kill a creature
|
||||||
return source.getNetToughness() - source.getDamage() <= DefP || source.getNetPower() < minDefT;
|
return source.getNetToughness() - source.getDamage() <= DefP || source.getNetCombatDamage() < minDefT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We can't deal lethal, check if there's any sac fodder than can be used for other circumstances
|
// We can't deal lethal, check if there's any sac fodder than can be used for other circumstances
|
||||||
|
|||||||
Reference in New Issue
Block a user