diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtil.java b/forge-ai/src/main/java/forge/ai/ComputerUtil.java index bd28641348a..006ddc17b7e 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtil.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtil.java @@ -1255,7 +1255,7 @@ public class ComputerUtil { // returns true if the AI should stop using the ability public static boolean preventRunAwayActivations(final SpellAbility sa) { - int activations = sa.getRestrictions().getNumberTurnActivations(); + int activations = sa.getActivationsThisTurn(); if (sa.isTemporary()) { return MyRandom.getRandom().nextFloat() >= .95; // Abilities created by static abilities have no memory diff --git a/forge-ai/src/main/java/forge/ai/ability/PumpAi.java b/forge-ai/src/main/java/forge/ai/ability/PumpAi.java index 928a2ed77c9..f71604bf98a 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PumpAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PumpAi.java @@ -20,7 +20,6 @@ import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.player.PlayerActionConfirmMode; import forge.game.spellability.SpellAbility; -import forge.game.spellability.SpellAbilityRestriction; import forge.game.spellability.TargetRestrictions; import forge.game.staticability.StaticAbility; import forge.game.zone.ZoneType; @@ -288,9 +287,8 @@ public class PumpAi extends PumpAiBase { } if (sa.hasParam("ActivationNumberSacrifice")) { - final SpellAbilityRestriction restrict = sa.getRestrictions(); final int sacActivations = Integer.parseInt(sa.getParam("ActivationNumberSacrifice").substring(2)); - final int activations = restrict.getNumberTurnActivations(); + final int activations = sa.getActivationsThisTurn(); // don't risk sacrificing a creature just to pump it if (activations >= sacActivations - 1) { return false; 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 72aedd7513e..0664b2c767d 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -324,12 +324,12 @@ public class GameCopier { if (c.isPlaneswalker()) { for (SpellAbility sa : c.getAllSpellAbilities()) { SpellAbilityRestriction restrict = sa.getRestrictions(); - if (sa.isPwAbility() && restrict.getNumberTurnActivations() > 0) { + int active = sa.getActivationsThisTurn(); + if (sa.isPwAbility() && active > 0) { SpellAbility newSa = findSAInCard(sa, newCard); if (newSa != null) { - for (int i = 0; i < restrict.getNumberTurnActivations(); i++) { - newSa.getRestrictions().abilityActivated(); - newCard.addPlaneswalkerAbilityActivated(); + for (int i = 0; i < active; i++) { + newCard.addAbilityActivated(newSa); } } } 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 75a752c9593..4d599db2b1e 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -269,6 +269,13 @@ public class Card extends GameEntity implements Comparable { private int planeswalkerAbilityActivated = 0; + private final Map numberTurnActivations = Maps.newHashMap(); + private final Map numberGameActivations = Maps.newHashMap(); + + private final Table numberTurnActivationsStatic = HashBasedTable.create(); + private final Table numberGameActivationsStatic = HashBasedTable.create(); + + // Enumeration for CMC request types public enum SplitCMCMode { CurrentSideCMC, @@ -6186,6 +6193,62 @@ public class Card extends GameEntity implements Comparable { return true; } + public void addAbilityActivated(SpellAbility ability) { + SpellAbility original = ability.getOriginalAbility(); + if (original == null) { + original = ability; + } + + int turnActivated = getAbilityActivatedThisTurn(ability); + int gameActivated = getAbilityActivatedThisGame(ability); + if (ability.getGrantorStatic() != null) { + numberTurnActivationsStatic.put(original, ability.getGrantorStatic(), turnActivated + 1); + numberGameActivationsStatic.put(original, ability.getGrantorStatic(), gameActivated + 1); + } else { + numberTurnActivations.put(original, turnActivated + 1); + numberGameActivations.put(original, gameActivated + 1); + } + + if (ability.isPwAbility()) { + addPlaneswalkerAbilityActivated(); + } + } + + public int getAbilityActivatedThisTurn(SpellAbility ability) { + SpellAbility original = ability.getOriginalAbility(); + if (original == null) { + original = ability; + } + + if (ability.getGrantorStatic() != null) { + if (numberTurnActivationsStatic.contains(original, ability.getGrantorStatic())) { + return numberTurnActivationsStatic.get(original, ability.getGrantorStatic()); + } + return 0; + } + return numberTurnActivations.containsKey(original) ? numberTurnActivations.get(original) : 0; + } + + public int getAbilityActivatedThisGame(SpellAbility ability) { + SpellAbility original = ability.getOriginalAbility(); + if (original == null) { + original = ability; + } + + if (ability.getGrantorStatic() != null) { + if (numberGameActivationsStatic.contains(original, ability.getGrantorStatic())) { + return numberGameActivationsStatic.get(original, ability.getGrantorStatic()); + } + return 0; + } + return numberGameActivations.containsKey(original) ? numberGameActivations.get(original) : 0; + } + + public void resetTurnActivations() { + numberTurnActivations.clear(); + numberTurnActivationsStatic.clear(); + } + public int getPlaneswalkerAbilityActivated() { return planeswalkerAbilityActivated; } @@ -6196,8 +6259,7 @@ public class Card extends GameEntity implements Comparable { public void resetActivationsPerTurn() { planeswalkerAbilityActivated = 0; - for (final SpellAbility sa : this.getAllSpellAbilities()) { - sa.getRestrictions().resetTurnActivations(); - } + numberTurnActivations.clear(); + numberTurnActivationsStatic.clear(); } } diff --git a/forge-game/src/main/java/forge/game/card/CardFactory.java b/forge-game/src/main/java/forge/game/card/CardFactory.java index 80453e3a6d5..fb2abfc74a9 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -631,9 +631,6 @@ public class CardFactory { } if (from.getRestrictions() != null) { to.setRestrictions((SpellAbilityRestriction) from.getRestrictions().copy()); - if (!lki) { - to.getRestrictions().resetTurnActivations(); - } } if (from.getConditions() != null) { to.setConditions((SpellAbilityCondition) from.getConditions().copy()); @@ -919,10 +916,6 @@ public class CardFactory { if (sa.hasParam("SetColor") || sa.hasParam("Embalm") || sa.hasParam("Eternalize")) { state.removeIntrinsicKeyword("Devoid"); } - - for (SpellAbility ab : state.getSpellAbilities()) { - ab.getRestrictions().resetTurnActivations(); - } } // Dont copy the facedown state, make new one 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 79d2bce6599..6a790b4f343 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -83,6 +83,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit private Player targetingPlayer = null; private Card grantorCard = null; // card which grants the ability (equipment or owner of static ability that gave this one) + private SpellAbility grantorOriginal = null; + private StaticAbility grantorStatic = null; + private SpellAbility mayPlayOriginal = null; private CardCollection splicedCards = null; @@ -463,8 +466,12 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit * Shortcut to see how many activations there were this turn. */ public int getActivationsThisTurn() { - return restrictions.getNumberTurnActivations(); + return getHostCard().getAbilityActivatedThisTurn(this); } + public int getActivationsThisGame() { + return getHostCard().getAbilityActivatedThisGame(this); + } + public SpellAbilityCondition getConditions() { return conditions; @@ -1701,7 +1708,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit if (hasParam("ActivationNumberSacrifice")) { String comp = getParam("ActivationNumberSacrifice"); int right = Integer.parseInt(comp.substring(2)); - int activationNum = getRestrictions().getNumberTurnActivations(); + int activationNum = getActivationsThisTurn(); if (Expressions.compare(activationNum, comp, right)) { SpellAbility deltrig = AbilityFactory.getAbility(hostCard.getSVar(getParam("ActivationResolveSub")), hostCard); deltrig.setActivatingPlayer(activatingPlayer); @@ -1886,4 +1893,20 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit public void setPreventMap(final CardDamageMap map) { preventMap = map; } + + public SpellAbility getOriginalAbility() { + return grantorOriginal; + } + + public void setOriginalAbility(final SpellAbility sa) { + grantorOriginal = sa; + } + + public StaticAbility getGrantorStatic() { + return grantorStatic; + } + + public void setGrantorStatic(final StaticAbility st) { + grantorStatic = st; + } } diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityCondition.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityCondition.java index 31cc0e81727..c53c34bd3ce 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityCondition.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityCondition.java @@ -299,11 +299,11 @@ public class SpellAbilityCondition extends SpellAbilityVariables { return false; } - if ((this.getActivationLimit() != -1) && (this.getNumberTurnActivations() >= this.getActivationLimit())) { + if ((this.getActivationLimit() != -1) && (sa.getActivationsThisTurn() >= this.getActivationLimit())) { return false; } - if ((this.getGameActivationLimit() != -1) && (this.getNumberGameActivations() >= this.getGameActivationLimit())) { + if ((this.getGameActivationLimit() != -1) && (sa.getActivationsThisGame() >= this.getGameActivationLimit())) { return false; } 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 f57128a9ae1..bc3e6649da4 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java @@ -572,7 +572,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { int activationLimit = AbilityUtils.calculateAmount(c, limit, sa); this.setActivationLimit(activationLimit); - if ((this.getActivationLimit() != -1) && (this.getNumberTurnActivations() >= this.getActivationLimit())) { + if ((this.getActivationLimit() != -1) && (sa.getActivationsThisTurn() >= this.getActivationLimit())) { return false; } } @@ -582,7 +582,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { int gameActivationLimit = AbilityUtils.calculateAmount(c, limit, sa); this.setGameActivationLimit(gameActivationLimit); - if ((this.getGameActivationLimit() != -1) && (this.getNumberGameActivations() >= this.getGameActivationLimit())) { + if ((this.getGameActivationLimit() != -1) && (sa.getActivationsThisGame() >= this.getGameActivationLimit())) { 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 d51bb0069ac..7f8c32e6f74 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java @@ -66,8 +66,6 @@ public class SpellAbilityVariables implements Cloneable { this.playerTurn = sav.isPlayerTurn(); this.activationLimit = sav.getActivationLimit(); this.gameActivationLimit = sav.getGameActivationLimit(); - this.numberTurnActivations = sav.getNumberTurnActivations(); - this.numberGameActivations = sav.getNumberGameActivations(); this.cardsInHand = sav.getCardsInHand(); this.chosenColors = sav.getColorToCheck(); this.threshold = sav.isThreshold(); @@ -136,12 +134,6 @@ public class SpellAbilityVariables implements Cloneable { /** The gameLimitToCheck to check. */ private String gameLimitToCheck = null; - /** The number turn activations. */ - private int numberTurnActivations = 0; - - /** The number game activations. */ - private int numberGameActivations = 0; - /** The n cards in hand. */ private int cardsInHand = -1; @@ -382,47 +374,6 @@ public class SpellAbilityVariables implements Cloneable { this.gameActivationLimit = limit; } - /** - *

- * abilityActivated. - *

- */ - public final void abilityActivated() { - this.numberTurnActivations++; - this.numberGameActivations++; - } - - /** - *

- * Getter for the field numberTurnActivations. - *

- * - * @return a int. - */ - public final int getNumberTurnActivations() { - return this.numberTurnActivations; - } - - /** - *

- * Getter for the field numberTurnActivations. - *

- * - * @return a int. - */ - public final int getNumberGameActivations() { - return this.numberGameActivations; - } - - /** - *

- * resetTurnActivations. - *

- */ - public final void resetTurnActivations() { - this.numberTurnActivations = 0; - } - /** *

* Setter for the field phases. 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 d5f1786bbcf..6097d7c0669 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java @@ -17,6 +17,7 @@ */ package forge.game.staticability; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import forge.GameCommand; @@ -375,14 +376,12 @@ public final class StaticAbilityContinuous { if (layer == StaticAbilityLayer.ABILITIES1 && params.containsKey("GainsAbilitiesOf")) { final String[] valids = params.get("GainsAbilitiesOf").split(","); - List validZones = new ArrayList(); + List validZones; final boolean loyaltyAB = params.containsKey("GainsLoyaltyAbilities"); - validZones.add(ZoneType.Battlefield); if (params.containsKey("GainsAbilitiesOfZones")) { - validZones.clear(); - for (String s : params.get("GainsAbilitiesOfZones").split(",")) { - validZones.add(ZoneType.smartValueOf(s)); - } + validZones = ZoneType.listValueOf(params.get("GainsAbilitiesOfZones")); + } else { + validZones = ImmutableList.of(ZoneType.Battlefield); } CardCollectionView cardsIGainedAbilitiesFrom = game.getCardsIn(validZones); @@ -403,6 +402,8 @@ public final class StaticAbilityContinuous { newSA.getRestrictions().setLimitToCheck(params.get("GainsAbilitiesLimitPerTurn")); } newSA.setOriginalHost(c); + newSA.setOriginalAbility(sa); // need to be set to get the Once Per turn Clause correct + newSA.setGrantorStatic(stAb); newSA.setIntrinsic(false); newSA.setTemporary(true); addFullAbs.add(newSA); 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 07242065e5a..7a814cc6a4f 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -137,10 +137,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable