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 f697679e0af..9dc02683a7b 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -66,11 +66,7 @@ public class GameCopier { } public Game makeCopy() { - if (origGame.EXPERIMENTAL_RESTORE_SNAPSHOT) { - return snapshot.makeCopy(); - } else { - return makeCopy(null, null); - } + return makeCopy(null, null); } public Game makeCopy(PhaseType advanceToPhase, Player aiPlayer) { if (origGame.EXPERIMENTAL_RESTORE_SNAPSHOT) { diff --git a/forge-core/src/main/java/forge/item/PaperCard.java b/forge-core/src/main/java/forge/item/PaperCard.java index 64107935513..a09e0fd85e9 100644 --- a/forge-core/src/main/java/forge/item/PaperCard.java +++ b/forge-core/src/main/java/forge/item/PaperCard.java @@ -138,11 +138,6 @@ public class PaperCard implements Comparable, InventoryItemFromSet, return unFoiledVersion; } -// @Override -// public String getImageKey() { -// return getImageLocator(getImageName(), getArtIndex(), true, false); -// } - @Override public String getItemType() { final Localizer localizer = Localizer.getInstance(); diff --git a/forge-game/src/main/java/forge/game/CardTraitBase.java b/forge-game/src/main/java/forge/game/CardTraitBase.java index c01f1c7c0d9..9b41fe6eb3c 100644 --- a/forge-game/src/main/java/forge/game/CardTraitBase.java +++ b/forge-game/src/main/java/forge/game/CardTraitBase.java @@ -27,6 +27,7 @@ import forge.game.spellability.SpellAbility; import forge.game.trigger.Trigger; import forge.game.zone.ZoneType; import forge.util.Expressions; +import forge.util.ITranslatable; /** * Base class for Triggers,ReplacementEffects and StaticAbilities. @@ -623,6 +624,14 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView, return getCardState().getView().getState(); } + public ITranslatable getHostName(CardTraitBase node) { + // if alternate state is viewed while card uses original + if (node.isIntrinsic() && node.cardState != null && !node.cardState.getStateName().equals(getHostCard().getCurrentStateName())) { + return node.cardState; + } + return node.getHostCard(); + } + public Card getOriginalHost() { if (getCardState() != null) return getCardState().getCard(); diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 9fa74479bba..f4379d891d4 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -1507,6 +1507,7 @@ public class GameAction { if (!c.isSaga()) { return false; } + // needs to be effect, because otherwise it might be a cost? if (!c.canBeSacrificedBy(null, true)) { return false; } @@ -1514,7 +1515,6 @@ public class GameAction { return false; } if (!game.getStack().hasSourceOnStack(c, SpellAbilityPredicates.isChapter())) { - // needs to be effect, because otherwise it might be a cost? sacrificeList.add(c); checkAgain = true; } @@ -1537,6 +1537,7 @@ public class GameAction { } return checkAgain; } + private boolean stateBasedAction_Role(Card c, CardCollection removeList) { if (!c.hasCardAttachments()) { return false; @@ -1552,7 +1553,6 @@ public class GameAction { if (rolesByPlayer.size() <= 1) { continue; } - // sort by game timestamp rolesByPlayer.sort(CardPredicates.compareByGameTimestamp()); removeList.addAll(rolesByPlayer.subList(0, rolesByPlayer.size() - 1)); checkAgain = true; @@ -1780,7 +1780,6 @@ public class GameAction { } private boolean handlePlaneswalkerRule(Player p, CardCollection noRegCreats) { - // get all Planeswalkers final List list = p.getPlaneswalkersInPlay(); boolean recheck = false; @@ -2584,7 +2583,6 @@ public class GameAction { player.addCompletedDungeon(dungeon); ceaseToExist(dungeon, true); - // Run RoomEntered trigger final Map runParams = AbilityKey.mapFromCard(dungeon); runParams.put(AbilityKey.Player, player); game.getTriggerHandler().runTrigger(TriggerType.DungeonCompleted, runParams, false); diff --git a/forge-game/src/main/java/forge/game/ability/AbilityApiBased.java b/forge-game/src/main/java/forge/game/ability/AbilityApiBased.java index f89593abf9c..e65ef5006f2 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityApiBased.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityApiBased.java @@ -30,16 +30,7 @@ public class AbilityApiBased extends AbilityActivated { @Override public String getStackDescription() { - StringBuilder sb = new StringBuilder(); - if (this.hostCard.hasPromisedGift() && this.isSpell() && !this.hostCard.isPermanent()) { - sb.append("Gift a "). - append(this.getAdditionalAbility("GiftAbility").getParam("GiftDescription")). - append(" to ").append(this.hostCard.getPromisedGift()). - append(". "); - } - - sb.append(effect.getStackDescriptionWithSubs(mapParams, this)); - return sb.toString(); + return effect.getStackDescriptionWithSubs(mapParams, this); } /* (non-Javadoc) diff --git a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java index 16a47466827..5460217844b 100644 --- a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java @@ -64,6 +64,11 @@ public abstract class SpellAbilityEffect { // prelude for when this is root ability if (!(sa instanceof AbilitySub)) { sb.append(sa.getHostCard()).append(" -"); + if (sa.getHostCard().hasPromisedGift()) { + sb.append(" Gift "). + append(sa.getAdditionalAbility("GiftAbility").getParam("GiftDescription")). + append(" to ").append(sa.getHostCard().getPromisedGift()).append(". "); + } } sb.append(" "); } @@ -462,6 +467,7 @@ public abstract class SpellAbilityEffect { public static void addForgetOnMovedTrigger(final Card card, final String zone) { String trig = "Mode$ ChangesZone | ValidCard$ Card.IsRemembered | Origin$ " + zone + " | ExcludedDestinations$ Stack,Exile | Destination$ Any | TriggerZones$ Command | Static$ True"; + // CR 400.8 Exiled card becomes new object when it's exiled String trig2 = "Mode$ Exiled | ValidCard$ Card.IsRemembered | ValidCause$ SpellAbility.!EffectSource | TriggerZones$ Command | Static$ True"; final Trigger parsedTrigger = TriggerHandler.parseTrigger(trig, card, true); diff --git a/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java index 955d78ad30c..2ebd33cbf00 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java @@ -28,7 +28,6 @@ public class AnimateAllEffect extends AnimateEffectBase { public void resolve(final SpellAbility sa) { final Card host = sa.getHostCard(); - // AF specific sa Integer power = null; if (sa.hasParam("Power")) { power = AbilityUtils.calculateAmount(host, sa.getParam("Power"), sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java index 2e3aff67e86..7f3ca431d7d 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java @@ -208,7 +208,7 @@ public class CopyPermanentEffect extends TokenEffectBase { Player chooser = activator; if (sa.hasParam("Chooser")) { final String choose = sa.getParam("Chooser"); - chooser = AbilityUtils.getDefinedPlayers(sa.getHostCard(), choose, sa).get(0); + chooser = AbilityUtils.getDefinedPlayers(host, choose, sa).get(0); } // For Mimic Vat with mutated creature, need to choose one imprinted card @@ -272,7 +272,6 @@ public class CopyPermanentEffect extends TokenEffectBase { if (!useZoneTable) { triggerList.triggerChangesZoneAll(game, sa); - triggerList.clear(); } if (combatChanged.isTrue()) { game.updateCombatForView(); diff --git a/forge-game/src/main/java/forge/game/ability/effects/DamageAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DamageAllEffect.java index c17351cdcb4..78645ddd050 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DamageAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DamageAllEffect.java @@ -56,8 +56,7 @@ public class DamageAllEffect extends DamageBaseEffect { final Card sourceLKI = card.getGame().getChangeZoneLKIInfo(card); final Game game = sa.getActivatingPlayer().getGame(); - final String damage = sa.getParam("NumDmg"); - final int dmg = AbilityUtils.calculateAmount(source, damage, sa); + final int dmg = AbilityUtils.calculateAmount(source, sa.getParam("NumDmg"), sa); //Remember params from this effect have been moved to dealDamage in GameAction Player targetPlayer = sa.getTargets().getFirstTargetedPlayer(); diff --git a/forge-game/src/main/java/forge/game/ability/effects/MakeCardEffect.java b/forge-game/src/main/java/forge/game/ability/effects/MakeCardEffect.java index 470d4688502..fa39065f704 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/MakeCardEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/MakeCardEffect.java @@ -43,7 +43,7 @@ public class MakeCardEffect extends SpellAbilityEffect { List faces = new ArrayList<>(); List pack = null; List names = Lists.newArrayList(); - + final String desc = sa.getParamOrDefault("OptionPrompt", ""); if (sa.hasParam("Optional") && sa.hasParam("OptionPrompt") && //for now, OptionPrompt is needed !player.getController().confirmAction(sa, null, Localizer.getInstance().getMessage(desc), null)) { @@ -175,7 +175,7 @@ public class MakeCardEffect extends SpellAbilityEffect { CardCollection madeCards = new CardCollection(); final boolean wCounter = sa.hasParam("WithCounter"); final boolean battlefield = zone.equals(ZoneType.Battlefield); - + for (final Card c : cards) { if (wCounter && battlefield) { int numCtr = AbilityUtils.calculateAmount(source, sa.getParamOrDefault("WithCounterNum", "1"), sa); @@ -230,7 +230,7 @@ public class MakeCardEffect extends SpellAbilityEffect { } } - private List parseFaces (final SpellAbility sa, final String param) { + private List parseFaces(final SpellAbility sa, final String param) { List parsedFaces = new ArrayList<>(); for (String s : sa.getParam(param).split(",")) { // Cardnames that include "," must use ";" instead (i.e. Tovolar; Dire Overlord) @@ -244,7 +244,7 @@ public class MakeCardEffect extends SpellAbilityEffect { return parsedFaces; } - private Card finishMaking (final SpellAbility sa, final Card made, final Card source) { + private Card finishMaking(final SpellAbility sa, final Card made, final Card source) { if (sa.hasParam("FaceDown")) made.turnFaceDown(true); if (sa.hasParam("RememberMade")) source.addRemembered(made); if (sa.hasParam("ImprintMade")) source.addImprintedCard(made); diff --git a/forge-game/src/main/java/forge/game/event/GameEventSpellAbilityCast.java b/forge-game/src/main/java/forge/game/event/GameEventSpellAbilityCast.java index 54e075c63c7..a64240e989d 100644 --- a/forge-game/src/main/java/forge/game/event/GameEventSpellAbilityCast.java +++ b/forge-game/src/main/java/forge/game/event/GameEventSpellAbilityCast.java @@ -11,14 +11,12 @@ public class GameEventSpellAbilityCast extends GameEvent { public final SpellAbility sa; public final SpellAbilityStackInstance si; - public final boolean replicate; public final int stackIndex; - public GameEventSpellAbilityCast(SpellAbility sp, SpellAbilityStackInstance si, int stackIndex, boolean replicate) { + public GameEventSpellAbilityCast(SpellAbility sp, SpellAbilityStackInstance si, int stackIndex) { sa = sp; this.si = si; this.stackIndex = stackIndex; - this.replicate = replicate; } /* (non-Javadoc) 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 f51e1eab79c..f1acd94dd17 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -2017,14 +2017,7 @@ public class Player extends GameEntity implements Comparable { } public final boolean cantWin() { - boolean isAnyOppLoseProof = false; - for (Player p : game.getPlayers()) { - if (p == this || p.getOutcome() != null) { - continue; // except self and already dead - } - isAnyOppLoseProof |= p.hasKeyword("You can't lose the game."); - } - return hasKeyword("You can't win the game.") || isAnyOppLoseProof; + return hasKeyword("You can't win the game."); } public final boolean checkLoseCondition() { diff --git a/forge-game/src/main/java/forge/game/player/RegisteredPlayer.java b/forge-game/src/main/java/forge/game/player/RegisteredPlayer.java index 226be9ce173..8967d91df3c 100644 --- a/forge-game/src/main/java/forge/game/player/RegisteredPlayer.java +++ b/forge-game/src/main/java/forge/game/player/RegisteredPlayer.java @@ -10,7 +10,6 @@ import forge.game.GameType; import forge.item.IPaperCard; import forge.item.PaperCard; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; @@ -19,10 +18,10 @@ public class RegisteredPlayer { private final Deck originalDeck; // never return or modify this instance (it's a reference to game resources) private Deck currentDeck; - private static final Iterable EmptyList = Collections.unmodifiableList(new ArrayList<>()); - + private static final Iterable EmptyList = Collections.emptyList(); + private LobbyPlayer player = null; - + private int startingLife = 20; private int startingHand = 7; private int manaShards = 0; @@ -40,7 +39,7 @@ public class RegisteredPlayer { private Integer id = null; private boolean randomFoil = false; private boolean enableETBCountersEffect = false; - + public RegisteredPlayer(Deck deck0) { originalDeck = deck0; restoreDeck(); @@ -49,7 +48,6 @@ public class RegisteredPlayer { public final Integer getId() { return id; } - public final void setId(Integer id0) { id = id0; } @@ -57,19 +55,10 @@ public class RegisteredPlayer { public final Deck getDeck() { return currentDeck; } - + public final int getStartingLife() { return startingLife; } - public final Iterable getCardsOnBattlefield() { - return Iterables.concat(cardsOnBattlefield == null ? EmptyList : cardsOnBattlefield, - extraCardsOnBattlefield == null ? EmptyList : extraCardsOnBattlefield); - } - - public final Iterable getExtraCardsInCommandZone() { - return extraCardsInCommandZone == null ? EmptyList : extraCardsInCommandZone; - } - public final void setStartingLife(int startingLife) { this.startingLife = startingLife; } @@ -77,7 +66,6 @@ public class RegisteredPlayer { public final int getManaShards() { return manaShards; } - public final void setManaShards(int manaShards) { this.manaShards = manaShards; } @@ -89,6 +77,15 @@ public class RegisteredPlayer { enableETBCountersEffect = value; } + public final Iterable getCardsOnBattlefield() { + return Iterables.concat(cardsOnBattlefield == null ? EmptyList : cardsOnBattlefield, + extraCardsOnBattlefield == null ? EmptyList : extraCardsOnBattlefield); + } + + public final Iterable getExtraCardsInCommandZone() { + return extraCardsInCommandZone == null ? EmptyList : extraCardsInCommandZone; + } + public final void setCardsOnBattlefield(Iterable cardsOnTable) { this.cardsOnBattlefield = cardsOnTable; } @@ -137,7 +134,6 @@ public class RegisteredPlayer { public int getTeamNumber() { return teamNumber; } - public void setTeamNumber(int teamNumber0) { this.teamNumber = teamNumber0; } @@ -153,7 +149,7 @@ public class RegisteredPlayer { final Set appliedVariants, final Deck deck, //General vars final Iterable schemes, final boolean playerIsArchenemy, //Archenemy specific vars final Iterable planes, final CardPool vanguardAvatar) { //Planechase and Vanguard - + RegisteredPlayer start = new RegisteredPlayer(deck); if (appliedVariants.contains(GameType.Archenemy) && playerIsArchenemy) { start.setStartingLife(40); // 904.5: The Archenemy has 40 life. @@ -192,7 +188,6 @@ public class RegisteredPlayer { public LobbyPlayer getPlayer() { return player; } - public RegisteredPlayer setPlayer(LobbyPlayer player0) { this.player = player0; return this; @@ -219,7 +214,6 @@ public class RegisteredPlayer { setStartingLife(getStartingLife() + avatar.getRules().getLife()); setStartingHand(getStartingHand() + avatar.getRules().getHand()); } - } public PaperCard getPlaneswalker() { diff --git a/forge-game/src/main/java/forge/game/replacement/ReplaceAddCounter.java b/forge-game/src/main/java/forge/game/replacement/ReplaceAddCounter.java index 875db95b822..097317039eb 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplaceAddCounter.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplaceAddCounter.java @@ -110,7 +110,6 @@ public class ReplaceAddCounter extends ReplacementEffect { @Override public boolean modeCheck(ReplacementType event, Map runParams) { - // TODO Auto-generated method stub if (super.modeCheck(event, runParams)) { return true; } diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java b/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java index 70b1284bd4c..1836337d45a 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java @@ -222,12 +222,7 @@ public abstract class ReplacementEffect extends TriggerReplacementBase { public String getDescription() { if (hasParam("Description") && !this.isSuppressed()) { String desc = AbilityUtils.applyDescriptionTextChangeEffects(getParam("Description"), this); - ITranslatable nameSource; - if (this.isIntrinsic() && cardState != null && cardState.getCard() == getHostCard()) { - nameSource = cardState; - } else { - nameSource = getHostCard(); - } + ITranslatable nameSource = getHostName(this); desc = CardTranslation.translateMultipleDescriptionText(desc, nameSource); String translatedName = CardTranslation.getTranslatedName(nameSource); desc = TextUtil.fastReplace(desc, "CARDNAME", translatedName); 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 6e43c207946..570ec061b59 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -984,13 +984,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit } String desc = node.getDescription(); if (node.getHostCard() != null) { - ITranslatable nameSource; - // if alternate state is viewed while card uses original - if (node.isIntrinsic() && node.cardState != null && node.cardState.getCard() == node.getHostCard()) { - nameSource = node.cardState; - } else { - nameSource = node.getHostCard(); - } + ITranslatable nameSource = getHostName(node); desc = CardTranslation.translateMultipleDescriptionText(desc, nameSource); String translatedName = CardTranslation.getTranslatedName(nameSource); desc = TextUtil.fastReplace(desc, "CARDNAME", translatedName); diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java index 7a4952bf594..327296f0d9c 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java @@ -183,12 +183,7 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone @Override public final String toString() { if (hasParam("Description") && !this.isSuppressed()) { - ITranslatable nameSource; - if (this.isIntrinsic() && cardState != null && cardState.getCard() == getHostCard()) { - nameSource = cardState; - } else { - nameSource = getHostCard(); - } + ITranslatable nameSource = getHostName(this); String desc = CardTranslation.translateSingleDescriptionText(getParam("Description"), nameSource); String translatedName = CardTranslation.getTranslatedName(nameSource); desc = TextUtil.fastReplace(desc, "CARDNAME", translatedName); diff --git a/forge-game/src/main/java/forge/game/trigger/Trigger.java b/forge-game/src/main/java/forge/game/trigger/Trigger.java index 99152cfbd57..9ab6ac9d7f1 100644 --- a/forge-game/src/main/java/forge/game/trigger/Trigger.java +++ b/forge-game/src/main/java/forge/game/trigger/Trigger.java @@ -120,12 +120,7 @@ public abstract class Trigger extends TriggerReplacementBase { public String toString(boolean active) { if (hasParam("TriggerDescription") && !this.isSuppressed()) { StringBuilder sb = new StringBuilder(); - ITranslatable nameSource; - if (this.isIntrinsic() && cardState != null && cardState.getCard() == getHostCard()) { - nameSource = cardState; - } else { - nameSource = getHostCard(); - } + ITranslatable nameSource = getHostName(this); String desc = getParam("TriggerDescription"); if (!desc.contains("ABILITY")) { desc = CardTranslation.translateSingleDescriptionText(getParam("TriggerDescription"), nameSource); 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 7f91e4f21a3..99fb6e0e15d 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -544,7 +544,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable itemManager0, Collection sets0, Collection limitedSets0, boolean allowReprints0) { this(itemManager0, sets0, allowReprints0); - this.limitedSets.addAll(limitedSets0); + if (limitedSets0 != null) { + this.limitedSets.addAll(limitedSets0); + } } @Override diff --git a/forge-gui/res/cardsfolder/g/golgari_brownscale.txt b/forge-gui/res/cardsfolder/g/golgari_brownscale.txt index b0810d7787f..fdadceb6ca2 100644 --- a/forge-gui/res/cardsfolder/g/golgari_brownscale.txt +++ b/forge-gui/res/cardsfolder/g/golgari_brownscale.txt @@ -3,6 +3,6 @@ ManaCost:1 G G Types:Creature Lizard PT:2/3 T:Mode$ ChangesZone | Origin$ Graveyard | Destination$ Hand | ValidCard$ Card.Self | Execute$ TrigGainLife | TriggerDescription$ When CARDNAME is put into your hand from your graveyard, you gain 2 life. -K:Dredge:2 SVar:TrigGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 2 +K:Dredge:2 Oracle:When Golgari Brownscale is put into your hand from your graveyard, you gain 2 life.\nDredge 2 (If you would draw a card, you may mill two cards instead. If you do, return this card from your graveyard to your hand.)