mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +00:00
Fix Tap trigger decisions
This commit is contained in:
@@ -102,7 +102,7 @@ public class DrawAi extends SpellAbilityAi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source,sa)) {
|
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source, sa)) {
|
||||||
AiCostDecision aiDecisions = new AiCostDecision(ai, sa, false);
|
AiCostDecision aiDecisions = new AiCostDecision(ai, sa, false);
|
||||||
for (final CostPart part : cost.getCostParts()) {
|
for (final CostPart part : cost.getCostParts()) {
|
||||||
if (part instanceof CostDiscard) {
|
if (part instanceof CostDiscard) {
|
||||||
|
|||||||
@@ -106,10 +106,8 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
|||||||
* @return a boolean.
|
* @return a boolean.
|
||||||
*/
|
*/
|
||||||
protected boolean tapPrefTargeting(final Player ai, final Card source, final SpellAbility sa, final boolean mandatory) {
|
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();
|
final Game game = ai.getGame();
|
||||||
CardCollection tapList = CardLists.filterControlledBy(game.getCardsIn(ZoneType.Battlefield), ai.getOpponents());
|
CardCollection tapList = CardLists.getTargetableCards(ai.getOpponents().getCardsIn(ZoneType.Battlefield), sa);
|
||||||
tapList = CardLists.getTargetableCards(tapList, sa);
|
|
||||||
tapList = CardLists.filter(tapList, Presets.UNTAPPED);
|
tapList = CardLists.filter(tapList, Presets.UNTAPPED);
|
||||||
tapList = CardLists.filter(tapList, new Predicate<Card>() {
|
tapList = CardLists.filter(tapList, new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -129,8 +127,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
|||||||
|
|
||||||
//use broader approach when the cost is a positive thing
|
//use broader approach when the cost is a positive thing
|
||||||
if (tapList.isEmpty() && ComputerUtil.activateForCost(sa, ai)) {
|
if (tapList.isEmpty() && ComputerUtil.activateForCost(sa, ai)) {
|
||||||
tapList = CardLists.filterControlledBy(game.getCardsIn(ZoneType.Battlefield), ai.getOpponents());
|
tapList = CardLists.getTargetableCards(ai.getOpponents().getCardsIn(ZoneType.Battlefield), sa);
|
||||||
tapList = CardLists.getTargetableCards(tapList, sa);
|
|
||||||
tapList = CardLists.filter(tapList, new Predicate<Card>() {
|
tapList = CardLists.filter(tapList, new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
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
|
//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
|
//already targeted in a parent or sub SA
|
||||||
CardCollection toExclude = ComputerUtilAbility.getCardsTargetedWithApi(ai, tapList, sa, ApiType.Tap);
|
if (!sa.isTrigger() || mandatory) { // but if just confirming trigger no need to look for other targets and might still help anyway
|
||||||
tapList.removeAll(toExclude);
|
CardCollection toExclude = ComputerUtilAbility.getCardsTargetedWithApi(ai, tapList, sa, ApiType.Tap);
|
||||||
|
tapList.removeAll(toExclude);
|
||||||
|
}
|
||||||
|
|
||||||
if (tapList.isEmpty()) {
|
if (tapList.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -176,6 +175,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PhaseHandler phase = game.getPhaseHandler();
|
PhaseHandler phase = game.getPhaseHandler();
|
||||||
|
final Player opp = AiAttackController.choosePreferredDefenderPlayer(ai);
|
||||||
Card primeTarget = ComputerUtil.getKilledByTargeting(sa, tapList);
|
Card primeTarget = ComputerUtil.getKilledByTargeting(sa, tapList);
|
||||||
if (primeTarget != null) {
|
if (primeTarget != null) {
|
||||||
choice = primeTarget;
|
choice = primeTarget;
|
||||||
@@ -193,7 +193,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
|||||||
return CombatUtil.canAttack(c, opp);
|
return CombatUtil.canAttack(c, opp);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
attackers.remove(sa.getHostCard());
|
attackers.remove(source);
|
||||||
}
|
}
|
||||||
Predicate<Card> findBlockers = CardPredicates.possibleBlockerForAtLeastOne(attackers);
|
Predicate<Card> findBlockers = CardPredicates.possibleBlockerForAtLeastOne(attackers);
|
||||||
List<Card> creatureList = CardLists.filter(tapList, findBlockers);
|
List<Card> creatureList = CardLists.filter(tapList, findBlockers);
|
||||||
@@ -202,7 +202,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
|||||||
|
|
||||||
if (!attackers.isEmpty() && !creatureList.isEmpty()) {
|
if (!attackers.isEmpty() && !creatureList.isEmpty()) {
|
||||||
choice = ComputerUtilCard.getBestCreatureAI(creatureList);
|
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);
|
choice = ComputerUtilCard.getMostExpensivePermanentAI(tapList);
|
||||||
}
|
}
|
||||||
} else if (phase.isPlayerTurn(opp)
|
} else if (phase.isPlayerTurn(opp)
|
||||||
@@ -272,7 +272,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
|||||||
return true;
|
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" };
|
final String[] tappablePermanents = { "Enchantment", "Planeswalker" };
|
||||||
tapList = CardLists.getValidCards(list, tappablePermanents, source.getController(), source, sa);
|
tapList = CardLists.getValidCards(list, tappablePermanents, source.getController(), source, sa);
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class UntapAi extends SpellAbilityAi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ComputerUtilCost.checkDiscardCost(ai, cost, sa.getHostCard(), sa);
|
return ComputerUtilCost.checkDiscardCost(ai, cost, source, sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
//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
|
//already targeted in a parent or sub SA
|
||||||
CardCollection toExclude = ComputerUtilAbility.getCardsTargetedWithApi(ai, untapList, sa, ApiType.Untap);
|
if (!sa.isTrigger() || mandatory) { // but if just confirming trigger no need to look for other targets and might still help anyway
|
||||||
untapList.removeAll(toExclude);
|
CardCollection toExclude = ComputerUtilAbility.getCardsTargetedWithApi(ai, untapList, sa, ApiType.Untap);
|
||||||
|
untapList.removeAll(toExclude);
|
||||||
|
}
|
||||||
|
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
while (sa.canAddMoreTarget()) {
|
while (sa.canAddMoreTarget()) {
|
||||||
@@ -199,7 +201,7 @@ public class UntapAi extends SpellAbilityAi {
|
|||||||
if (choice == null) {
|
if (choice == null) {
|
||||||
if (CardLists.getNotType(untapList, "Creature").isEmpty()) {
|
if (CardLists.getNotType(untapList, "Creature").isEmpty()) {
|
||||||
choice = ComputerUtilCard.getBestCreatureAI(untapList); // if only creatures take the best
|
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"))) {
|
|| "Always".equals(sa.getParam("AILogic"))) {
|
||||||
choice = ComputerUtilCard.getMostExpensivePermanentAI(untapList);
|
choice = ComputerUtilCard.getMostExpensivePermanentAI(untapList);
|
||||||
}
|
}
|
||||||
@@ -290,7 +292,7 @@ public class UntapAi extends SpellAbilityAi {
|
|||||||
choice = ComputerUtilCard.getBestAI(tapList);
|
choice = ComputerUtilCard.getBestAI(tapList);
|
||||||
|
|
||||||
if (choice == null) { // can't find anything left
|
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) {
|
if (!mandatory) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
}
|
}
|
||||||
@@ -310,9 +312,7 @@ public class UntapAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Card chooseSingleCard(Player ai, SpellAbility sa, Iterable<Card> list, boolean isOptional, Player targetedPlayer, Map<String, Object> params) {
|
public Card chooseSingleCard(Player ai, SpellAbility sa, Iterable<Card> list, boolean isOptional, Player targetedPlayer, Map<String, Object> params) {
|
||||||
PlayerCollection pl = new PlayerCollection();
|
PlayerCollection pl = ai.getYourTeam();
|
||||||
pl.add(ai);
|
|
||||||
pl.addAll(ai.getAllies());
|
|
||||||
return ComputerUtilCard.getBestAI(CardLists.filterControlledBy(list, pl));
|
return ComputerUtilCard.getBestAI(CardLists.filterControlledBy(list, pl));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ public class ControlGainEffect extends SpellAbilityEffect {
|
|||||||
tgtCards = getDefinedCards(sa);
|
tgtCards = getDefinedCards(sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tgtCards !=null & sa.hasParam("ControlledByTarget")) {
|
if (tgtCards != null & sa.hasParam("ControlledByTarget")) {
|
||||||
tgtCards = CardLists.filterControlledBy(tgtCards, getTargetPlayers(sa));
|
tgtCards = CardLists.filterControlledBy(tgtCards, getTargetPlayers(sa));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user