mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
- AI: Avoid infinitely activating AF Untap on another permanent that will then be used to untap the first one (e.g. 2x Kiora's Follower)
This commit is contained in:
@@ -13,6 +13,8 @@ import forge.game.card.CardCollection;
|
|||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
import forge.game.card.CardPredicates.Presets;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
|
import forge.game.cost.CostTap;
|
||||||
|
import forge.game.cost.CostTapType;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerCollection;
|
import forge.game.player.PlayerCollection;
|
||||||
@@ -148,6 +150,25 @@ public class UntapAi extends SpellAbilityAi {
|
|||||||
final String[] tappablePermanents = {"Creature", "Land", "Artifact"};
|
final String[] tappablePermanents = {"Creature", "Land", "Artifact"};
|
||||||
untapList = CardLists.getValidCards(untapList, tappablePermanents, source.getController(), source, sa);
|
untapList = CardLists.getValidCards(untapList, tappablePermanents, source.getController(), source, sa);
|
||||||
|
|
||||||
|
// Try to avoid potential infinite recursion,
|
||||||
|
// e.g. Kiora's Follower untapping another Kiora's Follower and repeating infinitely
|
||||||
|
if (sa.getPayCosts() != null && sa.getPayCosts().hasOnlySpecificCostType(CostTap.class)) {
|
||||||
|
CardCollection toRemove = new CardCollection();
|
||||||
|
for (Card c : untapList) {
|
||||||
|
for (SpellAbility ab : c.getAllSpellAbilities()) {
|
||||||
|
if (ab.getApi() == ApiType.Untap
|
||||||
|
&& ab.getPayCosts() != null
|
||||||
|
&& ab.getPayCosts().hasOnlySpecificCostType(CostTap.class)
|
||||||
|
&& ab.canTarget(source)) {
|
||||||
|
System.out.println("Found a recursive untap target: " + c);
|
||||||
|
toRemove.add(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
untapList.removeAll(toRemove);
|
||||||
|
}
|
||||||
|
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
while (sa.getTargets().getNumTargeted() < tgt.getMaxTargets(sa.getHostCard(), sa)) {
|
while (sa.getTargets().getNumTargeted() < tgt.getMaxTargets(sa.getHostCard(), sa)) {
|
||||||
Card choice = null;
|
Card choice = null;
|
||||||
|
|||||||
@@ -73,6 +73,15 @@ public class Cost {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final boolean hasOnlySpecificCostType(Class<? extends CostPart> costType) {
|
||||||
|
for (CostPart p : getCostParts()) {
|
||||||
|
if (!costType.isInstance(p)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the cost parts.
|
* Gets the cost parts.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user