diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set07/set07-Gollum.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set07/set07-Gollum.hjson index a8fbef4f5..0c665bf79 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set07/set07-Gollum.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set07/set07-Gollum.hjson @@ -1436,7 +1436,7 @@ trigger: { type: FPDecidedToStay } - until: endOfTurn + until: end(regroup) effect: { type: discardFromHand count: 100 diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set09/set09-Gandalf-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set09/set09-Gandalf-errata.hjson index 51d506a13..3b802c6bc 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set09/set09-Gandalf-errata.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set09/set09-Gandalf-errata.hjson @@ -29,80 +29,10 @@ resistance: 6, effects: [ { - type: trigger - trigger: [ - { - type: played - filter: self - } - { - type: startOfTurn - } - ] - requires: { - type: perTurnLimit - limit: 1 - } - effect: [ - { - type: incrementPerTurnLimit - limit: 1 - } - { - type: addModifier - until: endOfTurn - modifier: { - type: modifyMoveLimit - amount: 1 - } - } - { - type: AddTrigger - until: endOfTurn - optional: false - trigger: { - type: RemovedFromPlay - filter: title(Radagast) - } - effect: { - type: addModifier - until: endOfTurn - modifier: { - type: modifyMoveLimit - amount: -1 - } - } - } - ] + type: modifier + modifier: modifyMoveLimit + amount: 1 } - # { - # type: DiscardedFromPlayTrigger - # optional: false - # effect: [ - # { - # type: addModifier - # until: endOfTurn - # modifier: { - # type: modifyMoveLimit - # amount: -1 - # } - # } - # ] - # } - # { - # type: KilledTrigger - # optional: false - # effect: [ - # { - # type: addModifier - # until: endOfTurn - # modifier: { - # type: modifyMoveLimit - # amount: -1 - # } - # } - # ] - # } { type: trigger trigger: { diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/Heals.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/Heals.java index eab141016..c390098a1 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/Heals.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/Heals.java @@ -16,8 +16,8 @@ public class Heals implements TriggerCheckerProducer { final String filter = FieldUtils.getString(value.get("filter"), "filter", "any"); final String memorize = FieldUtils.getString(value.get("memorize"), "memorize"); - final String player = FieldUtils.getString(value.get("player"), "player", "you"); - final PlayerSource playerSource = PlayerResolver.resolvePlayer(player); + final String player = FieldUtils.getString(value.get("player"), "player"); + final PlayerSource playerSource = player != null ? PlayerResolver.resolvePlayer(player) : null; final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment); @@ -30,7 +30,7 @@ public class Heals implements TriggerCheckerProducer { @Override public boolean accepts(ActionContext actionContext) { final Filterable filterable = filterableSource.getFilterable(actionContext); - final boolean result = TriggerConditions.forEachHealed(actionContext.getGame(), actionContext.getEffectResult(), playerSource.getPlayer(actionContext), filterable); + final boolean result = TriggerConditions.forEachHealed(actionContext.getGame(), actionContext.getEffectResult(), playerSource != null ? playerSource.getPlayer(actionContext) : null, filterable); if (result && memorize != null) { final PhysicalCard healedCard = ((HealResult) actionContext.getEffectResult()).getHealedCard(); actionContext.setCardMemory(memorize, healedCard); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RemovedFromPlay.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RemovedFromPlay.java deleted file mode 100644 index 556db96de..000000000 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RemovedFromPlay.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.gempukku.lotro.cards.build.field.effect.trigger; - -import com.gempukku.lotro.cards.build.ActionContext; -import com.gempukku.lotro.cards.build.CardGenerationEnvironment; -import com.gempukku.lotro.cards.build.FilterableSource; -import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; -import com.gempukku.lotro.cards.build.field.FieldUtils; -import com.gempukku.lotro.common.Filterable; -import com.gempukku.lotro.game.PhysicalCard; -import com.gempukku.lotro.logic.timing.TriggerConditions; -import com.gempukku.lotro.logic.timing.results.DiscardCardsFromPlayResult; -import com.gempukku.lotro.logic.timing.results.ForEachKilledResult; -import com.gempukku.lotro.logic.timing.results.ReturnCardsToHandResult; -import org.json.simple.JSONObject; - -public class RemovedFromPlay implements TriggerCheckerProducer { - @Override - public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(value, "filter", "memorize"); - - final String filter = FieldUtils.getString(value.get("filter"), "filter", "any"); - final String memorize = FieldUtils.getString(value.get("memorize"), "memorize"); - - final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment); - - return new TriggerChecker() { - @Override - public boolean isBefore() { - return false; - } - - @Override - public boolean accepts(ActionContext actionContext) { - final Filterable filterable = filterableSource.getFilterable(actionContext); - final boolean killResult = TriggerConditions.forEachKilled(actionContext.getGame(), actionContext.getEffectResult(), filterable); - if (killResult && memorize != null) { - final PhysicalCard killedCard = ((ForEachKilledResult) actionContext.getEffectResult()).getKilledCard(); - actionContext.setCardMemory(memorize, killedCard); - } - - final boolean discardResult = TriggerConditions.forEachDiscardedFromPlay(actionContext.getGame(), actionContext.getEffectResult(), filterable); - if (discardResult && memorize != null) { - final PhysicalCard discardedCard = ((DiscardCardsFromPlayResult) actionContext.getEffectResult()).getDiscardedCard(); - actionContext.setCardMemory(memorize, discardedCard); - } - - final boolean returnedResult = TriggerConditions.forEachReturnedToHand(actionContext.getGame(), actionContext.getEffectResult(), filterable); - if (returnedResult && memorize != null) { - final PhysicalCard returnedCard = ((ReturnCardsToHandResult) actionContext.getEffectResult()).getReturnedCard(); - actionContext.setCardMemory(memorize, returnedCard); - } - return killResult || discardResult || returnedResult; - } - }; - } -} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java index ebbf70815..497aafc20 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java @@ -58,7 +58,6 @@ public class TriggerCheckerFactory { triggerCheckers.put("playerdrawscard", new PlayerDrawsCard()); triggerCheckers.put("putsonring", new PutsOnRing()); triggerCheckers.put("reconciles", new Reconciles()); - triggerCheckers.put("removedfromplay", new RemovedFromPlay()); triggerCheckers.put("removesburden", new RemovesBurden()); triggerCheckers.put("replacessite", new ReplacesSite()); triggerCheckers.put("revealscardfromtopofdrawdeck", new RevealsCardFromTopOfDrawDeck()); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java index 5944b03dc..cbdfc43ab 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java @@ -14,13 +14,19 @@ import java.util.Objects; public class TriggerConditions { public static boolean startOfPhase(LotroGame game, EffectResult effectResult, Phase phase) { - return (effectResult.getType() == EffectResult.Type.START_OF_PHASE - && ((StartOfPhaseResult) effectResult).getPhase() == phase || phase == null); + if (effectResult.getType() == EffectResult.Type.START_OF_PHASE) { + StartOfPhaseResult startOfPhaseResult = (StartOfPhaseResult) effectResult; + return (startOfPhaseResult.getPhase() == phase || phase == null); + } + return false; } public static boolean endOfPhase(LotroGame game, EffectResult effectResult, Phase phase) { - return (effectResult.getType() == EffectResult.Type.END_OF_PHASE - && ((EndOfPhaseResult) effectResult).getPhase() == phase || phase == null); + if (effectResult.getType() == EffectResult.Type.END_OF_PHASE) { + EndOfPhaseResult endOfPhaseResult = (EndOfPhaseResult) effectResult; + return (endOfPhaseResult.getPhase() == phase || phase == null); + } + return false; } public static boolean startOfTurn(LotroGame game, EffectResult effectResult) { diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/AbstractAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/AbstractAtTest.java index e32a4b024..8e581cc4a 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/AbstractAtTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/AbstractAtTest.java @@ -140,6 +140,10 @@ public abstract class AbstractAtTest { return _game.getGameState().getBurdens(); } + public void removeBurdens(int count) { + _game.getGameState().removeBurdens(count); + } + public Phase getPhase() { return _game.getGameState().getCurrentPhase(); } @@ -192,6 +196,10 @@ public abstract class AbstractAtTest { playerDecided(P2, "0"); } + public void playerAnswersNo(String player) throws DecisionResultInvalidException { + playerDecided(player, "1"); + } + public void passUntil(Phase phase) throws DecisionResultInvalidException { while (true) { Phase currentPhase = _game.getGameState().getCurrentPhase(); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/TriggersAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/TriggersAtTest.java index 48fe05f52..0bf8a3add 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/TriggersAtTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/TriggersAtTest.java @@ -10,6 +10,7 @@ import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.decisions.AwaitingDecisionType; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; import com.gempukku.lotro.logic.modifiers.AddKeywordModifier; +import com.gempukku.lotro.logic.vo.LotroDeck; import org.junit.Test; import java.util.Collection; @@ -17,8 +18,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; public class TriggersAtTest extends AbstractAtTest { @Test @@ -535,4 +535,179 @@ public class TriggersAtTest extends AbstractAtTest { selectCardAction(P1, elfSong); hasCardAction(P1, theShireCountryside); } + + @Test + public void reconciles() throws Exception { + initializeSimplestGame(); + + PhysicalCard isildur = addToZone(createCard(P1, "13_71"), Zone.FREE_CHARACTERS); + + for (int i = 0; i < 5; i++) { + addToZone(createCard(P1, "13_71"), Zone.HAND); + } + + passUntil(Phase.REGROUP); + pass(P1); + pass(P2); + assertEquals(Zone.FREE_CHARACTERS, isildur.getZone()); + playerAnswersNo(P1); + pass(P1); + hasCardAction(P1, isildur); + } + + @Test + public void putsOnRing() throws Exception { + initializeSimplestGame(); + + PhysicalCard theTwilightWorld = addToZone(createCard(P2, "1_228"), Zone.HAND); + PhysicalCard nelya = addToZone(createCard(P2, "11_222"), Zone.SHADOW_CHARACTERS); + PhysicalCard goblinRunner = addToZone(createCard(P2, "1_178"), Zone.SHADOW_CHARACTERS); + + PhysicalCard ringBearer = getRingBearer(P1); + PhysicalCard ring = getRing(P1); + + passUntil(Phase.ASSIGNMENT); + pass(P1); + pass(P2); + playerDecided(P1, ringBearer.getCardId() + " " + goblinRunner.getCardId()); + pass(P2); + selectCard(P1, ringBearer); + pass(P1); + pass(P2); + selectCardAction(P1, ring); + assertEquals(1, getBurdens()); + selectCardAction(P2, theTwilightWorld); + assertEquals(4, getBurdens()); + assertEquals(1, getWounds(nelya)); + } + + @Test + public void movesTo() throws Exception { + Map decks = new HashMap<>(); + decks.put(P1, createSpecialMovesToDeck()); + decks.put(P2, createSpecialMovesToDeck()); + initializeGameWithDecks(decks); + + passUntil(Phase.SHADOW); + assertEquals(1, getWounds(getRingBearer(P1))); + } + + public LotroDeck createSpecialMovesToDeck() { + LotroDeck lotroDeck = new LotroDeck("Some deck"); + lotroDeck.setRingBearer("10_121"); + lotroDeck.setRing("1_2"); + lotroDeck.addSite("7_330"); + lotroDeck.addSite("1_332"); + lotroDeck.addSite("8_117"); + lotroDeck.addSite("7_342"); + lotroDeck.addSite("7_345"); + lotroDeck.addSite("7_350"); + lotroDeck.addSite("8_120"); + lotroDeck.addSite("10_120"); + lotroDeck.addSite("7_360"); + return lotroDeck; + } + + @Test + public void movesFrom() throws Exception { + initializeSimplestGame(); + + PhysicalCard councilCourtyard = addToZone(createCard(P1, "1_337"), Zone.ADVENTURE_DECK); + + passUntil(Phase.FELLOWSHIP); + replaceSite(councilCourtyard, 1); + setTwilightPool(2); + + passUntil(Phase.SHADOW); + assertEquals(2, getTwilightPool()); + } + + @Test + public void losesInitiative() throws Exception { + initializeSimplestGame(); + + PhysicalCard glimpseOfFate = addToZone(createCard(P1, "10_12"), Zone.SUPPORT); + PhysicalCard legolas1 = addToZone(createCard(P1, "1_50"), Zone.HAND); + PhysicalCard legolas2 = addToZone(createCard(P1, "1_50"), Zone.HAND); + PhysicalCard legolas3 = addToZone(createCard(P1, "1_50"), Zone.HAND); + PhysicalCard legolas4 = addToZone(createCard(P1, "1_50"), Zone.HAND); + PhysicalCard goblinRunner = addToZone(createCard(P2, "1_178"), Zone.SHADOW_CHARACTERS); + + passUntil(Phase.FELLOWSHIP); + assertEquals(5, getStrength(goblinRunner)); + selectCardAction(P1, legolas1); + assertEquals(1, getStrength(goblinRunner)); + } + + @Test + public void heals() throws Exception { + initializeSimplestGame(); + + PhysicalCard frodo = getRingBearer(P1); + + PhysicalCard lingeringShadow = attachTo(createCard(P2, "12_166"), frodo); + PhysicalCard theGaffer = addToZone(createCard(P1, "1_291"), Zone.SUPPORT); + + addWounds(frodo, 1); + + passUntil(Phase.FELLOWSHIP); + assertEquals(1, getBurdens()); + selectCardAction(P1, theGaffer); + assertEquals(0, getWounds(frodo)); + assertEquals(2, getBurdens()); + } + + @Test + public void fpStartedAssigning() throws Exception { + initializeSimplestGame(); + + PhysicalCard nerteaDarkHorseman = addToZone(createCard(P2, "69_38"), Zone.SHADOW_CHARACTERS); + + passUntil(Phase.ASSIGNMENT); + pass(P1); + pass(P2); + assertNotNull(getMultipleDecisionIndex(getAwaitingDecision(P1), "Yes")); + } + + @Test + public void fpDecidedToStay() throws Exception { + initializeSimplestGame(); + + PhysicalCard veryNiceFriends = addToZone(createCard(P1, "7_76"), Zone.HAND); + PhysicalCard smeagol = addToZone(createCard(P1, "7_71"), Zone.DISCARD); + PhysicalCard legolas1 = addToZone(createCard(P1, "1_50"), Zone.HAND); + + passUntil(Phase.REGROUP); + selectCardAction(P1, veryNiceFriends); + pass(P2); + pass(P1); + selectNo(P1); + assertEquals(Zone.DISCARD, legolas1.getZone()); + } + + @Test + public void exerted() throws Exception { + initializeSimplestGame(); + + PhysicalCard demandsOfSackvilleBagginses = addToZone(createCard(P2, "2_40"), Zone.SUPPORT); + PhysicalCard theGaffer = addToZone(createCard(P1, "1_291"), Zone.SUPPORT); + + passUntil(Phase.FELLOWSHIP); + assertEquals(0, getTwilightPool()); + selectCardAction(P1, theGaffer); + assertEquals(1, getTwilightPool()); + } + + @Test + public void endOfTurn() throws Exception { + initializeSimplestGame(); + + PhysicalCard sarumansChill = addToZone(createCard(P2, "1_134"), Zone.SUPPORT); + + passUntil(Phase.REGROUP); + pass(P1); + pass(P2); + selectNo(P1); + assertEquals(Zone.DISCARD, sarumansChill.getZone()); + } }