diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index ab523e47e81..9b2c98bad32 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -1010,7 +1010,7 @@ public class AiController { p += 9; } // sort planeswalker abilities with most costly first - if (sa.getRestrictions().isPwAbility()) { + if (sa.isPwAbility()) { final CostPart cost = sa.getPayCosts().getCostParts().get(0); if (cost instanceof CostRemoveCounter) { p += cost.convertAmount() == null ? 1 : cost.convertAmount(); diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java index fb44ff4e31c..4afe5174eb8 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java @@ -481,7 +481,7 @@ public class ComputerUtilCost { } // Try not to lose Planeswalker if not threatened - if (sa.getRestrictions().isPwAbility()) { + if (sa.isPwAbility()) { for (final CostPart part : sa.getPayCosts().getCostParts()) { if (part instanceof CostRemoveCounter) { if (part.convertAmount() != null && part.convertAmount() == sa.getHostCard().getCurrentLoyalty()) { diff --git a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java index 03c96209a0c..d86989d87a8 100644 --- a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java @@ -247,7 +247,7 @@ public abstract class SpellAbilityAi { protected static boolean isSorcerySpeed(final SpellAbility sa) { return (sa.getRootAbility().isSpell() && sa.getHostCard().isSorcery()) || (sa.getRootAbility().isAbility() && sa.getRestrictions().isSorcerySpeed()) - || (sa.getRestrictions().isPwAbility() && !sa.getHostCard().hasKeyword("CARDNAME's loyalty abilities can be activated at instant speed.")); + || (sa.isPwAbility() && !sa.getHostCard().hasKeyword("CARDNAME's loyalty abilities can be activated at instant speed.")); } /** @@ -276,7 +276,7 @@ public abstract class SpellAbilityAi { return true; } - if (sa.getRestrictions().isPwAbility() && phase.is(PhaseType.MAIN2)) { + if (sa.isPwAbility() && phase.is(PhaseType.MAIN2)) { return true; } if (sa.isSpell() && !sa.isBuyBackAbility()) { diff --git a/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java b/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java index 1d088464afb..531ba01988a 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java @@ -717,8 +717,7 @@ public class DamageDealAi extends DamageAiBase { } if (phase.is(PhaseType.MAIN2) && sa.isAbility()) { - if (sa.getRestrictions().isPwAbility() - || source.hasSVar("EndOfTurnLeavePlay")) + if (sa.isPwAbility() || source.hasSVar("EndOfTurnLeavePlay")) freePing = true; } } diff --git a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java index 4a193850e01..feae6ff6106 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java @@ -78,7 +78,7 @@ public class TokenAi extends SpellAbilityAi { // Planeswalker-related flags boolean pwMinus = false; boolean pwPlus = false; - if (sa.getRestrictions().isPwAbility()) { + if (sa.isPwAbility()) { /* * Planeswalker token ability with loyalty costs should be played in * Main1 or it might never be used due to other positive abilities. @@ -230,7 +230,7 @@ public class TokenAi extends SpellAbilityAi { alwaysOnOppAttack = aic.getBooleanProperty(AiProps.TOKEN_GENERATION_ALWAYS_IF_OPP_ATTACKS); } - if (sa.getRestrictions() != null && sa.getRestrictions().isPwAbility() && alwaysFromPW) { + if (sa.isPwAbility() && alwaysFromPW) { return true; } else if (ai.getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS) && ai.getGame().getPhaseHandler().getPlayerTurn().isOpponentOf(ai) diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java index 30ffb85619a..72aedd7513e 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -324,11 +324,12 @@ public class GameCopier { if (c.isPlaneswalker()) { for (SpellAbility sa : c.getAllSpellAbilities()) { SpellAbilityRestriction restrict = sa.getRestrictions(); - if (restrict.isPwAbility() && restrict.getNumberTurnActivations() > 0) { + if (sa.isPwAbility() && restrict.getNumberTurnActivations() > 0) { SpellAbility newSa = findSAInCard(sa, newCard); if (newSa != null) { for (int i = 0; i < restrict.getNumberTurnActivations(); i++) { newSa.getRestrictions().abilityActivated(); + newCard.addPlaneswalkerAbilityActivated(); } } } diff --git a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java index 210930785b7..a14f2b94047 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java +++ b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java @@ -148,7 +148,7 @@ public class SpellAbilityPicker { if (sa.isSpell()) { return !sa.getHostCard().isInstant() && !sa.getHostCard().withFlash(player); } - if (sa.getRestrictions().isPwAbility()) { + if (sa.isPwAbility()) { return !sa.getHostCard().hasKeyword("CARDNAME's loyalty abilities can be activated at instant speed."); } return sa.isAbility() && sa.getRestrictions().isSorcerySpeed(); diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 6b515831aad..f9043497e96 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -72,9 +72,7 @@ public class GameAction { public final void resetActivationsPerTurn() { // Reset Activations per Turn for (final Card card : game.getCardsInGame()) { - for (final SpellAbility sa : card.getAllSpellAbilities()) { - sa.getRestrictions().resetTurnActivations(); - } + card.resetActivationsPerTurn(); } } diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 6dabca8a792..75a752c9593 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -267,6 +267,8 @@ public class Card extends GameEntity implements Comparable { private SpellAbility[] basicLandAbilities = new SpellAbility[MagicColor.WUBRG.length]; + private int planeswalkerAbilityActivated = 0; + // Enumeration for CMC request types public enum SplitCMCMode { CurrentSideCMC, @@ -6183,4 +6185,19 @@ public class Card extends GameEntity implements Comparable { return true; } + + public int getPlaneswalkerAbilityActivated() { + return planeswalkerAbilityActivated; + } + + public void addPlaneswalkerAbilityActivated() { + planeswalkerAbilityActivated++; + } + + public void resetActivationsPerTurn() { + planeswalkerAbilityActivated = 0; + for (final SpellAbility sa : this.getAllSpellAbilities()) { + sa.getRestrictions().resetTurnActivations(); + } + } } diff --git a/forge-game/src/main/java/forge/game/player/AchievementTracker.java b/forge-game/src/main/java/forge/game/player/AchievementTracker.java index 7f7d0d0d82e..58ff288510e 100644 --- a/forge-game/src/main/java/forge/game/player/AchievementTracker.java +++ b/forge-game/src/main/java/forge/game/player/AchievementTracker.java @@ -19,7 +19,7 @@ public class AchievementTracker { public void onSpellAbilityPlayed(final SpellAbility sa) { final Card card = sa.getHostCard(); - if (sa.getRestrictions().isPwAbility() && sa.hasParam("Ultimate")) { + if (sa.isPwAbility() && sa.hasParam("Ultimate")) { activatedUltimates.add(card.getName()); } if (card.determineColor().equals(ColorSet.ALL_COLORS)) { diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index 7d4fe9b8656..79d2bce6599 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -264,7 +264,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit } // without a target if (usesTargeting()) { return false; } - if (restrictions != null && restrictions.isPwAbility()) { + if (isPwAbility()) { return false; //Loyalty ability, not a mana ability. } if (isWrapper() && ((WrappedAbility) this).getTrigger().getMode() != TriggerType.TapsForMana) { @@ -438,6 +438,11 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit return hasParam("IsCurse"); } + public final boolean isPwAbility() { + // TODO try to check the Cost itself + return hasParam("Planeswalker"); + } + // begin - Input methods public Cost getPayCosts() { diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java index e992a95a90c..f57128a9ae1 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java @@ -153,10 +153,6 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { this.setColorToCheck(params.get("ActivationChosenColor")); } - if (params.containsKey("Planeswalker")) { - this.setPwAbility(true); - } - if (params.containsKey("IsPresent")) { this.setIsPresent(params.get("IsPresent")); if (params.containsKey("PresentCompare")) { @@ -482,7 +478,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { } } - if (this.isPwAbility()) { + if (sa.isPwAbility()) { if (!c.hasKeyword("CARDNAME's loyalty abilities can be activated at instant speed.") && !activator.canCastSorcery()) { return false; @@ -491,15 +487,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { final int initialLimit = c.hasKeyword("CARDNAME's loyalty abilities can be activated twice each turn rather than only once") ? 1 : 0; final int limits = c.getAmountOfKeyword("May activate CARDNAME's loyalty abilities once") + initialLimit; - int numActivates = 0; - for (final SpellAbility pwAbs : c.getAllSpellAbilities()) { - // check all abilities on card that have their planeswalker - // restriction set to confirm they haven't been activated - final SpellAbilityRestriction restrict = pwAbs.getRestrictions(); - if (restrict.isPwAbility()) { - numActivates += restrict.getNumberTurnActivations(); - } - } + int numActivates = c.getPlaneswalkerAbilityActivated(); if (numActivates > limits) { return false; } diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java index ed4cc49e41f..d51bb0069ac 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java @@ -90,7 +90,6 @@ public class SpellAbilityVariables implements Cloneable { this.manaSpent = sav.getManaSpent(); this.targetValidTargeting = sav.getTargetValidTargeting(); this.targetsSingleTarget = sav.targetsSingleTarget(); - this.pwAbility = sav.isPwAbility(); this.presenceCondition = sav.getPresenceCondition(); } @@ -197,9 +196,6 @@ public class SpellAbilityVariables implements Cloneable { /** The mana spent. */ private String manaSpent = ""; - /** The pw ability. */ - private boolean pwAbility = false; - /** The chosen colors string. */ private String chosenColors = null; @@ -674,25 +670,6 @@ public class SpellAbilityVariables implements Cloneable { this.shareAllColors = shareAllColors; } - /** - * Checks if is pw ability. - * - * @return the pwAbility - */ - public final boolean isPwAbility() { - return this.pwAbility; - } - - /** - * Sets the pw ability. - * - * @param pwAbility0 - * the new pw ability - */ - public final void setPwAbility(final boolean pwAbility0) { - this.pwAbility = pwAbility0; - } - /** * Checks if is player turn. * diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java index 58b910d01eb..bf0213da0f2 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java @@ -126,11 +126,11 @@ public class StaticAbilityCantBeCast { return false; } - if (params.containsKey("NonLoyalty") && (spellAbility.getRestrictions().isPwAbility())) { + if (params.containsKey("NonLoyalty") && spellAbility.isPwAbility()) { return false; } - if (params.containsKey("Loyalty") && !(spellAbility.getRestrictions().isPwAbility())) { + if (params.containsKey("Loyalty") && !spellAbility.isPwAbility()) { return false; } diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java index ff9ff5ffb51..d5f1786bbcf 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java @@ -394,7 +394,7 @@ public final class StaticAbilityContinuous { for (Card c : cardsIGainedAbilitiesFrom) { for (SpellAbility sa : c.getSpellAbilities()) { if (sa instanceof AbilityActivated) { - if (loyaltyAB && !sa.getRestrictions().isPwAbility()) { + if (loyaltyAB && !sa.isPwAbility()) { continue; } SpellAbility newSA = sa.copy(hostCard, false); diff --git a/forge-game/src/main/java/forge/game/zone/MagicStack.java b/forge-game/src/main/java/forge/game/zone/MagicStack.java index 016ab697d17..07242065e5a 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -133,16 +133,20 @@ public class MagicStack /* extends MyObservable */ implements Iterable