- Improved AI targeting opponents cards with "When CARDNAME becomes the target of a spell or ability, sacrifice it.".

This commit is contained in:
Sloth
2015-07-10 21:31:29 +00:00
parent 6620f0a7f9
commit 7305a05be0
4 changed files with 30 additions and 14 deletions

View File

@@ -1732,6 +1732,17 @@ public class ComputerUtil {
return safeCards;
}
public static Card getKilledByTargeting(final SpellAbility sa, CardCollectionView validCards) {
CardCollection killables = new CardCollection(validCards);
killables = CardLists.filter(killables, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.getController() != sa.getActivatingPlayer() && c.getSVar("Targeting").equals("Dies");
}
});
return ComputerUtilCard.getBestCreatureAI(killables);
}
public static int damageFromETB(final Player player, final Card permanent) {
int damage = 0;
final Game game = player.getGame();

View File

@@ -170,8 +170,9 @@ public class DamageDealAi extends DamageAiBase {
final List<Card> killables = CardLists.filter(hPlay, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return (ComputerUtilCombat.getEnoughDamageToKill(c, d, source, false, noPrevention) <= d) && !ComputerUtil.canRegenerate(ai, c)
&& !(c.getSVar("SacMe").length() > 0);
return c.getSVar("Targeting").equals("Dies")
|| (ComputerUtilCombat.getEnoughDamageToKill(c, d, source, false, noPrevention) <= d) && !ComputerUtil.canRegenerate(ai, c)
&& !(c.getSVar("SacMe").length() > 0);
}
});

View File

@@ -467,10 +467,10 @@ public abstract class PumpAiBase extends SpellAbilityAi {
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
if (c.getNetToughness() <= -defense) {
if (c.getSVar("Targeting").equals("Dies") || c.getNetToughness() <= -defense) {
return true; // can kill indestructible creatures
}
return ((ComputerUtilCombat.getDamageToKill(c) <= -defense) && !c.hasKeyword("Indestructible"));
return (ComputerUtilCombat.getDamageToKill(c) <= -defense && !c.hasKeyword("Indestructible"));
}
}); // leaves all creatures that will be destroyed
} // -X/-X end

View File

@@ -47,7 +47,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
tapList.remove(c);
}
if (tapList.size() == 0) {
if (tapList.isEmpty()) {
return false;
}
@@ -55,7 +55,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
Card choice = null;
if (tapList.size() == 0) {
if ((sa.getTargets().getNumTargeted() < tgt.getMinTargets(source, sa)) || (sa.getTargets().getNumTargeted() == 0)) {
if (sa.getTargets().getNumTargeted() < tgt.getMinTargets(source, sa) || sa.getTargets().getNumTargeted() == 0) {
if (!mandatory) {
sa.resetTargets();
}
@@ -68,7 +68,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
}
}
if (CardLists.getNotType(tapList, "Creature").size() == 0) {
if (CardLists.getNotType(tapList, "Creature").isEmpty()) {
// if only creatures take the best
choice = ComputerUtilCard.getBestCreatureAI(tapList);
} else {
@@ -76,7 +76,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
}
if (choice == null) { // can't find anything left
if ((sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) || (sa.getTargets().getNumTargeted() == 0)) {
if (sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa) || sa.getTargets().getNumTargeted() == 0) {
if (!mandatory) {
sa.resetTargets();
}
@@ -117,9 +117,9 @@ public abstract class TapAiBase extends SpellAbilityAi {
final Player opp = ai.getOpponent();
final Game game = ai.getGame();
CardCollection tapList = CardLists.filterControlledBy(game.getCardsIn(ZoneType.Battlefield), ai.getOpponents());
tapList = CardLists.filter(tapList, Presets.UNTAPPED);
tapList = CardLists.getValidCards(tapList, tgt.getValidTgts(), source.getController(), source);
tapList = CardLists.getTargetableCards(tapList, sa);
tapList = CardLists.filter(tapList, Presets.UNTAPPED);
tapList = CardLists.filter(tapList, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
@@ -162,17 +162,18 @@ public abstract class TapAiBase extends SpellAbilityAi {
return false;
}
boolean goodTargets = false;
while (sa.getTargets().getNumTargeted() < tgt.getMaxTargets(source, sa)) {
Card choice = null;
if (tapList.isEmpty()) {
if ((sa.getTargets().getNumTargeted() < tgt.getMinTargets(source, sa)) || (sa.getTargets().getNumTargeted() == 0)) {
if (sa.getTargets().getNumTargeted() < tgt.getMinTargets(source, sa) || sa.getTargets().getNumTargeted() == 0) {
if (!mandatory) {
sa.resetTargets();
}
return false;
} else {
if (!ComputerUtil.shouldCastLessThanMax(ai, source)) {
if (!goodTargets && !ComputerUtil.shouldCastLessThanMax(ai, source)) {
return false;
}
break;
@@ -180,8 +181,11 @@ public abstract class TapAiBase extends SpellAbilityAi {
}
PhaseHandler phase = game.getPhaseHandler();
if (phase.isPlayerTurn(ai)
&& phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
Card primeTarget = ComputerUtil.getKilledByTargeting(sa, tapList);
if (primeTarget != null) {
choice = primeTarget;
goodTargets = true;
} else if (phase.isPlayerTurn(ai) && phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
// Tap creatures possible blockers before combat during AI's turn.
List<Card> attackers;
if (phase.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
@@ -224,7 +228,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
}
if (choice == null) { // can't find anything left
if ((sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) || (sa.getTargets().getNumTargeted() == 0)) {
if (sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa) || sa.getTargets().getNumTargeted() == 0) {
if (!mandatory) {
sa.resetTargets();
}