From e20bf34fa00be44a82295f760ce64c2ed52bfd07 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 29 Sep 2024 22:17:44 -0500 Subject: [PATCH 1/5] Altered tournament rewards boosters to include far more PC promos more frequently. Added do-nothing promo "card" for the 2024 WC invitation. --- .../src/main/web/js/gemp-022/PC_Cards.js | 5 ++++- .../unofficial/pc/setV00/V0-shadows-sites.hjson | 17 +++++++++++++++++ .../main/resources/product/Event-Rewards.hjson | 9 +++++---- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js index 8ec9d6b98..5af3c0ba6 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js @@ -660,7 +660,10 @@ var PCCards = { '53_80' : 'https://i.lotrtcgpc.net/errata/LOTR-EN03E080.2_card.jpg', '53_85' : 'https://i.lotrtcgpc.net/errata/LOTR-EN03E085.2_card.jpg', '53_103' : 'https://i.lotrtcgpc.net/errata/LOTR-EN03E103.3_card.jpg', - '53_105' : 'https://i.lotrtcgpc.net/errata/LOTR-EN03E105.2_card.jpg' + '53_105' : 'https://i.lotrtcgpc.net/errata/LOTR-EN03E105.2_card.jpg', + + //2024 WC Invitation "Card" + '100_0' : 'https://i.lotrtcgpc.net/other/2024-wc-invite.jpg', } diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV00/V0-shadows-sites.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV00/V0-shadows-sites.hjson index dd6947eeb..c0dd73f4c 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV00/V0-shadows-sites.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV00/V0-shadows-sites.hjson @@ -1,4 +1,21 @@ { + 100_0: { + title: 2024 World Championship Invitation + type: Event + twilight: 5 + culture: Elven + keyword: Regroup + effects: { + type: event + effect: [ + { + type: SendMessage + text: The holder of this card is invited to the 2024 World Championship Group Stage. How the hell did you play this card in a game...? + } + ] + } + } + 100_1: { cardInfo: { imagePath: errata/LOTR-ENV0E001.0.jpg diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/product/Event-Rewards.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/product/Event-Rewards.hjson index 3ffcf92b5..e095d996d 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/product/Event-Rewards.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/product/Event-Rewards.hjson @@ -51,7 +51,7 @@ 30%1xRandom Ultra Rare Foil 10%1xRandom Masterwork 10%1xRandom Alt Image Promo - 10%1xRandom PC Full Art + 30%1xRandom PC Full Art 5%1xRandom Tengwar 1%1x(S)Masterwork Selection 1%1x(S)PC Promo Art Selection @@ -77,13 +77,14 @@ name: Placement Random Chase Card Selector type: random items: [ - 50%1x(S)Alt Image Promo Selection + 40%1x(S)Alt Image Promo Selection + 40%1xRandom PC Full Art 10%1x(S)FotR - Tengwar 10%1x(S)TTT - Tengwar 10%1x(S)RotK - Tengwar 10%1x(S)SH - Tengwar - 30%1x(S)Masterwork Selection - 5%1x(S)PC Promo Art Selection + 40%1x(S)Masterwork Selection + 40%1x(S)PC Promo Art Selection ] } { From e5bc543cceb6e3c721967a349fdaee0d296cb698 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 29 Sep 2024 22:29:44 -0500 Subject: [PATCH 2/5] Converting invitation to a tautological card instead of a card. --- .../gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js | 5 +---- .../gemp-lotr-async/src/main/web/js/gemp-022/jCards.js | 4 +++- .../src/main/resources/product/Misc-Packs.hjson | 9 +++++++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js index 5af3c0ba6..8ec9d6b98 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js @@ -660,10 +660,7 @@ var PCCards = { '53_80' : 'https://i.lotrtcgpc.net/errata/LOTR-EN03E080.2_card.jpg', '53_85' : 'https://i.lotrtcgpc.net/errata/LOTR-EN03E085.2_card.jpg', '53_103' : 'https://i.lotrtcgpc.net/errata/LOTR-EN03E103.3_card.jpg', - '53_105' : 'https://i.lotrtcgpc.net/errata/LOTR-EN03E105.2_card.jpg', - - //2024 WC Invitation "Card" - '100_0' : 'https://i.lotrtcgpc.net/other/2024-wc-invite.jpg', + '53_105' : 'https://i.lotrtcgpc.net/errata/LOTR-EN03E105.2_card.jpg' } diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/jCards.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/jCards.js index d963e69cb..4a5e34c60 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/jCards.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/jCards.js @@ -201,7 +201,9 @@ var packBlueprints = { "SHELBI - Aragorn Starter":"/gemp-lotr/images/boosters/shelbi-aragorn.jpg", "SHELBI - Gandalf Starter":"/gemp-lotr/images/boosters/shelbi-gandalf.jpg", "SHELBI - Gimli Starter":"/gemp-lotr/images/boosters/shelbi-gimli.jpg", - "SHELBI - Treebeard Starter":"/gemp-lotr/images/boosters/shelbi-treebeard.jpg" + "SHELBI - Treebeard Starter":"/gemp-lotr/images/boosters/shelbi-treebeard.jpg", + + "2024 World Championship Invitation":"https://i.lotrtcgpc.net/other/2024-wc-invite.jpg" }; class Card { diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/product/Misc-Packs.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/product/Misc-Packs.hjson index 6c621d692..250cbba90 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/product/Misc-Packs.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/product/Misc-Packs.hjson @@ -134,6 +134,15 @@ ] } + { + name: 2024 World Championship Invitation + type: pack + recursive: false + items: [ + 1x2024 World Championship Invitation + ] + } + { name: The Nine Riders Collection type: pack From d3bf3de7f0f3f845a5b76accba0acc23d219c524 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 29 Sep 2024 22:30:28 -0500 Subject: [PATCH 3/5] Deleting card. --- .../unofficial/pc/setV00/V0-shadows-sites.hjson | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV00/V0-shadows-sites.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV00/V0-shadows-sites.hjson index c0dd73f4c..53427c3e4 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV00/V0-shadows-sites.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV00/V0-shadows-sites.hjson @@ -1,20 +1,4 @@ { - 100_0: { - title: 2024 World Championship Invitation - type: Event - twilight: 5 - culture: Elven - keyword: Regroup - effects: { - type: event - effect: [ - { - type: SendMessage - text: The holder of this card is invited to the 2024 World Championship Group Stage. How the hell did you play this card in a game...? - } - ] - } - } 100_1: { cardInfo: { From be20092bc89109c93522026859c2c0899a458cf7 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Mon, 7 Oct 2024 09:09:57 -0500 Subject: [PATCH 4/5] Fixing Nertea and Tol Brandir playing one more minion than the player asked for --- .../cards/official/set01/set1-wraith.hjson | 16 +- .../resources/cards/official/set01/set1.hjson | 102 +++++++++ .../set01/set01-Ringwraith-errata.hjson | 14 +- .../lotro/cards/GenericCardTestHelper.java | 2 + .../official/set01/Card_01_234_Tests.java | 34 +++ .../official/set01/Card_01_363_Tests.java | 207 +++++++++++++----- .../errata/set01/Card_01_234_ErrataTests.java | 37 +++- 7 files changed, 357 insertions(+), 55 deletions(-) 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 5014b4288..744747fd2 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 @@ -1025,12 +1025,22 @@ { type: chooseYesOrNo player: you - text: Would you like to play a minion from your discard pile? + text: Would you like to play a minion from your discard? memorize: choice } { - type: playCardFromDiscard - filter: choose(minion) + 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 9ec5cd6e6..9437e663f 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 @@ -1217,12 +1217,114 @@ effect: { type: playCardFromDiscard filter: choose(tracker) + //This should be updated to "optional" + nocheck: true } } { type: endPhase } ] + + /* + // A less obnoxious version that short-circuits the loop if the + // player ever chooses 0 cards at the prompt. Unfortunately, it + // turns out that "memoryIs" does not check card memory, so this + // is useless until those are unified. + effect: [ + { + type: MemorizeValue + memory: choice + value: default + } + { + type: repeat + amount: 3 + effect: { + type: conditional + requires: [ + { + type: Not + requires: { + type: MemoryIs + memory: choice + value: "" + } + } + { + type: HasCardInDiscard + filter: playable,tracker + } + ] + effect: { + type: playCardFromDiscard + filter: choose(tracker) + memorize: choice + //Forces the choice to allow 0 options + nocheck: true + } + } + } + { + type: endPhase + } + ] + */ + + /* + // An obnoxious version that prompts the user with a question + // for each individual tracker played + effect: [ + { + type: MemorizeValue + memory: choice + value: yes + } + { + type: repeat + amount: 3 + effect: { + type: conditional + requires: [ + { + type: MemoryIs + memory: choice + value: yes + } + { + type: HasCardInDiscard + filter: playable,tracker + } + ] + effect: [ + { + type: chooseYesOrNo + player: you + text: Would you like to play a tracker from your discard pile? + memorize: choice + } + { + type: conditional + requires: [ + { + type: MemoryIs + memory: choice + value: yes + } + ] + effect: { + type: playCardFromDiscard + filter: choose(tracker) + } + } + ] + } + } + { + type: endPhase + } + ] + */ } } } 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 7ae13feaf..90f35f81d 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 @@ -77,8 +77,18 @@ memorize: choice } { - type: playCardFromDiscard - filter: choose(unique,culture(wraith),minion) + 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/GenericCardTestHelper.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java index 8a2ceefa4..f8fcf2fa9 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java @@ -949,6 +949,8 @@ public class GenericCardTestHelper extends AbstractAtTest { public void FreepsDeclineOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P1, ""); } public void ShadowAcceptOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, "0"); } public void ShadowDeclineOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, ""); } + public void FreepsDeclineChoosing() throws DecisionResultInvalidException { playerDecided(P1, ""); } + public void ShadowDeclineChoosing() throws DecisionResultInvalidException { playerDecided(P2, ""); } public void FreepsDeclineReconciliation() throws DecisionResultInvalidException { FreepsPassCurrentPhaseAction(); } public void ShadowDeclineReconciliation() throws DecisionResultInvalidException { ShadowPassCurrentPhaseAction(); } 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 46fc04934..b22006981 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 @@ -182,6 +182,40 @@ public class Card_01_234_Tests assertFalse(scn.ShadowDecisionAvailable("play a minion")); } + @Test + public void NerteaStopsPlayingMinionsIfUserDeclinesPartwayThrough() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + scn.FreepsMoveCharToTable("comp2", "comp3", "comp4", "comp5", "comp6"); + + var twk = scn.GetShadowCard("twk"); + var attea = scn.GetShadowCard("attea"); + var nertea = scn.GetShadowCard("nertea"); + scn.ShadowMoveCardToDiscard("runner", "rit", "twk", "attea"); + scn.ShadowMoveCardToDiscard(twk); + scn.ShadowMoveCardToHand(nertea); + + scn.StartGame(); + scn.SetTwilight(30); + scn.FreepsPassCurrentPhaseAction(); + + scn.ShadowPlayCard(nertea); + assertTrue(scn.ShadowDecisionAvailable("play a minion")); + scn.ShadowChooseYes(); + assertEquals(4, scn.GetShadowCardChoiceCount()); + assertEquals(Zone.DISCARD, twk.getZone()); + scn.ShadowChooseCardBPFromSelection(twk); + assertEquals(Zone.SHADOW_CHARACTERS, twk.getZone()); + + assertTrue(scn.ShadowDecisionAvailable("play a minion")); + assertEquals(Zone.DISCARD, attea.getZone()); + scn.ShadowChooseNo(); + assertEquals(Zone.DISCARD, attea.getZone()); + + assertFalse(scn.ShadowDecisionAvailable("play a minion")); + } + @Test public void NerteaDoesNotPromptIfNoMinionsInDiscardPile() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_363_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_363_Tests.java index 0d425de31..6cb979bd3 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_363_Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_363_Tests.java @@ -5,6 +5,7 @@ import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.CardType; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; @@ -21,11 +22,11 @@ public class Card_01_363_Tests protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { return new GenericCardTestHelper( new HashMap<>() {{ - put("greenleaf", "1_50"); - put("moriatroop1", "1_177"); - put("moriatroop2", "1_177"); - put("moriatroop3", "1_177"); + put("tracker1", "1_261"); + put("tracker2", "1_262"); + put("tracker3", "1_270"); put("shelob", "8_26"); + put("hollowing", "3_54"); }}, new HashMap<>() {{ put("site1", "1_319"); @@ -58,7 +59,7 @@ public class Card_01_363_Tests //Pre-game setup GenericCardTestHelper scn = GetScenario(); - PhysicalCardImpl site9 = scn.GetFreepsSite(9); + var site9 = scn.GetFreepsSite(9); assertFalse(site9.getBlueprint().isUnique()); assertEquals(CardType.SITE, site9.getBlueprint().getCardType()); @@ -72,60 +73,168 @@ public class Card_01_363_Tests //Pre-game setup GenericCardTestHelper scn = GetScenario(); - PhysicalCardImpl moriatroop1 = scn.GetShadowCard("moriatroop1"); - PhysicalCardImpl moriatroop2 = scn.GetShadowCard("moriatroop2"); - PhysicalCardImpl moriatroop3 = scn.GetShadowCard("moriatroop3"); - PhysicalCardImpl shelob = scn.GetShadowCard("shelob"); - scn.ShadowMoveCardToHand(moriatroop1, moriatroop2, moriatroop3, shelob); - - //Max out the move limit so we don't have to juggle play back and forth - scn.ApplyAdHocModifier(new MoveLimitModifier(null, 10)); + var tolbrandir = scn.GetShadowSite(9); + var tracker1 = scn.GetShadowCard("tracker1"); + var tracker2 = scn.GetShadowCard("tracker2"); + var tracker3 = scn.GetShadowCard("tracker3"); + var hollowing = scn.GetShadowCard("hollowing"); + scn.ShadowMoveCardToSupportArea(hollowing); + scn.ShadowMoveCardToDiscard(tracker1, tracker2, tracker3); + scn.ShadowMoveCardToDiscard("shelob"); scn.StartGame(); - // 1 -> 3 - scn.SkipToPhase(Phase.REGROUP); - scn.PassCurrentPhaseActions(); - scn.ShadowDeclineReconciliation(); - scn.FreepsChooseToMove(); + scn.SkipToSite(8); + scn.FreepsPassCurrentPhaseAction(); - // 3 -> 4 - scn.SkipToPhase(Phase.REGROUP); - scn.PassCurrentPhaseActions(); - scn.ShadowDeclineReconciliation(); - scn.FreepsChooseToMove(); + assertSame(tolbrandir, scn.GetCurrentSite()); + assertTrue(scn.ShadowActionAvailable(tolbrandir)); + assertTrue(scn.ShadowActionAvailable(hollowing)); + assertEquals(Zone.DISCARD, tracker1.getZone()); + assertEquals(Zone.DISCARD, tracker2.getZone()); + assertEquals(Zone.DISCARD, tracker3.getZone()); + assertEquals(10, scn.GetTwilight()); - // 4 -> 5 - scn.SkipToPhase(Phase.REGROUP); - scn.PassCurrentPhaseActions(); - scn.ShadowDeclineReconciliation(); - scn.FreepsChooseToMove(); + scn.ShadowUseCardAction(tolbrandir); + assertTrue(scn.ShadowDecisionAvailable("Choose card from discard")); + //Should not have the non-tracker in the choice pool + assertEquals(3, scn.ShadowGetBPChoices().size()); - // 5 -> 6 - scn.SkipToPhase(Phase.REGROUP); - scn.PassCurrentPhaseActions(); - scn.ShadowDeclineReconciliation(); - scn.FreepsChooseToMove(); + scn.ShadowChooseCardBPFromSelection(tracker1); + assertEquals(Zone.SHADOW_CHARACTERS, tracker1.getZone()); + assertEquals(9, scn.GetTwilight()); + assertTrue(scn.ShadowDecisionAvailable("Choose card from discard")); - // 6 -> 7 - scn.SkipToPhase(Phase.REGROUP); - scn.PassCurrentPhaseActions(); - scn.ShadowDeclineReconciliation(); - scn.FreepsChooseToMove(); + scn.ShadowChooseCardBPFromSelection(tracker2); + assertEquals(Zone.SHADOW_CHARACTERS, tracker2.getZone()); + assertEquals(7, scn.GetTwilight()); + assertTrue(scn.ShadowDecisionAvailable("Choose card from discard")); - // 7 -> 8 - scn.SkipToPhase(Phase.REGROUP); - scn.PassCurrentPhaseActions(); - scn.ShadowDeclineReconciliation(); - scn.FreepsChooseToMove(); + scn.ShadowChooseCardBPFromSelection(tracker3); + assertEquals(Zone.SHADOW_CHARACTERS, tracker3.getZone()); + assertEquals(4, scn.GetTwilight()); - // 8 -> 9 - scn.SkipToPhase(Phase.REGROUP); - scn.PassCurrentPhaseActions(); - scn.ShadowDeclineReconciliation(); - scn.FreepsChooseToMove(); + //No more shadow actions should be permitted (but Shadow is still required to pass manually) + assertFalse(scn.ShadowActionAvailable(hollowing)); + } - //TODO: actually finish this + @Test + public void TolBrandirActionCanPlay0TrackersAndDecline3() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + var tolbrandir = scn.GetShadowSite(9); + var tracker1 = scn.GetShadowCard("tracker1"); + var tracker2 = scn.GetShadowCard("tracker2"); + var tracker3 = scn.GetShadowCard("tracker3"); + scn.ShadowMoveCardToDiscard(tracker1, tracker2, tracker3); + + scn.StartGame(); + + scn.SkipToSite(8); + scn.FreepsPassCurrentPhaseAction(); + + assertSame(tolbrandir, scn.GetCurrentSite()); + assertTrue(scn.ShadowActionAvailable(tolbrandir)); + assertEquals(Zone.DISCARD, tracker1.getZone()); + assertEquals(Zone.DISCARD, tracker2.getZone()); + assertEquals(Zone.DISCARD, tracker3.getZone()); + assertEquals(10, scn.GetTwilight()); + + scn.ShadowUseCardAction(tolbrandir); + assertTrue(scn.ShadowDecisionAvailable("Choose card from discard")); + //Should not have the non-tracker in the choice pool + assertEquals(3, scn.ShadowGetBPChoices().size()); + + scn.ShadowDeclineChoosing(); + scn.ShadowDeclineChoosing(); + scn.ShadowDeclineChoosing(); + assertEquals(Zone.DISCARD, tracker1.getZone()); + assertEquals(Zone.DISCARD, tracker2.getZone()); + assertEquals(Zone.DISCARD, tracker3.getZone()); + assertTrue(scn.ShadowDecisionAvailable("Play Shadow action or pass")); + } + + @Test + public void TolBrandirActionCanPlay1TrackerAndDecline2() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + var tolbrandir = scn.GetShadowSite(9); + var tracker1 = scn.GetShadowCard("tracker1"); + var tracker2 = scn.GetShadowCard("tracker2"); + var tracker3 = scn.GetShadowCard("tracker3"); + scn.ShadowMoveCardToDiscard(tracker1, tracker2, tracker3); + + scn.StartGame(); + + scn.SkipToSite(8); + scn.FreepsPassCurrentPhaseAction(); + + assertSame(tolbrandir, scn.GetCurrentSite()); + assertTrue(scn.ShadowActionAvailable(tolbrandir)); + assertEquals(Zone.DISCARD, tracker1.getZone()); + assertEquals(Zone.DISCARD, tracker2.getZone()); + assertEquals(Zone.DISCARD, tracker3.getZone()); + assertEquals(10, scn.GetTwilight()); + + scn.ShadowUseCardAction(tolbrandir); + assertTrue(scn.ShadowDecisionAvailable("Choose card from discard")); + //Should not have the non-tracker in the choice pool + assertEquals(3, scn.ShadowGetBPChoices().size()); + + scn.ShadowChooseCardBPFromSelection(tracker1); + assertEquals(Zone.SHADOW_CHARACTERS, tracker1.getZone()); + assertEquals(9, scn.GetTwilight()); + assertTrue(scn.ShadowDecisionAvailable("Choose card from discard")); + + scn.ShadowDeclineChoosing(); + scn.ShadowDeclineChoosing(); + assertEquals(Zone.DISCARD, tracker2.getZone()); + assertEquals(Zone.DISCARD, tracker3.getZone()); + assertTrue(scn.ShadowDecisionAvailable("Play Shadow action or pass")); + } + + @Test + public void TolBrandirActionCanPlay2TrackersAndDecline1() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + var tolbrandir = scn.GetShadowSite(9); + var tracker1 = scn.GetShadowCard("tracker1"); + var tracker2 = scn.GetShadowCard("tracker2"); + var tracker3 = scn.GetShadowCard("tracker3"); + scn.ShadowMoveCardToDiscard(tracker1, tracker2, tracker3); + + scn.StartGame(); + + scn.SkipToSite(8); + scn.FreepsPassCurrentPhaseAction(); + + assertSame(tolbrandir, scn.GetCurrentSite()); + assertTrue(scn.ShadowActionAvailable(tolbrandir)); + assertEquals(Zone.DISCARD, tracker1.getZone()); + assertEquals(Zone.DISCARD, tracker2.getZone()); + assertEquals(Zone.DISCARD, tracker3.getZone()); + assertEquals(10, scn.GetTwilight()); + + scn.ShadowUseCardAction(tolbrandir); + assertTrue(scn.ShadowDecisionAvailable("Choose card from discard")); + //Should not have the non-tracker in the choice pool + assertEquals(3, scn.ShadowGetBPChoices().size()); + + scn.ShadowChooseCardBPFromSelection(tracker1); + assertEquals(Zone.SHADOW_CHARACTERS, tracker1.getZone()); + assertEquals(9, scn.GetTwilight()); + assertTrue(scn.ShadowDecisionAvailable("Choose card from discard")); + + scn.ShadowChooseCardBPFromSelection(tracker2); + assertEquals(Zone.SHADOW_CHARACTERS, tracker2.getZone()); + assertEquals(7, scn.GetTwilight()); + assertTrue(scn.ShadowDecisionAvailable("Choose card from discard")); + + scn.ShadowDeclineChoosing(); + assertEquals(Zone.DISCARD, tracker3.getZone()); + assertTrue(scn.ShadowDecisionAvailable("Play Shadow action or pass")); } } 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 4a929ac89..128efe00c 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 @@ -180,6 +180,41 @@ public class Card_01_234_ErrataTests assertFalse(scn.ShadowDecisionAvailable("play a unique WRAITH minion")); } + @Test + public void NerteaStopsPlayingMinionsIfUserDeclinesPartwayThrough() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + scn.FreepsMoveCharToTable("comp2", "comp3", "comp4", "comp5", "comp6"); + + var twk = scn.GetShadowCard("twk"); + var attea = scn.GetShadowCard("attea"); + var nertea = scn.GetShadowCard("nertea"); + scn.ShadowMoveCardToDiscard("runner", "rit", "twk", "attea"); + scn.ShadowMoveCardToDiscard(twk); + scn.ShadowMoveCardToHand(nertea); + + scn.StartGame(); + scn.SetTwilight(30); + scn.FreepsPassCurrentPhaseAction(); + + scn.ShadowPlayCard(nertea); + assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion")); + scn.ShadowChooseYes(); + //twk and attea, but not rit or runner + assertEquals(2, scn.GetShadowCardChoiceCount()); + assertEquals(Zone.DISCARD, twk.getZone()); + scn.ShadowChooseCardBPFromSelection(twk); + assertEquals(Zone.SHADOW_CHARACTERS, twk.getZone()); + + assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion")); + assertEquals(Zone.DISCARD, attea.getZone()); + scn.ShadowChooseNo(); + assertEquals(Zone.DISCARD, attea.getZone()); + + assertFalse(scn.ShadowDecisionAvailable("play a unique WRAITH minion")); + } + @Test public void NerteaDoesNotPromptIfNoUniqueRingwraithMinionsInDiscardPile() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup @@ -202,7 +237,7 @@ public class Card_01_234_ErrataTests //Imported from the at tests @Test - public void ulaireNerteaCantPlayMinionsOnGreatRiver() throws Exception { + public void UlaireNerteaCantPlayMinionsOnGreatRiver() throws Exception { var scn = GetScenario(); var _game = scn._game; From 7d065bd5508ee5e24eb670ad88bea02ca7c7d8cc Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Wed, 16 Oct 2024 18:16:02 -0500 Subject: [PATCH 5/5] Fixing Glimpse of Fate PC errata being required instead of optional --- .../cards/unofficial/pc/errata/set10/set10-Elven-errata.hjson | 1 + 1 file changed, 1 insertion(+) diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set10/set10-Elven-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set10/set10-Elven-errata.hjson index 51ed5a806..da3de578d 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set10/set10-Elven-errata.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set10/set10-Elven-errata.hjson @@ -305,6 +305,7 @@ } effects: { type: trigger + optional: true trigger: { type: losesInitiative side: free peoples