diff --git a/forge-ai/src/main/java/forge/ai/AIDeckStatistics.java b/forge-ai/src/main/java/forge/ai/AiDeckStatistics.java similarity index 90% rename from forge-ai/src/main/java/forge/ai/AIDeckStatistics.java rename to forge-ai/src/main/java/forge/ai/AiDeckStatistics.java index caf6a65e1f3..b7ac1be0d85 100644 --- a/forge-ai/src/main/java/forge/ai/AIDeckStatistics.java +++ b/forge-ai/src/main/java/forge/ai/AiDeckStatistics.java @@ -13,7 +13,7 @@ import java.util.List; import java.util.Map; -public class AIDeckStatistics { +public class AiDeckStatistics { public float averageCMC = 0; // TODO implement this. Use a numerically stable algorithm from @@ -24,9 +24,9 @@ public class AIDeckStatistics { // in WUBRGC order from ManaCost.getColorShardCounts() public int[] maxPips = null; -// public int[] numSources = new int[6]; + // public int[] numSources = new int[6]; public int numLands = 0; - public AIDeckStatistics(float averageCMC, float stddevCMC, int maxCost, int maxColoredCost, int[] maxPips, int numLands) { + public AiDeckStatistics(float averageCMC, float stddevCMC, int maxCost, int maxColoredCost, int[] maxPips, int numLands) { this.averageCMC = averageCMC; this.stddevCMC = stddevCMC; this.maxCost = maxCost; @@ -35,7 +35,7 @@ public AIDeckStatistics(float averageCMC, float stddevCMC, int maxCost, int maxC this.numLands = numLands; } - public static AIDeckStatistics fromCards(List cards) { + public static AiDeckStatistics fromCards(List cards) { int totalCMC = 0; int totalCount = 0; int numLands = 0; @@ -75,7 +75,7 @@ public static AIDeckStatistics fromCards(List cards) { } - return new AIDeckStatistics(totalCount == 0 ? 0 : totalCMC / (float)totalCount, + return new AiDeckStatistics(totalCount == 0 ? 0 : totalCMC / (float)totalCount, 0, // TODO use https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance maxCost, maxColoredCost, @@ -85,7 +85,7 @@ public static AIDeckStatistics fromCards(List cards) { } - public static AIDeckStatistics fromDeck(Deck deck, Player player) { + public static AiDeckStatistics fromDeck(Deck deck, Player player) { List cardlist = new ArrayList<>(); for (final Map.Entry deckEntry : deck) { switch (deckEntry.getKey()) { @@ -104,7 +104,7 @@ public static AIDeckStatistics fromDeck(Deck deck, Player player) { return fromCards(cardlist); } - public static AIDeckStatistics fromPlayer(Player player) { + public static AiDeckStatistics fromPlayer(Player player) { Deck deck = player.getRegisteredPlayer().getDeck(); if (deck.isEmpty()) { // we're in a test or some weird match, search through the hand and library and build the decklist diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameStateEvaluator.java b/forge-ai/src/main/java/forge/ai/simulation/GameStateEvaluator.java index eeab7621bb0..2c2bf24ae83 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameStateEvaluator.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameStateEvaluator.java @@ -1,6 +1,6 @@ package forge.ai.simulation; -import forge.ai.AIDeckStatistics; +import forge.ai.AiDeckStatistics; import forge.ai.CreatureEvaluator; import forge.card.mana.ManaAtom; import forge.game.Game; @@ -133,7 +133,7 @@ private Score getScoreForGameStateImpl(Game game, Player aiPlayer) { score -= 2* opponentLife / (game.getPlayers().size() - 1); // evaluate mana base quality - score += evalManaBase(game, aiPlayer, AIDeckStatistics.fromPlayer(aiPlayer)); + score += evalManaBase(game, aiPlayer, AiDeckStatistics.fromPlayer(aiPlayer)); // TODO deal with opponents. Do we want to use perfect information to evaluate their manabase? //int opponentManaScore = 0; //for (Player opponent : aiPlayer.getOpponents()) { @@ -173,7 +173,7 @@ private Score getScoreForGameStateImpl(Game game, Player aiPlayer) { return new Score(score, summonSickScore); } - public int evalManaBase(Game game, Player player, AIDeckStatistics statistics) { + public int evalManaBase(Game game, Player player, AiDeckStatistics statistics) { // TODO should these be fixed quantities or should they be linear out of like 1000/(desired - total)? int value = 0; // get the colors of mana we can produce and the maximum number of pips 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 eee430d863f..fff4ec72284 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -100,7 +100,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr private Map mustBlockCards = Maps.newHashMap(); private List blockedThisTurn = Lists.newArrayList(); private List blockedByThisTurn = Lists.newArrayList(); - private Map chosenMap = Maps.newHashMap(); private CardCollection untilLeavesBattlefield = new CardCollection(); @@ -113,8 +112,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr private GameEntity entityAttachedTo; - private Map mayPlay = Maps.newHashMap(); - // changes by AF animate and continuous static effects protected CardChangedType changedTypeByText; // Layer 3 by Text Change @@ -160,6 +157,8 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr private final Table> changedSVars = TreeBasedTable.create(); + private Map mayPlay = Maps.newHashMap(); + private final Map mayLook = Maps.newHashMap(); private final PlayerCollection mayLookFaceDownExile = new PlayerCollection(); private final PlayerCollection mayLookTemp = new PlayerCollection(); @@ -200,9 +199,8 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr private boolean unearthed; private boolean ringbearer; private boolean monstrous; - private boolean renowned; - private boolean solved = false; + private boolean solved; private Long suspectedTimestamp = null; private StaticAbility suspectedStatic = null; @@ -304,6 +302,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr private String currentRoom = null; private String sector = null; private String chosenSector = null; + private Map chosenMap = Maps.newHashMap(); // points to the host that exiled this card, usually the one that has this object it its exiledCards field // however it could also be a different card which isn't an error but means the exiling SA was gained @@ -331,6 +330,8 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr // breaking when the LKI object is changed to a different card state. private int lkiCMC = -1; + private CombatLki combatLKI; + private CardRules cardRules; private final CardView view; @@ -353,8 +354,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr private final Table> chosenModesYourCombatStatic = HashBasedTable.create(); private final Table> chosenModesYourLastCombatStatic = HashBasedTable.create(); - private CombatLki combatLKI; - private ReplacementEffect shieldCounterReplaceDamage = null; private ReplacementEffect shieldCounterReplaceDestroy = null; private ReplacementEffect stunCounterReplaceUntap = null; @@ -8235,6 +8234,5 @@ public void copyFrom(Card in) { this.changedCardNames.putAll(in.changedCardNames); setChangedCardTraits(in.getChangedCardTraits()); - } } diff --git a/forge-game/src/main/java/forge/game/card/CardState.java b/forge-game/src/main/java/forge/game/card/CardState.java index 9947641d33a..462d323815f 100644 --- a/forge-game/src/main/java/forge/game/card/CardState.java +++ b/forge-game/src/main/java/forge/game/card/CardState.java @@ -211,7 +211,6 @@ public void setFunctionalVariantName(String functionalVariantName) { view.setFunctionalVariantName(functionalVariantName); } - public final int getBasePower() { return basePower; } @@ -263,7 +262,6 @@ public final void setBaseDefense(final String string) { public Set getAttractionLights() { return this.attractionLights; } - public final void setAttractionLights(Set attractionLights) { this.attractionLights = attractionLights; view.updateAttractionLights(this); @@ -492,14 +490,6 @@ public final void clearStaticAbilities() { staticAbilities.clear(); } - public final String getImageKey() { - return imageKey; - } - public final void setImageKey(final String imageFilename0) { - imageKey = imageFilename0; - view.updateImageKey(this); - } - public FCollectionView getReplacementEffects() { FCollection result = new FCollection<>(replacementEffects); CardTypeView type = getTypeWithChanges(); @@ -752,6 +742,14 @@ public void setSetCode(String setCode0) { view.updateSetCode(this); } + public final String getImageKey() { + return imageKey; + } + public final void setImageKey(final String imageFilename0) { + imageKey = imageFilename0; + view.updateImageKey(this); + } + /* (non-Javadoc) * @see forge.game.GameObject#hasProperty(java.lang.String, forge.game.player.Player, forge.game.card.Card, forge.game.spellability.SpellAbility) */ diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index e03ae69a7c0..5bc8147b807 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -78,61 +78,58 @@ public class Player extends GameEntity implements Comparable { ZoneType.Sideboard, ZoneType.PlanarDeck, ZoneType.SchemeDeck, ZoneType.AttractionDeck, ZoneType.Junkyard, ZoneType.Merged, ZoneType.Subgame, ZoneType.None)); - private final Map commanderDamage = Maps.newHashMap(); - private int life = 20; private int startingLife = 20; private int lifeStartedThisTurnWith = startingLife; - private int spellsCastThisTurn; - private int spellsCastThisGame; - private int spellsCastLastTurn; - private List spellsCastSinceBeginningOfLastTurn = Lists.newArrayList(); - private int landsPlayedThisTurn; - private int landsPlayedLastTurn; - private int investigatedThisTurn; - private int surveilThisTurn; private int lifeLostThisTurn; private int lifeLostLastTurn; private int lifeGainedThisTurn; private int lifeGainedTimesThisTurn; private int lifeGainedByTeamThisTurn; - private int committedCrimeThisTurn; - private List diceRollsThisTurn = Lists.newArrayList(); - private int expentThisTurn; - private int numManaShards; - private int numPowerSurgeLands; - private int numLibrarySearchedOwn; //The number of times this player has searched his library + private int maxHandSize = 7; + private int startingHandSize = 7; + private boolean unlimitedHandSize = false; + private Card lastDrawnCard; private int numDrawnThisTurn; private int numDrawnLastTurn; private int numDrawnThisDrawStep; - private int numRollsThisTurn; + private int numCardsInHandStartedThisTurnWith; private int numExploredThisTurn; private int numTokenCreatedThisTurn; private int numForetoldThisTurn; - private int numCardsInHandStartedThisTurnWith; + private int landsPlayedThisTurn; + private int landsPlayedLastTurn; + private int numPowerSurgeLands; + private int spellsCastThisTurn; + private int spellsCastThisGame; + private int spellsCastLastTurn; + private List spellsCastSinceBeginningOfLastTurn = Lists.newArrayList(); + private int investigatedThisTurn; + private int surveilThisTurn; + private int committedCrimeThisTurn; + private int numRollsThisTurn; + private List diceRollsThisTurn = Lists.newArrayList(); + private int expentThisTurn; + private int numLibrarySearchedOwn; //The number of times this player has searched his library private int venturedThisTurn; - private int maxHandSize = 7; - private int startingHandSize = 7; - private boolean unlimitedHandSize = false; - private Card lastDrawnCard; + private int descended = 0; + private boolean revolt = false; + private int numRingTemptedYou = 0; private Card ringBearer, theRing; - private String namedCard = ""; + + private List discardedThisTurn = new ArrayList<>(); + private List sacrificedThisTurn = new ArrayList<>(); private int simultaneousDamage = 0; private int lastTurnNr = 0; - private int numRingTemptedYou = 0; + + private String namedCard = ""; private final Map> notes = Maps.newHashMap(); private final Map notedNum = Maps.newHashMap(); private final Map draftNotes = Maps.newHashMap(); - private boolean revolt = false; - private int descended = 0; - - private List sacrificedThisTurn = new ArrayList<>(); - private List discardedThisTurn = new ArrayList<>(); - /** A list of tokens not in play, but on their way. * This list is kept in order to not break ETB-replacement * on tokens. */ @@ -141,11 +138,10 @@ public class Player extends GameEntity implements Comparable { private KeywordCollection keywords = new KeywordCollection(); // stores the keywords created by static abilities private final Table storedKeywords = TreeBasedTable.create(); + private Table changedKeywords = TreeBasedTable.create(); private Map staticAbilities = Maps.newHashMap(); - private Table changedKeywords = TreeBasedTable.create(); - private ManaPool manaPool = new ManaPool(this); private Map> attackedThisTurn = new HashMap<>(); private List attackedPlayersLastTurn = new ArrayList<>(); private List attackedPlayersThisCombat = new ArrayList<>(); @@ -153,7 +149,6 @@ public class Player extends GameEntity implements Comparable { private boolean beenDealtCombatDamageSinceLastTurn = false; private boolean tappedLandForManaThisTurn = false; - private List completedDungeons = new ArrayList<>(); private final Map zones = Maps.newEnumMap(ZoneType.class); private List extraZones = null; @@ -165,30 +160,37 @@ public class Player extends GameEntity implements Comparable { private CardCollection currentPlanes = new CardCollection(); private CardCollection planeswalkedToThisTurn = new CardCollection(); - private PlayerStatistics stats = new PlayerStatistics(); - private PlayerController controller; + private Card activeScheme = null; private NavigableMap> controlledBy = Maps.newTreeMap(); - private NavigableMap controlledWhileSearching = Maps.newTreeMap(); + private int numManaShards; + private int teamNumber = -1; - private Card activeScheme = null; - private final CardCollection commanders = new CardCollection(); - private final Map commanderCast = Maps.newHashMap(); - private DetachedCardEffect commanderEffect = null; + + private PlayerController controller; private final Game game; + private boolean triedToDrawFromEmptyLibrary = false; private CardCollection lostOwnership = new CardCollection(); private CardCollection gainedOwnership = new CardCollection(); + + private ManaPool manaPool = new ManaPool(this); private int numManaConversion = 0; // The SA currently being paid for private Deque paidForStack = new ArrayDeque<>(); + private List completedDungeons = new ArrayList<>(); + + private final CardCollection commanders = new CardCollection(); + private final Map commanderCast = Maps.newHashMap(); + private final Map commanderDamage = Maps.newHashMap(); + private DetachedCardEffect commanderEffect = null; + private Card monarchEffect; private Card initiativeEffect; private Card blessingEffect; - private Card radiationEffect; private Card keywordEffect; @@ -200,6 +202,8 @@ public class Player extends GameEntity implements Comparable { private NavigableMap declaresAttackers = Maps.newTreeMap(); private NavigableMap declaresBlockers = Maps.newTreeMap(); + private PlayerStatistics stats = new PlayerStatistics(); + private final AchievementTracker achievementTracker = new AchievementTracker(); private final PlayerView view; @@ -278,7 +282,6 @@ public void setSchemeInMotion(SpellAbility cause) { return; } - // Replacement effects if (game.getReplacementHandler().run(ReplacementType.SetInMotion, AbilityKey.mapFromAffected(this)) != ReplacementResult.NotReplaced) { return; } @@ -480,7 +483,6 @@ public final boolean gainLife(int lifeGain, final Card source, final SpellAbilit p.addLifeGainedByTeamThisTurn(lifeGain); } - // Run triggers final Map runParams = AbilityKey.mapFromPlayer(this); runParams.put(AbilityKey.LifeAmount, lifeGain); runParams.put(AbilityKey.Source, source); @@ -546,7 +548,6 @@ public final int loseLife(int toLose, final boolean damage, final boolean manaBu lifeLostThisTurn += toLose; - // Run triggers final Map runParams = AbilityKey.mapFromPlayer(this); runParams.put(AbilityKey.LifeAmount, toLose); runParams.put(AbilityKey.FirstTime, firstLost); @@ -602,12 +603,11 @@ public final boolean payLife(final int lifePayment, final SpellAbility cause, fi return false; default: break; - }; + } final int lost = loseLife(lifePayment, false, false); cause.setPaidLife(lifePayment); - // Run triggers final Map runParams = AbilityKey.mapFromPlayer(this); runParams.put(AbilityKey.LifeAmount, lifePayment); game.getTriggerHandler().runTrigger(TriggerType.PayLife, runParams, false); @@ -3889,7 +3889,6 @@ public void commitCrime() { //boolean firstTime = this.commitedCrimeThisTurn == 0; committedCrimeThisTurn++; - // Run triggers final Map runParams = AbilityKey.mapFromPlayer(this); game.getTriggerHandler().runTrigger(TriggerType.CommitCrime, runParams, false); diff --git a/forge-game/src/main/java/forge/game/player/PlayerActionConfirmMode.java b/forge-game/src/main/java/forge/game/player/PlayerActionConfirmMode.java index 355d309f6d9..4801d4c2048 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerActionConfirmMode.java +++ b/forge-game/src/main/java/forge/game/player/PlayerActionConfirmMode.java @@ -6,7 +6,6 @@ */ public enum PlayerActionConfirmMode { Random, - // BraidOfFire, FromOpeningHand, ChangeZoneToAltDestination, ChangeZoneFromAltSource, 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 480c59dcb6f..a6fed29f646 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -118,7 +118,7 @@ public static class EmptySa extends SpellAbility { private boolean basicSpell = true; private Trigger triggerObj; private boolean optionalTrigger = false; - private ReplacementEffect replacementEffect = null; + private ReplacementEffect replacementEffect; private int sourceTrigger = -1; private List triggerRemembered = Lists.newArrayList(); @@ -274,6 +274,25 @@ public void setKeyword(final KeywordInterface kw) { } } + // If this is not null, then ability was made in a factory + public ApiType getApi() { + return api; + } + public void setApi(ApiType apiType) { + api = apiType; + } + + public SpellAbility findSubAbilityByType(ApiType apiType) { + SpellAbility sub = this.getSubAbility(); + while (sub != null) { + if (apiType.equals(sub.getApi())) { + return sub; + } + sub = sub.getSubAbility(); + } + return null; + } + public boolean canThisProduce(final String s) { AbilityManaPart mp = getManaPart(); if (mp != null && metConditions() && mp.canProduce(s, this)) { @@ -509,6 +528,23 @@ public void setManaCostBeingPaid(ManaCostBeingPaid costBeingPaid) { manaCostBeingPaid = costBeingPaid; } + public Iterable getOptionalCosts() { + return optionalCosts; + } + public final void addOptionalCost(OptionalCost cost) { + // Optional costs are added to swallow copies of original SAs, + // Thus, to protect the original's set from changes, we make a copy right here. + optionalCosts = EnumSet.copyOf(optionalCosts); + optionalCosts.add(cost); + if (!cost.getPip().isEmpty()) { + pipsToReduce.get().add(cost.getPip()); + } + } + public boolean isOptionalCostPaid(OptionalCost cost) { + SpellAbility saRoot = getRootAbility(); + return saRoot.optionalCosts.contains(cost); + } + public boolean isSpell() { return false; } public boolean isAbility() { return true; } public boolean isActivatedAbility() { return false; } @@ -568,23 +604,141 @@ public boolean isEpic() { return sub != null && sub.hasParam("Epic"); } - // If this is not null, then ability was made in a factory - public ApiType getApi() { - return api; + public boolean isBargained() { + return isOptionalCostPaid(OptionalCost.Bargain); } - public void setApi(ApiType apiType) { - api = apiType; + + public boolean isBuyback() { + return isOptionalCostPaid(OptionalCost.Buyback); } - public SpellAbility findSubAbilityByType(ApiType apiType) { - SpellAbility sub = this.getSubAbility(); - while (sub != null) { - if (apiType.equals(sub.getApi())) { - return sub; - } - sub = sub.getSubAbility(); + public boolean isKicked() { + return isOptionalCostPaid(OptionalCost.Kicker1) || isOptionalCostPaid(OptionalCost.Kicker2) || + getRootAbility().getOptionalKeywordAmount(Keyword.MULTIKICKER) > 0; + } + + public boolean isEntwine() { + return isOptionalCostPaid(OptionalCost.Entwine); + } + + public boolean isJumpstart() { + return isOptionalCostPaid(OptionalCost.Jumpstart); + } + + public final boolean isBestow() { + return isAlternativeCost(AlternativeCost.Bestow); + } + + public final boolean isBlitz() { + return isAlternativeCost(AlternativeCost.Blitz); + } + + public final boolean isDash() { + return isAlternativeCost(AlternativeCost.Dash); + } + + public final boolean isDisturb() { + return isAlternativeCost(AlternativeCost.Disturb); + } + + public final boolean isEscape() { + return isAlternativeCost(AlternativeCost.Escape); + } + + public final boolean isEvoke() { + return isAlternativeCost(AlternativeCost.Evoke); + } + + public final boolean isFreerunning() { + return isAlternativeCost(AlternativeCost.Freerunning); + } + + public final boolean isImpending() { + return isAlternativeCost(AlternativeCost.Impending); + } + + public final boolean isMadness() { + return isAlternativeCost(AlternativeCost.Madness); + } + + public final boolean isMutate() { + return isAlternativeCost(AlternativeCost.Mutate); + } + + public final boolean isProwl() { + return isAlternativeCost(AlternativeCost.Prowl); + } + + public final boolean isSurged() { + return isAlternativeCost(AlternativeCost.Surge); + } + + public final boolean isSpectacle() { + return isAlternativeCost(AlternativeCost.Spectacle); + } + + public boolean isFlashback() { + return this.isAlternativeCost(AlternativeCost.Flashback); + } + + public boolean isForetelling() { + return false; + } + public boolean isForetold() { + return this.isAlternativeCost(AlternativeCost.Foretold); + } + + public boolean isPlotting() { + return false; + } + + public boolean isOutlast() { + return isKeyword(Keyword.OUTLAST); + } + + public boolean isCraft() { + return isKeyword(Keyword.CRAFT); + } + + public boolean isCrew() { + return isKeyword(Keyword.CREW); + } + + public boolean isEquip() { + return isKeyword(Keyword.EQUIP); + } + + /** + * @return the aftermath + */ + public boolean isAftermath() { + return aftermath; + } + + /** + * @param aftermath the aftermath to set + */ + public void setAftermath(boolean aftermath) { + this.aftermath = aftermath; + } + + public boolean isChapter() { + return isTrigger() && getTrigger().isChapter(); + } + + public Integer getChapter() { + if (!isTrigger()) { + return null; } - return null; + return getTrigger().getChapter(); + } + + public boolean isLastChapter() { + return isTrigger() && getTrigger().isLastChapter(); + } + + public boolean isAdventure() { + return this.getCardStateName() == CardStateName.Adventure; } public final boolean isCurse() { @@ -754,45 +908,6 @@ public void resetPaidHash() { paidLists.clear(); } - public Iterable getOptionalCosts() { - return optionalCosts; - } - public final void addOptionalCost(OptionalCost cost) { - // Optional costs are added to swallow copies of original SAs, - // Thus, to protect the original's set from changes, we make a copy right here. - optionalCosts = EnumSet.copyOf(optionalCosts); - optionalCosts.add(cost); - if (!cost.getPip().isEmpty()) { - pipsToReduce.get().add(cost.getPip()); - } - } - - public boolean isBargained() { - return isOptionalCostPaid(OptionalCost.Bargain); - } - - public boolean isBuyback() { - return isOptionalCostPaid(OptionalCost.Buyback); - } - - public boolean isKicked() { - return isOptionalCostPaid(OptionalCost.Kicker1) || isOptionalCostPaid(OptionalCost.Kicker2) || - getRootAbility().getOptionalKeywordAmount(Keyword.MULTIKICKER) > 0; - } - - public boolean isEntwine() { - return isOptionalCostPaid(OptionalCost.Entwine); - } - - public boolean isJumpstart() { - return isOptionalCostPaid(OptionalCost.Jumpstart); - } - - public boolean isOptionalCostPaid(OptionalCost cost) { - SpellAbility saRoot = getRootAbility(); - return saRoot.optionalCosts.contains(cost); - } - public Map getTriggeringObjects() { return triggeringObjects; } @@ -1068,64 +1183,6 @@ public void setBasicSpell(final boolean basicSpell0) { basicSpell = basicSpell0; } - public boolean isFlashback() { - return this.isAlternativeCost(AlternativeCost.Flashback); - } - - public boolean isForetelling() { - return false; - } - public boolean isForetold() { - return this.isAlternativeCost(AlternativeCost.Foretold); - } - - public boolean isPlotting() { - return false; - } - - /** - * @return the aftermath - */ - public boolean isAftermath() { - return aftermath; - } - - /** - * @param aftermath the aftermath to set - */ - public void setAftermath(boolean aftermath) { - this.aftermath = aftermath; - } - - public boolean isOutlast() { - return isKeyword(Keyword.OUTLAST); - } - - public boolean isCraft() { - return isKeyword(Keyword.CRAFT); - } - public boolean isCrew() { - return isKeyword(Keyword.CREW); - } - public boolean isEquip() { - return isKeyword(Keyword.EQUIP); - } - - public boolean isChapter() { - return isTrigger() && getTrigger().isChapter(); - } - - public Integer getChapter() { - if (!isTrigger()) { - return null; - } - return getTrigger().getChapter(); - } - - public boolean isLastChapter() { - return isTrigger() && getTrigger().isLastChapter(); - } - public CardPlayOption getMayPlayOption() { return mayPlay; } @@ -1136,10 +1193,6 @@ public void setMayPlay(final CardPlayOption sta) { mayPlay = sta; } - public boolean isAdventure() { - return this.getCardStateName() == CardStateName.Adventure; - } - public SpellAbility copy() { return copy(hostCard, false); } @@ -1499,58 +1552,6 @@ public boolean isWrapper() { return false; } - public final boolean isBestow() { - return isAlternativeCost(AlternativeCost.Bestow); - } - - public final boolean isBlitz() { - return isAlternativeCost(AlternativeCost.Blitz); - } - - public final boolean isDash() { - return isAlternativeCost(AlternativeCost.Dash); - } - - public final boolean isDisturb() { - return isAlternativeCost(AlternativeCost.Disturb); - } - - public final boolean isEscape() { - return isAlternativeCost(AlternativeCost.Escape); - } - - public final boolean isEvoke() { - return isAlternativeCost(AlternativeCost.Evoke); - } - - public final boolean isFreerunning() { - return isAlternativeCost(AlternativeCost.Freerunning); - } - - public final boolean isImpending() { - return isAlternativeCost(AlternativeCost.Impending); - } - - public final boolean isMadness() { - return isAlternativeCost(AlternativeCost.Madness); - } - - public final boolean isMutate() { - return isAlternativeCost(AlternativeCost.Mutate); - } - - public final boolean isProwl() { - return isAlternativeCost(AlternativeCost.Prowl); - } - - public final boolean isSurged() { - return isAlternativeCost(AlternativeCost.Surge); - } - - public final boolean isSpectacle() { - return isAlternativeCost(AlternativeCost.Spectacle); - } - public List getPipsToReduce() { return pipsToReduce.get(); } @@ -2495,6 +2496,7 @@ public boolean isSkip() { public void setSkip(boolean val) { skip = val; } + public boolean canCastTiming(Player activator) { return canCastTiming(getHostCard(), activator); } @@ -2539,7 +2541,6 @@ public boolean withFlash(Card host, Player activator) { public boolean checkRestrictions(Player activator) { return checkRestrictions(getHostCard(), activator); } - public boolean checkRestrictions(Card host, Player activator) { return true; } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerLifeChanged.java b/forge-game/src/main/java/forge/game/trigger/TriggerLifeChanged.java index c6fc8b11683..561bd29126d 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerLifeChanged.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerLifeChanged.java @@ -58,12 +58,6 @@ public final boolean performTest(final Map runParams) { return false; } - if (hasParam("FirstTime")) { - if (!(boolean) runParams.get(AbilityKey.FirstTime)) { - return false; - } - } - return true; } 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 25da03a2a3a..f42b080ae88 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -379,7 +379,7 @@ public final void add(SpellAbility sp, SpellAbilityStackInstance si, int id) { } manaPayer.setExpentThisTurn(totalMana); - for(int i = startingMana + 1; i <= totalMana; i++) { + for (int i = startingMana + 1; i <= totalMana; i++) { Map expendParams = AbilityKey.mapFromPlayer(manaPayer); expendParams.put(AbilityKey.SpellAbility, sp); expendParams.put(AbilityKey.Amount, i); diff --git a/forge-gui/res/cardsfolder/f/fear_of_falling.txt b/forge-gui/res/cardsfolder/f/fear_of_falling.txt index 9eaa6c814c8..9ec69536da7 100644 --- a/forge-gui/res/cardsfolder/f/fear_of_falling.txt +++ b/forge-gui/res/cardsfolder/f/fear_of_falling.txt @@ -3,8 +3,8 @@ ManaCost:3 U U Types:Enchantment Creature Nightmare PT:4/4 K:Flying -T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ Whenever CARDNAME attacks, target creature defending player controls gets -2/-0 and loses flying until end of turn. +T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ Whenever CARDNAME attacks, target creature defending player controls gets -2/-0 and loses flying until your next turn. SVar:TrigPump:DB$ Pump | ValidTgts$ Creature.ControlledBy TriggeredDefendingPlayer | TgtPrompt$ Select target creature defending player controls | NumAtt$ -2 | IsCurse$ True | SubAbility$ DBDebuff -SVar:DBDebuff:DB$ Debuff | Defined$ Targeted | Keywords$ Flying +SVar:DBDebuff:DB$ Debuff | Defined$ Targeted | Keywords$ Flying | Duration$ UntilYourNextTurn SVar:HasAttackEffect:TRUE -Oracle:Flying\nWhenever Fear of Falling attacks, target creature defending player controls gets -2/-0 and loses flying until end of turn. +Oracle:Flying\nWhenever Fear of Falling attacks, target creature defending player controls gets -2/-0 and loses flying until your next turn. diff --git a/forge-gui/res/cardsfolder/t/the_aesir_escape_valhalla.txt b/forge-gui/res/cardsfolder/t/the_aesir_escape_valhalla.txt index 14333e71a54..3093debb875 100644 --- a/forge-gui/res/cardsfolder/t/the_aesir_escape_valhalla.txt +++ b/forge-gui/res/cardsfolder/t/the_aesir_escape_valhalla.txt @@ -2,8 +2,9 @@ Name:The Aesir Escape Valhalla ManaCost:2 G Types:Enchantment Saga K:Chapter:3:I,II,III -SVar:I:DB$ ChangeZone | ChangeNum$ 1 | ChangeType$ Permanent.YouOwn | Mandatory$ True | Origin$ Graveyard | Destination$ Exile | SubAbility$ DBGainLife | SpellDescription$ Exile a permanent card from your graveyard. You gain life equal to its mana value. -SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ ExiledWith$CardManaCost +SVar:I:DB$ ChangeZone | ChangeNum$ 1 | ChangeType$ Permanent.YouOwn | Mandatory$ True | Origin$ Graveyard | Destination$ Exile | Hidden$ True | RememberChanged$ True | SubAbility$ DBGainLife | SpellDescription$ Exile a permanent card from your graveyard. You gain life equal to its mana value. +SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ Remembered$CardManaCost | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:II:DB$ PutCounter | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | CounterType$ P1P1 | CounterNum$ ExiledWith$CardManaCost | SpellDescription$ Put a number of +1/+1 counters on target creature you control equal to the mana value of the exiled card. -SVar:III:DB$ ChangeZone | ChangeType$ Card.StrictlySelf,Card.ExiledWithSource | Origin$ Battlefield,Exile | Destination$ Hand | SpellDescription$ Return CARDNAME and the exiled card to their owner's hand. +SVar:III:DB$ ChangeZone | Defined$ Self & ExiledWith | Origin$ Battlefield,Exile | Destination$ Hand | SpellDescription$ Return CARDNAME and the exiled card to their owner's hand. Oracle:(As this Saga enters and after your draw step, add a lore counter.)\nI — Exile a permanent card from your graveyard. You gain life equal to its mana value.\nII — Put a number of +1/+1 counters on target creature you control equal to the mana value of the exiled card.\nIII — Return The Aesir Escape Valhalla and the exiled card to their owner's hand. diff --git a/forge-gui/res/cardsfolder/w/wax_wane_witness.txt b/forge-gui/res/cardsfolder/w/wax_wane_witness.txt index 0e34c00de6b..f098a4792e9 100644 --- a/forge-gui/res/cardsfolder/w/wax_wane_witness.txt +++ b/forge-gui/res/cardsfolder/w/wax_wane_witness.txt @@ -6,5 +6,4 @@ K:Flying K:Vigilance T:Mode$ LifeChanged | ValidPlayer$ You | TriggerZones$ Battlefield | PlayerTurn$ True | Execute$ TrigPump | TriggerDescription$ Whenever you gain or lose life during your turn, CARDNAME gets +1/+0 until end of turn. SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ 1 -SVar:X:TriggerCount$LifeAmount Oracle:Flying, vigilance\nWhenever you gain or lose life during your turn, Wax-Wane Witness gets +1/+0 until end of turn.