diff --git a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java index 3c90d62ade0..8bebf86ee49 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java @@ -338,13 +338,11 @@ public class ChangeZoneAi extends SpellAbilityAi { } String type = sa.getParam("ChangeType"); - if (type != null) { - if (type.contains("X") && sa.getSVar("X").equals("Count$xPaid")) { - // Set PayX here to maximum value. - final int xPay = ComputerUtilCost.getMaxXValue(sa, ai, sa.isTrigger()); - sa.setXManaCostPaid(xPay); - type = type.replace("X", Integer.toString(xPay)); - } + if (type != null && type.contains("X") && sa.getSVar("X").equals("Count$xPaid")) { + // Set PayX here to maximum value. + final int xPay = ComputerUtilCost.getMaxXValue(sa, ai, sa.isTrigger()); + sa.setXManaCostPaid(xPay); + type = type.replace("X", Integer.toString(xPay)); } for (final Player p : pDefined) { @@ -500,7 +498,7 @@ public class ChangeZoneAi extends SpellAbilityAi { // this works for hidden because the mana is paid first. final String type = sa.getParam("ChangeType"); - if (type != null && type.contains("X") && sa.getSVar("X").equals("Count$xPaid")) { + if (!mandatory && sa.getPayCosts().hasXInAnyCostPart() && type != null && type.contains("X") && sa.getSVar("X").equals("Count$xPaid")) { // Set PayX here to maximum value. final int xPay = ComputerUtilCost.getMaxXValue(sa, ai, sa.isTrigger()); sa.setXManaCostPaid(xPay); diff --git a/forge-ai/src/main/java/forge/ai/ability/ManaEffectAi.java b/forge-ai/src/main/java/forge/ai/ability/ManaEffectAi.java index eb8104e47db..17cc2f8ed75 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ManaEffectAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ManaEffectAi.java @@ -4,6 +4,7 @@ import java.util.Arrays; import java.util.List; import com.google.common.base.Predicates; +import com.google.common.collect.Iterables; import forge.ai.AiPlayDecision; import forge.ai.ComputerUtil; @@ -17,6 +18,7 @@ import forge.card.ColorSet; import forge.card.MagicColor; import forge.card.mana.ManaAtom; import forge.card.mana.ManaCost; +import forge.game.CardTraitPredicates; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardCollection; @@ -65,7 +67,7 @@ public class ManaEffectAi extends SpellAbilityAi { */ @Override protected boolean checkPhaseRestrictions(Player ai, SpellAbility sa, PhaseHandler ph) { - if (ph.is(PhaseType.END_OF_TURN) && (ph.getNextTurn() == ai || ComputerUtilCard.willUntap(ai, sa.getHostCard())) && canRampPool(ai, sa.getHostCard())) { + if (improvesPosition(ai, sa)) { return true; } if (!ph.is(PhaseType.MAIN2)) { @@ -109,12 +111,8 @@ public class ManaEffectAi extends SpellAbilityAi { return true; } - PhaseHandler ph = ai.getGame().getPhaseHandler(); - boolean moreManaNextTurn = ph.is(PhaseType.END_OF_TURN) && (ph.getNextTurn() == ai || ComputerUtilCard.willUntap(ai, sa.getHostCard())) - && canRampPool(ai, sa.getHostCard()); - return sa.getPayCosts().hasNoManaCost() && sa.getPayCosts().isReusuableResource() - && sa.getSubAbility() == null && (moreManaNextTurn || ComputerUtil.playImmediately(ai, sa)); + && sa.getSubAbility() == null && (improvesPosition(ai, sa) || ComputerUtil.playImmediately(ai, sa)); } /** @@ -262,6 +260,16 @@ public class ManaEffectAi extends SpellAbilityAi { return castableSpells.size() > 0; } + private boolean improvesPosition(Player ai, SpellAbility sa) { + boolean activateForTrigger = Iterables.any(Iterables.filter(sa.getHostCard().getTriggers(), CardTraitPredicates.hasParam("AILogic", "ActivateOnce")), + t -> sa.getHostCard().getAbilityActivatedThisTurn(t.getOverridingAbility()) == 0); + + PhaseHandler ph = ai.getGame().getPhaseHandler(); + // TODO if threatened use right away + return ph.is(PhaseType.END_OF_TURN) && (ph.getNextTurn() == ai || ComputerUtilCard.willUntap(ai, sa.getHostCard())) + && (activateForTrigger || canRampPool(ai, sa.getHostCard())); + } + public static boolean canRampPool(Player ai, Card source) { ManaPool mp = ai.getManaPool(); Mana test = null; diff --git a/forge-gui/res/cardsfolder/t/tyvar_the_bellicose.txt b/forge-gui/res/cardsfolder/t/tyvar_the_bellicose.txt index 9d93a0b05a0..6b87794edfd 100644 --- a/forge-gui/res/cardsfolder/t/tyvar_the_bellicose.txt +++ b/forge-gui/res/cardsfolder/t/tyvar_the_bellicose.txt @@ -5,7 +5,7 @@ PT:5/4 T:Mode$ AttackersDeclared | ValidAttackers$ Elf.YouCtrl | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ Whenever one or more Elves you control attack, they gain deathtouch until end of turn. SVar:TrigPump:DB$ Pump | Defined$ TriggeredAttackers | KW$ Deathtouch S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddTrigger$ ManaTrig | Description$ Each creature you control has "Whenever a mana ability of this creature resolves, put a number of +1/+1 counters on it equal to the amount of mana this creature produced. This ability triggers only once each turn." -SVar:ManaTrig:Mode$ AbilityResolves | ValidSource$ Card.Self | ValidSpellAbility$ SpellAbility.ManaAbility | ActivationLimit$ 1 | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever a mana ability of this creature resolves, put a number of +1/+1 counters on it equal to the amount of mana this creature produced. This ability triggers only once each turn. +SVar:ManaTrig:Mode$ AbilityResolves | ValidSource$ Card.Self | ValidSpellAbility$ SpellAbility.ManaAbility | ActivationLimit$ 1 | TriggerZones$ Battlefield | Execute$ TrigPutCounter | AILogic$ ActivateOnce | TriggerDescription$ Whenever a mana ability of this creature resolves, put a number of +1/+1 counters on it equal to the amount of mana this creature produced. This ability triggers only once each turn. SVar:TrigPutCounter:DB$ PutCounter | CounterType$ P1P1 | CounterNum$ X SVar:X:TriggeredSpellAbility$AmountManaProduced DeckHints:Type$Elf