Merge pull request #524 from tool4ever/tappingai

Fix Tap trigger decisions
This commit is contained in:
Agetian
2022-05-27 13:09:38 +03:00
committed by GitHub
4 changed files with 20 additions and 20 deletions

View File

@@ -102,7 +102,7 @@ public class DrawAi extends SpellAbilityAi {
return false;
}
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source,sa)) {
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source, sa)) {
AiCostDecision aiDecisions = new AiCostDecision(ai, sa, false);
for (final CostPart part : cost.getCostParts()) {
if (part instanceof CostDiscard) {

View File

@@ -106,10 +106,8 @@ public abstract class TapAiBase extends SpellAbilityAi {
* @return a boolean.
*/
protected boolean tapPrefTargeting(final Player ai, final Card source, final SpellAbility sa, final boolean mandatory) {
final Player opp = AiAttackController.choosePreferredDefenderPlayer(ai);
final Game game = ai.getGame();
CardCollection tapList = CardLists.filterControlledBy(game.getCardsIn(ZoneType.Battlefield), ai.getOpponents());
tapList = CardLists.getTargetableCards(tapList, sa);
CardCollection tapList = CardLists.getTargetableCards(ai.getOpponents().getCardsIn(ZoneType.Battlefield), sa);
tapList = CardLists.filter(tapList, Presets.UNTAPPED);
tapList = CardLists.filter(tapList, new Predicate<Card>() {
@Override
@@ -129,8 +127,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
//use broader approach when the cost is a positive thing
if (tapList.isEmpty() && ComputerUtil.activateForCost(sa, ai)) {
tapList = CardLists.filterControlledBy(game.getCardsIn(ZoneType.Battlefield), ai.getOpponents());
tapList = CardLists.getTargetableCards(tapList, sa);
tapList = CardLists.getTargetableCards(ai.getOpponents().getCardsIn(ZoneType.Battlefield), sa);
tapList = CardLists.filter(tapList, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
@@ -150,8 +147,10 @@ public abstract class TapAiBase extends SpellAbilityAi {
//try to exclude things that will already be tapped due to something on stack or because something is
//already targeted in a parent or sub SA
if (!sa.isTrigger() || mandatory) { // but if just confirming trigger no need to look for other targets and might still help anyway
CardCollection toExclude = ComputerUtilAbility.getCardsTargetedWithApi(ai, tapList, sa, ApiType.Tap);
tapList.removeAll(toExclude);
}
if (tapList.isEmpty()) {
return false;
@@ -176,6 +175,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
}
PhaseHandler phase = game.getPhaseHandler();
final Player opp = AiAttackController.choosePreferredDefenderPlayer(ai);
Card primeTarget = ComputerUtil.getKilledByTargeting(sa, tapList);
if (primeTarget != null) {
choice = primeTarget;
@@ -193,7 +193,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
return CombatUtil.canAttack(c, opp);
}
});
attackers.remove(sa.getHostCard());
attackers.remove(source);
}
Predicate<Card> findBlockers = CardPredicates.possibleBlockerForAtLeastOne(attackers);
List<Card> creatureList = CardLists.filter(tapList, findBlockers);
@@ -202,7 +202,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
if (!attackers.isEmpty() && !creatureList.isEmpty()) {
choice = ComputerUtilCard.getBestCreatureAI(creatureList);
} else if (sa.getRootAbility().isTrigger() || ComputerUtil.castSpellInMain1(ai, sa)) {
} else if (sa.isTrigger() || ComputerUtil.castSpellInMain1(ai, sa)) {
choice = ComputerUtilCard.getMostExpensivePermanentAI(tapList);
}
} else if (phase.isPlayerTurn(opp)
@@ -272,7 +272,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
return true;
}
// filter by enchantments and planeswalkers, their tapped state doesn't matter.
// filter by enchantments and planeswalkers, their tapped state (usually) doesn't matter.
final String[] tappablePermanents = { "Enchantment", "Planeswalker" };
tapList = CardLists.getValidCards(list, tappablePermanents, source.getController(), source, sa);

View File

@@ -53,7 +53,7 @@ public class UntapAi extends SpellAbilityAi {
return false;
}
return ComputerUtilCost.checkDiscardCost(ai, cost, sa.getHostCard(), sa);
return ComputerUtilCost.checkDiscardCost(ai, cost, source, sa);
}
@Override
@@ -174,8 +174,10 @@ public class UntapAi extends SpellAbilityAi {
//try to exclude things that will already be untapped due to something on stack or because something is
//already targeted in a parent or sub SA
if (!sa.isTrigger() || mandatory) { // but if just confirming trigger no need to look for other targets and might still help anyway
CardCollection toExclude = ComputerUtilAbility.getCardsTargetedWithApi(ai, untapList, sa, ApiType.Untap);
untapList.removeAll(toExclude);
}
sa.resetTargets();
while (sa.canAddMoreTarget()) {
@@ -199,7 +201,7 @@ public class UntapAi extends SpellAbilityAi {
if (choice == null) {
if (CardLists.getNotType(untapList, "Creature").isEmpty()) {
choice = ComputerUtilCard.getBestCreatureAI(untapList); // if only creatures take the best
} else if (!sa.getPayCosts().hasManaCost() || sa.getRootAbility().isTrigger()
} else if (!sa.getPayCosts().hasManaCost() || sa.isTrigger()
|| "Always".equals(sa.getParam("AILogic"))) {
choice = ComputerUtilCard.getMostExpensivePermanentAI(untapList);
}
@@ -290,7 +292,7 @@ public class UntapAi extends SpellAbilityAi {
choice = ComputerUtilCard.getBestAI(tapList);
if (choice == null) { // can't find anything left
if (sa.getTargets().size() < tgt.getMinTargets(sa.getHostCard(), sa) || sa.getTargets().size() == 0) {
if (sa.getTargets().size() < tgt.getMinTargets(source, sa) || sa.getTargets().size() == 0) {
if (!mandatory) {
sa.resetTargets();
}
@@ -310,9 +312,7 @@ public class UntapAi extends SpellAbilityAi {
@Override
public Card chooseSingleCard(Player ai, SpellAbility sa, Iterable<Card> list, boolean isOptional, Player targetedPlayer, Map<String, Object> params) {
PlayerCollection pl = new PlayerCollection();
pl.add(ai);
pl.addAll(ai.getAllies());
PlayerCollection pl = ai.getYourTeam();
return ComputerUtilCard.getBestAI(CardLists.filterControlledBy(list, pl));
}

View File

@@ -132,7 +132,7 @@ public class ControlGainEffect extends SpellAbilityEffect {
tgtCards = getDefinedCards(sa);
}
if (tgtCards !=null & sa.hasParam("ControlledByTarget")) {
if (tgtCards != null & sa.hasParam("ControlledByTarget")) {
tgtCards = CardLists.filterControlledBy(tgtCards, getTargetPlayers(sa));
}