diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set01/set1-wraith.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set01/set1-wraith.hjson index 744747fd2..53513a22d 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set01/set1-wraith.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set01/set1-wraith.hjson @@ -978,10 +978,22 @@ site: 3 effects: { type: trigger + optional: true trigger: { type: played filter: self } + requires: [ + { + type: CanSpot + filter: companion + count: 5 + } + { + type: PlayableFromDiscard + filter: minion + } + ] effect: [ { type: MemorizeValue @@ -989,61 +1001,47 @@ value: yes } { - type: conditional - requires: [ - { - type: CanSpot - filter: companion - count: 5 - } - { - type: PlayableFromDiscard - filter: minion - } - ] + type: Repeat + amount: { + type: forEachYouCanSpot + filter: companion + over: 4 + } effect: { - type: Repeat - amount: { - type: forEachYouCanSpot - filter: companion - over: 4 - } - effect: { - type: conditional - requires: [ - { - type: MemoryIs - memory: choice - value: yes - } - { - type: HasCardInDiscard - filter: playable,minion - } - ] - effect: [ - { - type: chooseYesOrNo - player: you - text: Would you like to play a minion from your discard? - memorize: choice - } - { - type: conditional - requires: [ - { - type: MemoryIs - memory: choice - value: yes - } - ] - effect: { - type: playCardFromDiscard - filter: choose(minion) + type: conditional + requires: [ + { + type: MemoryIs + memory: choice + value: yes + } + { + type: HasCardInDiscard + filter: playable,minion + } + ] + effect: [ + { + type: chooseYesOrNo + player: you + text: Would you like to play a minion from your discard? + memorize: choice + } + { + type: conditional + requires: [ + { + type: MemoryIs + memory: choice + value: yes } + ] + effect: { + type: playCardFromDiscard + filter: choose(minion) } - ] - } + } + ] } } ] diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set01/set1.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set01/set1.hjson index 9437e663f..ad963c84e 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set01/set1.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set01/set1.hjson @@ -526,7 +526,10 @@ type: site site: 3 block: fellowship - keyword: river + keywords: [ + river + Sanctuary + ] direction: right effects: [ { @@ -534,11 +537,8 @@ modifier: { type: modifyCost requires: { - type: not - requires: { - type: hasInZoneData - filter: self - } + type: perTurnLimit + limit: 1 } filter: nazgul amount: -5 @@ -549,41 +549,10 @@ trigger: { type: played filter: nazgul - memorize: playedNazgul - } - requires: { - type: not - requires: { - type: hasInZoneData - filter: self - } } effect: { - type: appendCardIdsToWhileInZone - memory: playedNazgul - } - } - { - type: trigger - trigger: { - type: endOfTurn - } - effect: { - type: resetWhileInZoneData - } - } - { - type: trigger - trigger: { - type: movesFrom - filter: self - } - requires: { - type: phase - phase: regroup - } - effect: { - type: resetWhileInZoneData + type: incrementPerTurnLimit + limit: 1 } } ] @@ -900,17 +869,15 @@ site: 6 block: fellowship direction: left + keywords: Sanctuary effects: [ { type: modifier modifier: { type: modifyCost requires: { - type: not - requires: { - type: hasInZoneData - filter: self - } + type: perPhaseLimit + limit: 1 } filter: culture(moria),orc amount: -2 @@ -923,26 +890,9 @@ filter: culture(moria),orc memorize: playedOrc } - requires: { - type: not - requires: { - type: hasInZoneData - filter: self - } - } effect: { - type: appendCardIdsToWhileInZone - memory: playedOrc - } - } - { - type: trigger - trigger: { - type: endOfPhase - phase: shadow - } - effect: { - type: resetWhileInZoneData + type: incrementPerPhaseLimit + limit: 1 } } ] diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Ringwraith-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Ringwraith-errata.hjson index 90f35f81d..b6214aa1a 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Ringwraith-errata.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Ringwraith-errata.hjson @@ -26,10 +26,22 @@ site: 3 effects: { type: trigger + optional: true trigger: { type: played filter: self } + requires: [ + { + type: CanSpot + filter: companion + count: 5 + } + { + type: PlayableFromDiscard + filter: minion + } + ] effect: [ { type: MemorizeValue @@ -37,61 +49,47 @@ value: yes } { - type: conditional - requires: [ - { - type: CanSpot - filter: companion - count: 5 - } - { - type: PlayableFromDiscard - filter: unique,culture(wraith),minion - } - ] + type: Repeat + amount: { + type: forEachYouCanSpot + filter: companion + over: 4 + } effect: { - type: Repeat - amount: { - type: forEachYouCanSpot - filter: companion - over: 4 - } - effect: { - type: conditional - requires: [ - { - type: MemoryIs - memory: choice - value: yes - } - { - type: HasCardInDiscard - filter: playable,unique,culture(wraith),minion - } - ] - effect: [ - { - type: chooseYesOrNo - player: you - text: Would you like to play a unique WRAITH minion from your discard? - memorize: choice - } - { - type: conditional - requires: [ - { - type: MemoryIs - memory: choice - value: yes - } - ] - effect: { - type: playCardFromDiscard - filter: choose(unique,culture(wraith),minion) + type: conditional + requires: [ + { + type: MemoryIs + memory: choice + value: yes + } + { + type: HasCardInDiscard + filter: playable,unique,culture(wraith),minion + } + ] + effect: [ + { + type: chooseYesOrNo + player: you + text: Would you like to play a unique WRAITH minion from your discard? + memorize: choice + } + { + type: conditional + requires: [ + { + type: MemoryIs + memory: choice + value: yes } + ] + effect: { + type: playCardFromDiscard + filter: choose(unique,culture(wraith),minion) } - ] - } + } + ] } } ] diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_234_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_234_Tests.java index b22006981..4f0f57c32 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_234_Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_234_Tests.java @@ -108,6 +108,8 @@ public class Card_01_234_Tests scn.FreepsPassCurrentPhaseAction(); scn.ShadowPlayCard(nertea); + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); assertTrue(scn.ShadowDecisionAvailable("play a minion")); scn.ShadowChooseYes(); //twk, attea, rit, and runner @@ -139,6 +141,8 @@ public class Card_01_234_Tests scn.FreepsPassCurrentPhaseAction(); scn.ShadowPlayCard(nertea); + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); assertTrue(scn.ShadowDecisionAvailable("play a minion")); scn.ShadowChooseYes(); //twk, attea, rit, and runner @@ -176,6 +180,8 @@ public class Card_01_234_Tests scn.FreepsPassCurrentPhaseAction(); scn.ShadowPlayCard(nertea); + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); assertTrue(scn.ShadowDecisionAvailable("play a minion")); scn.ShadowChooseNo(); @@ -201,6 +207,8 @@ public class Card_01_234_Tests scn.FreepsPassCurrentPhaseAction(); scn.ShadowPlayCard(nertea); + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); assertTrue(scn.ShadowDecisionAvailable("play a minion")); scn.ShadowChooseYes(); assertEquals(4, scn.GetShadowCardChoiceCount()); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_338_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_338_Tests.java new file mode 100644 index 000000000..4a7530d8a --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_338_Tests.java @@ -0,0 +1,152 @@ +package com.gempukku.lotro.cards.official.set01; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.*; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static org.junit.Assert.*; + +public class Card_01_338_Tests +{ + + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap<>() + {{ + put("twk", "1_237"); + put("lemenya", "1_232"); + put("nertea", "1_234"); + + put("guard1", "1_7"); + put("guard2", "1_7"); + put("guard3", "1_7"); + put("guard4", "1_7"); + }}, + new HashMap<>() {{ + put("site1", "1_319"); + put("site2", "1_327"); + put("site3", "1_338"); + put("site4", "1_343"); + put("site5", "1_349"); + put("site6", "1_351"); + put("site7", "1_353"); + put("site8", "1_356"); + put("site9", "1_360"); + }}, + GenericCardTestHelper.FOTRFrodo, + GenericCardTestHelper.RulingRing + ); + } + + @Test + public void FordofBruinenStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1 + * Name: Ford of Bruinen + * Unique: False + * Side: + * Culture: + * Shadow Number: 0 + * Type: Sanctuary + * Subtype: + * Site Number: 3 + * Game Text: River. Sanctuary. The twilight cost of the first Nazgûl played to Ford of Bruinen each turn is -5. + */ + + var scn = GetScenario(); + + var card = scn.GetFreepsSite(3); + + assertEquals("Ford of Bruinen", card.getBlueprint().getTitle()); + assertNull(card.getBlueprint().getSubtitle()); + assertFalse(card.getBlueprint().isUnique()); + assertEquals(CardType.SITE, card.getBlueprint().getCardType()); + assertTrue(scn.HasKeyword(card, Keyword.RIVER)); + assertTrue(scn.HasKeyword(card, Keyword.SANCTUARY)); + assertEquals(0, card.getBlueprint().getTwilightCost()); + assertEquals(3, card.getBlueprint().getSiteNumber()); + } + + @Test + public void FordofBruinenOnlyDiscountsTheFirstNazgul() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var ford = scn.GetShadowSite(3); + + var twk = scn.GetShadowCard("twk"); + var lemenya = scn.GetShadowCard("lemenya"); + scn.ShadowMoveCardToHand(twk, lemenya); + + scn.StartGame(); + //Start our test on 2 so that moving to 3 is the first thing we do + scn.SkipToSite(2); + + scn.SetTwilight(9); + scn.FreepsPassCurrentPhaseAction(); + + assertEquals(ford, scn.GetCurrentSite()); + + //9 manual + 1 from the fellowship moving + assertEquals(10, scn.GetTwilight()); + + scn.ShadowPlayCard(twk); + //TWK costs 8 (no roaming), discounted by 5 to 3 total + //10 - 3 + assertEquals(7, scn.GetTwilight()); + + scn.ShadowPlayCard(lemenya); + //Lemenya costs 4, should have no discount + //7 - 4 + assertEquals(3, scn.GetTwilight()); + } + + @Test + public void FordDiscountsNerteaButNotNerteasTrigger() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var ford = scn.GetShadowSite(3); + + var twk = scn.GetShadowCard("twk"); + var nertea = scn.GetShadowCard("nertea"); + scn.ShadowMoveCardToHand(nertea); + scn.ShadowMoveCardToDiscard(twk); + + scn.FreepsMoveCharToTable("guard1", "guard2", "guard3", "guard4"); + + scn.StartGame(); + //Start our test on 2 so that moving to 3 is the first thing we do + scn.SkipToSite(2); + + scn.SetTwilight(5); + scn.FreepsPassCurrentPhaseAction(); + + assertEquals(ford, scn.GetCurrentSite()); + + //5 manual + 5 from the fellowship moving + assertEquals(10, scn.GetTwilight()); + + scn.ShadowPlayCard(nertea); + //Nertea costs 4 (no roaming), discounted by 5 to 0 total + //10 - 0 + assertEquals(10, scn.GetTwilight()); + + //Nertea pulls a minion from discard, which should not get discounted + // as Nertea should have consumed the only discount + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); + assertTrue(scn.ShadowDecisionAvailable("play a minion")); + scn.ShadowChooseYes(); + + scn.ShadowChooseCardBPFromSelection(twk); + //TWK costs 8, should not be discounted + //10 - 8 + assertEquals(2, scn.GetTwilight()); + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set01/Card_01_234_ErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set01/Card_01_234_ErrataTests.java index 128efe00c..501d2d6ce 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set01/Card_01_234_ErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set01/Card_01_234_ErrataTests.java @@ -108,6 +108,8 @@ public class Card_01_234_ErrataTests scn.FreepsPassCurrentPhaseAction(); scn.ShadowPlayCard(nertea); + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion")); scn.ShadowChooseYes(); //twk and attea, but not rit or runner @@ -138,6 +140,8 @@ public class Card_01_234_ErrataTests scn.FreepsPassCurrentPhaseAction(); scn.ShadowPlayCard(nertea); + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion")); scn.ShadowChooseYes(); //twk and attea, but not rit or runner @@ -174,6 +178,8 @@ public class Card_01_234_ErrataTests scn.FreepsPassCurrentPhaseAction(); scn.ShadowPlayCard(nertea); + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion")); scn.ShadowChooseNo(); @@ -199,6 +205,8 @@ public class Card_01_234_ErrataTests scn.FreepsPassCurrentPhaseAction(); scn.ShadowPlayCard(nertea); + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion")); scn.ShadowChooseYes(); //twk and attea, but not rit or runner