Card: store activations in Card

This commit is contained in:
Hans Mackowiak
2019-05-13 14:39:11 +00:00
committed by Michael Kamensky
parent 8f0457f0fa
commit 8e5e8e1759
11 changed files with 108 additions and 83 deletions

View File

@@ -1255,7 +1255,7 @@ public class ComputerUtil {
// returns true if the AI should stop using the ability // returns true if the AI should stop using the ability
public static boolean preventRunAwayActivations(final SpellAbility sa) { public static boolean preventRunAwayActivations(final SpellAbility sa) {
int activations = sa.getRestrictions().getNumberTurnActivations(); int activations = sa.getActivationsThisTurn();
if (sa.isTemporary()) { if (sa.isTemporary()) {
return MyRandom.getRandom().nextFloat() >= .95; // Abilities created by static abilities have no memory return MyRandom.getRandom().nextFloat() >= .95; // Abilities created by static abilities have no memory

View File

@@ -20,7 +20,6 @@ import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode; import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityRestriction;
import forge.game.spellability.TargetRestrictions; import forge.game.spellability.TargetRestrictions;
import forge.game.staticability.StaticAbility; import forge.game.staticability.StaticAbility;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -288,9 +287,8 @@ public class PumpAi extends PumpAiBase {
} }
if (sa.hasParam("ActivationNumberSacrifice")) { if (sa.hasParam("ActivationNumberSacrifice")) {
final SpellAbilityRestriction restrict = sa.getRestrictions();
final int sacActivations = Integer.parseInt(sa.getParam("ActivationNumberSacrifice").substring(2)); 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 // don't risk sacrificing a creature just to pump it
if (activations >= sacActivations - 1) { if (activations >= sacActivations - 1) {
return false; return false;

View File

@@ -324,12 +324,12 @@ public class GameCopier {
if (c.isPlaneswalker()) { if (c.isPlaneswalker()) {
for (SpellAbility sa : c.getAllSpellAbilities()) { for (SpellAbility sa : c.getAllSpellAbilities()) {
SpellAbilityRestriction restrict = sa.getRestrictions(); SpellAbilityRestriction restrict = sa.getRestrictions();
if (sa.isPwAbility() && restrict.getNumberTurnActivations() > 0) { int active = sa.getActivationsThisTurn();
if (sa.isPwAbility() && active > 0) {
SpellAbility newSa = findSAInCard(sa, newCard); SpellAbility newSa = findSAInCard(sa, newCard);
if (newSa != null) { if (newSa != null) {
for (int i = 0; i < restrict.getNumberTurnActivations(); i++) { for (int i = 0; i < active; i++) {
newSa.getRestrictions().abilityActivated(); newCard.addAbilityActivated(newSa);
newCard.addPlaneswalkerAbilityActivated();
} }
} }
} }

View File

@@ -269,6 +269,13 @@ public class Card extends GameEntity implements Comparable<Card> {
private int planeswalkerAbilityActivated = 0; private int planeswalkerAbilityActivated = 0;
private final Map<SpellAbility, Integer> numberTurnActivations = Maps.newHashMap();
private final Map<SpellAbility, Integer> numberGameActivations = Maps.newHashMap();
private final Table<SpellAbility, StaticAbility, Integer> numberTurnActivationsStatic = HashBasedTable.create();
private final Table<SpellAbility, StaticAbility, Integer> numberGameActivationsStatic = HashBasedTable.create();
// Enumeration for CMC request types // Enumeration for CMC request types
public enum SplitCMCMode { public enum SplitCMCMode {
CurrentSideCMC, CurrentSideCMC,
@@ -6186,6 +6193,62 @@ public class Card extends GameEntity implements Comparable<Card> {
return true; 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() { public int getPlaneswalkerAbilityActivated() {
return planeswalkerAbilityActivated; return planeswalkerAbilityActivated;
} }
@@ -6196,8 +6259,7 @@ public class Card extends GameEntity implements Comparable<Card> {
public void resetActivationsPerTurn() { public void resetActivationsPerTurn() {
planeswalkerAbilityActivated = 0; planeswalkerAbilityActivated = 0;
for (final SpellAbility sa : this.getAllSpellAbilities()) { numberTurnActivations.clear();
sa.getRestrictions().resetTurnActivations(); numberTurnActivationsStatic.clear();
}
} }
} }

View File

@@ -631,9 +631,6 @@ public class CardFactory {
} }
if (from.getRestrictions() != null) { if (from.getRestrictions() != null) {
to.setRestrictions((SpellAbilityRestriction) from.getRestrictions().copy()); to.setRestrictions((SpellAbilityRestriction) from.getRestrictions().copy());
if (!lki) {
to.getRestrictions().resetTurnActivations();
}
} }
if (from.getConditions() != null) { if (from.getConditions() != null) {
to.setConditions((SpellAbilityCondition) from.getConditions().copy()); to.setConditions((SpellAbilityCondition) from.getConditions().copy());
@@ -919,10 +916,6 @@ public class CardFactory {
if (sa.hasParam("SetColor") || sa.hasParam("Embalm") || sa.hasParam("Eternalize")) { if (sa.hasParam("SetColor") || sa.hasParam("Embalm") || sa.hasParam("Eternalize")) {
state.removeIntrinsicKeyword("Devoid"); state.removeIntrinsicKeyword("Devoid");
} }
for (SpellAbility ab : state.getSpellAbilities()) {
ab.getRestrictions().resetTurnActivations();
}
} }
// Dont copy the facedown state, make new one // Dont copy the facedown state, make new one

View File

@@ -83,6 +83,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
private Player targetingPlayer = null; private Player targetingPlayer = null;
private Card grantorCard = null; // card which grants the ability (equipment or owner of static ability that gave this one) 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 SpellAbility mayPlayOriginal = null;
private CardCollection splicedCards = 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. * Shortcut to see how many activations there were this turn.
*/ */
public int getActivationsThisTurn() { public int getActivationsThisTurn() {
return restrictions.getNumberTurnActivations(); return getHostCard().getAbilityActivatedThisTurn(this);
} }
public int getActivationsThisGame() {
return getHostCard().getAbilityActivatedThisGame(this);
}
public SpellAbilityCondition getConditions() { public SpellAbilityCondition getConditions() {
return conditions; return conditions;
@@ -1701,7 +1708,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
if (hasParam("ActivationNumberSacrifice")) { if (hasParam("ActivationNumberSacrifice")) {
String comp = getParam("ActivationNumberSacrifice"); String comp = getParam("ActivationNumberSacrifice");
int right = Integer.parseInt(comp.substring(2)); int right = Integer.parseInt(comp.substring(2));
int activationNum = getRestrictions().getNumberTurnActivations(); int activationNum = getActivationsThisTurn();
if (Expressions.compare(activationNum, comp, right)) { if (Expressions.compare(activationNum, comp, right)) {
SpellAbility deltrig = AbilityFactory.getAbility(hostCard.getSVar(getParam("ActivationResolveSub")), hostCard); SpellAbility deltrig = AbilityFactory.getAbility(hostCard.getSVar(getParam("ActivationResolveSub")), hostCard);
deltrig.setActivatingPlayer(activatingPlayer); deltrig.setActivatingPlayer(activatingPlayer);
@@ -1886,4 +1893,20 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
public void setPreventMap(final CardDamageMap map) { public void setPreventMap(final CardDamageMap map) {
preventMap = 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;
}
} }

View File

@@ -299,11 +299,11 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
return false; return false;
} }
if ((this.getActivationLimit() != -1) && (this.getNumberTurnActivations() >= this.getActivationLimit())) { if ((this.getActivationLimit() != -1) && (sa.getActivationsThisTurn() >= this.getActivationLimit())) {
return false; return false;
} }
if ((this.getGameActivationLimit() != -1) && (this.getNumberGameActivations() >= this.getGameActivationLimit())) { if ((this.getGameActivationLimit() != -1) && (sa.getActivationsThisGame() >= this.getGameActivationLimit())) {
return false; return false;
} }

View File

@@ -572,7 +572,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
int activationLimit = AbilityUtils.calculateAmount(c, limit, sa); int activationLimit = AbilityUtils.calculateAmount(c, limit, sa);
this.setActivationLimit(activationLimit); this.setActivationLimit(activationLimit);
if ((this.getActivationLimit() != -1) && (this.getNumberTurnActivations() >= this.getActivationLimit())) { if ((this.getActivationLimit() != -1) && (sa.getActivationsThisTurn() >= this.getActivationLimit())) {
return false; return false;
} }
} }
@@ -582,7 +582,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
int gameActivationLimit = AbilityUtils.calculateAmount(c, limit, sa); int gameActivationLimit = AbilityUtils.calculateAmount(c, limit, sa);
this.setGameActivationLimit(gameActivationLimit); this.setGameActivationLimit(gameActivationLimit);
if ((this.getGameActivationLimit() != -1) && (this.getNumberGameActivations() >= this.getGameActivationLimit())) { if ((this.getGameActivationLimit() != -1) && (sa.getActivationsThisGame() >= this.getGameActivationLimit())) {
return false; return false;
} }
} }

View File

@@ -66,8 +66,6 @@ public class SpellAbilityVariables implements Cloneable {
this.playerTurn = sav.isPlayerTurn(); this.playerTurn = sav.isPlayerTurn();
this.activationLimit = sav.getActivationLimit(); this.activationLimit = sav.getActivationLimit();
this.gameActivationLimit = sav.getGameActivationLimit(); this.gameActivationLimit = sav.getGameActivationLimit();
this.numberTurnActivations = sav.getNumberTurnActivations();
this.numberGameActivations = sav.getNumberGameActivations();
this.cardsInHand = sav.getCardsInHand(); this.cardsInHand = sav.getCardsInHand();
this.chosenColors = sav.getColorToCheck(); this.chosenColors = sav.getColorToCheck();
this.threshold = sav.isThreshold(); this.threshold = sav.isThreshold();
@@ -136,12 +134,6 @@ public class SpellAbilityVariables implements Cloneable {
/** The gameLimitToCheck to check. */ /** The gameLimitToCheck to check. */
private String gameLimitToCheck = null; 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. */ /** The n cards in hand. */
private int cardsInHand = -1; private int cardsInHand = -1;
@@ -382,47 +374,6 @@ public class SpellAbilityVariables implements Cloneable {
this.gameActivationLimit = limit; this.gameActivationLimit = limit;
} }
/**
* <p>
* abilityActivated.
* </p>
*/
public final void abilityActivated() {
this.numberTurnActivations++;
this.numberGameActivations++;
}
/**
* <p>
* Getter for the field <code>numberTurnActivations</code>.
* </p>
*
* @return a int.
*/
public final int getNumberTurnActivations() {
return this.numberTurnActivations;
}
/**
* <p>
* Getter for the field <code>numberTurnActivations</code>.
* </p>
*
* @return a int.
*/
public final int getNumberGameActivations() {
return this.numberGameActivations;
}
/**
* <p>
* resetTurnActivations.
* </p>
*/
public final void resetTurnActivations() {
this.numberTurnActivations = 0;
}
/** /**
* <p> * <p>
* Setter for the field <code>phases</code>. * Setter for the field <code>phases</code>.

View File

@@ -17,6 +17,7 @@
*/ */
package forge.game.staticability; package forge.game.staticability;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.GameCommand; import forge.GameCommand;
@@ -375,14 +376,12 @@ public final class StaticAbilityContinuous {
if (layer == StaticAbilityLayer.ABILITIES1 && params.containsKey("GainsAbilitiesOf")) { if (layer == StaticAbilityLayer.ABILITIES1 && params.containsKey("GainsAbilitiesOf")) {
final String[] valids = params.get("GainsAbilitiesOf").split(","); final String[] valids = params.get("GainsAbilitiesOf").split(",");
List<ZoneType> validZones = new ArrayList<ZoneType>(); List<ZoneType> validZones;
final boolean loyaltyAB = params.containsKey("GainsLoyaltyAbilities"); final boolean loyaltyAB = params.containsKey("GainsLoyaltyAbilities");
validZones.add(ZoneType.Battlefield);
if (params.containsKey("GainsAbilitiesOfZones")) { if (params.containsKey("GainsAbilitiesOfZones")) {
validZones.clear(); validZones = ZoneType.listValueOf(params.get("GainsAbilitiesOfZones"));
for (String s : params.get("GainsAbilitiesOfZones").split(",")) { } else {
validZones.add(ZoneType.smartValueOf(s)); validZones = ImmutableList.of(ZoneType.Battlefield);
}
} }
CardCollectionView cardsIGainedAbilitiesFrom = game.getCardsIn(validZones); CardCollectionView cardsIGainedAbilitiesFrom = game.getCardsIn(validZones);
@@ -403,6 +402,8 @@ public final class StaticAbilityContinuous {
newSA.getRestrictions().setLimitToCheck(params.get("GainsAbilitiesLimitPerTurn")); newSA.getRestrictions().setLimitToCheck(params.get("GainsAbilitiesLimitPerTurn"));
} }
newSA.setOriginalHost(c); 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.setIntrinsic(false);
newSA.setTemporary(true); newSA.setTemporary(true);
addFullAbs.add(newSA); addFullAbs.add(newSA);

View File

@@ -137,10 +137,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
if (!ability.isCopied()) { if (!ability.isCopied()) {
// Copied abilities aren't activated, so they shouldn't change these values // Copied abilities aren't activated, so they shouldn't change these values
ability.getRestrictions().abilityActivated(); source.addAbilityActivated(ability);
if (ability.isPwAbility()) {
source.addPlaneswalkerAbilityActivated();
}
ability.checkActivationResloveSubs(); ability.checkActivationResloveSubs();
} }