From 832bd21183fbafa62af907f8c24ea752751b6a9b Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 14 Aug 2022 17:38:38 -0500 Subject: [PATCH] Fixes and Errata - Fixed Here Lies Balin from not working on a single 1-vitality orc - Errata'd Merry, Of Buckland to require 3 exertions - Reworked Amon Hen Ruins to applying damage +1 per wound on each minion - Errata'd Corsair Marauder again to instead only discard Shadow possessions --- .../cards/official/set01/set1-dwarven.hjson | 46 ++-- .../cards/official/set08/set08-raider.hjson | 35 +++ .../pc/errata/set08-errata-playtest.hjson | 34 ++- .../pc/setV01/V1_shire_playtest.hjson | 2 +- .../pc/setV01/V1_sites_playtest.hjson | 16 +- .../lotro/cards/set8/raider/Card8_057.java | 57 ----- .../lotro/cards/GenericCardTestHelper.java | 4 + .../official/set01/Card_01_018_Tests.java | 15 +- .../official/set01/Card_01_019_Tests.java | 199 ++++++++++++++++++ .../official/set08/Card_08_057_Tests.java | 146 +++++++++++++ .../errata/set08/Card_08_057_ErrataTests.java | 145 +++++++++++++ .../pc/vsets/set_v01/Card_V1_052_Tests.java | 8 +- .../pc/vsets/set_v01/Card_V1_064_Tests.java | 68 +++--- 13 files changed, 639 insertions(+), 136 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-async/src/main/web/cards/official/set08/set08-raider.hjson delete mode 100644 gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set8/raider/Card8_057.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_019_Tests.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set08/Card_08_057_Tests.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set08/Card_08_057_ErrataTests.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/official/set01/set1-dwarven.hjson b/gemp-lotr/gemp-lotr-async/src/main/web/cards/official/set01/set1-dwarven.hjson index 383653b98..7d8868c52 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/official/set01/set1-dwarven.hjson +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/official/set01/set1-dwarven.hjson @@ -508,25 +508,33 @@ type: exert filter: choose(dwarf) } - effect: { - type: choice - texts: [ - Wound 2 Orcs - Wound 1 Orc twice - ] - effects: [ - { - type: wound - count: 2 - filter: choose(orc) - } - { - type: wound - filter: choose(orc) - times: 2 - } - ] - } + effect: [ + { + type: choice + texts: [ + Wound 2 Orcs + Wound 1 Orc twice + ] + effects: [ + { + type: wound + count: 2 + filter: choose(orc) + } + { + type: chooseActiveCards + memorize: chosenOrc + filter: choose(orc) + text: Choose an Orc to wound twice + } + ] + } + { + type: wound + filter: memory(chosenOrc) + times: 2 + } + ] } } 1_20: { diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/official/set08/set08-raider.hjson b/gemp-lotr/gemp-lotr-async/src/main/web/cards/official/set08/set08-raider.hjson new file mode 100644 index 000000000..c80ef4ec4 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/official/set08/set08-raider.hjson @@ -0,0 +1,35 @@ +{ + 8_57: { + title: Corsair Marauder + culture: Raider + twilight: 4 + type: minion + race: Man + strength: 9 + vitality: 2 + site: 4 + keyword: Corsair + effects: { + type: trigger + optional: true + trigger: { + type: played + filter: self + } + requires: { + type: canSpot + filter: not(self),corsair + } + cost: { + type: discard + filter: choose(possession) + } + effect: { + type: addTokens + culture: raider + filter: choose(hasToken(raider)) + amount: 2 + } + } + } +} diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/errata/set08-errata-playtest.hjson b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/errata/set08-errata-playtest.hjson index 0db3279e4..66061c043 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/errata/set08-errata-playtest.hjson +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/errata/set08-errata-playtest.hjson @@ -1,3 +1,35 @@ { - + 78_57: { + title: Corsair Marauder + culture: Raider + twilight: 4 + type: minion + race: Man + strength: 9 + vitality: 2 + site: 4 + keyword: Corsair + effects: { + type: trigger + optional: true + trigger: { + type: played + filter: self + } + requires: { + type: canSpot + filter: not(self),corsair + } + cost: { + type: discard + filter: choose(possession,side(Shadow)) + } + effect: { + type: addTokens + culture: raider + filter: choose(hasToken(raider)) + amount: 2 + } + } + } } diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/V1_shire_playtest.hjson b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/V1_shire_playtest.hjson index 2b301671c..1136d07df 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/V1_shire_playtest.hjson +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/V1_shire_playtest.hjson @@ -92,7 +92,7 @@ { type: exert filter: self - times: 2 + times: 3 } { type: chooseActiveCards diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/V1_sites_playtest.hjson b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/V1_sites_playtest.hjson index 31e61b592..608f69136 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/V1_sites_playtest.hjson +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/V1_sites_playtest.hjson @@ -201,7 +201,7 @@ } 151_64: { - title: Henneth Anun Glade + title: Amon Hen Ruins twilight: 9 type: site site: 9 @@ -212,16 +212,12 @@ { type: modifier modifier: { - type: canttakewounds + type: addKeyword filter: minion,wounded - } - } - { - type: modifier - modifier: { - type: cantbeexerted - filter: companion,wounded - by: side(free peoples) + keyword: damage+1 + amount: { + type: forEachWound + } } } ] diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set8/raider/Card8_057.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set8/raider/Card8_057.java deleted file mode 100644 index 4735158b5..000000000 --- a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set8/raider/Card8_057.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.gempukku.lotro.cards.set8.raider; - -import com.gempukku.lotro.logic.cardtype.AbstractMinion; -import com.gempukku.lotro.logic.timing.PlayConditions; -import com.gempukku.lotro.logic.timing.TriggerConditions; -import com.gempukku.lotro.logic.effects.AddTokenEffect; -import com.gempukku.lotro.logic.effects.choose.ChooseAndDiscardCardsFromPlayEffect; -import com.gempukku.lotro.common.*; -import com.gempukku.lotro.filters.Filters; -import com.gempukku.lotro.game.PhysicalCard; -import com.gempukku.lotro.game.state.LotroGame; -import com.gempukku.lotro.logic.actions.OptionalTriggerAction; -import com.gempukku.lotro.logic.effects.ChooseActiveCardEffect; -import com.gempukku.lotro.logic.timing.EffectResult; - -import java.util.Collections; -import java.util.List; - -/** - * Set: Siege of Gondor - * Side: Shadow - * Culture: Raider - * Twilight Cost: 4 - * Type: Minion • Man - * Strength: 9 - * Vitality: 2 - * Site: 4 - * Game Text: Corsair. When you play this minion, if you can spot another corsair, you may discard a possession to add - * 2 [RAIDER] tokens to a card that already has a [RAIDER] token on it. - */ -public class Card8_057 extends AbstractMinion { - public Card8_057() { - super(4, 9, 2, 4, Race.MAN, Culture.RAIDER, "Corsair Marauder"); - addKeyword(Keyword.CORSAIR); - } - - @Override - public List getOptionalAfterTriggers(String playerId, LotroGame game, EffectResult effectResult, final PhysicalCard self) { - if (TriggerConditions.played(game, effectResult, self) - && PlayConditions.canSpot(game, Filters.not(self), Keyword.CORSAIR) - && PlayConditions.canDiscardFromPlay(self, game, CardType.POSSESSION)) { - final OptionalTriggerAction action = new OptionalTriggerAction(self); - action.appendCost( - new ChooseAndDiscardCardsFromPlayEffect(action, playerId, 1, 1, CardType.POSSESSION)); - action.appendEffect( - new ChooseActiveCardEffect(self, playerId, "Choose a card to add tokens to", Filters.hasToken(Token.RAIDER)) { - @Override - protected void cardSelected(LotroGame game, PhysicalCard card) { - action.insertEffect( - new AddTokenEffect(self, card, Token.RAIDER, 2)); - } - }); - return Collections.singletonList(action); - } - return null; - } -} 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 5d96a5386..e4cc2af08 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 @@ -255,6 +255,10 @@ public class GenericCardTestHelper extends AbstractAtTest { public int ShadowGetWoundsOn(String cardName) { return GetWoundsOn(GetShadowCard(cardName)); } public int GetWoundsOn(PhysicalCardImpl card) { return _game.getGameState().getWounds(card); } + public int FreepsGetCultureTokensOn(String cardName) { return GetCultureTokensOn(GetFreepsCard(cardName)); } + public int ShadowGetCultureTokensOn(String cardName) { return GetCultureTokensOn(GetShadowCard(cardName)); } + public int GetCultureTokensOn(PhysicalCardImpl card) { return _game.getGameState().getTokenCount(card, Token.findTokenForCulture(card.getBlueprint().getCulture())); } + public int GetBurdens() { return _game.getGameState().getBurdens(); } public int GetFreepsArcheryTotal() { return RuleUtils.calculateFellowshipArcheryTotal(_game); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_018_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_018_Tests.java index b51e1962b..a04743186 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_018_Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_018_Tests.java @@ -39,16 +39,15 @@ public class Card_01_018_Tests public void HallsStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { /** - * Set: V1 - * Title: *A Shadow of the Past + * Set: 1 + * Title: Halls of My Home * Side: Free Peoples - * Culture: sauron + * Culture: Dwarven * Twilight Cost: 1 - * Type: condition - * Subtype: Support Area - * Game Text: While you can spot 4 burdens, each [sauron] Orc is fierce. - * While you can spot 6 burdens, each [Sauron] Orc is damage +1. - * Discard this condition at the start of the regroup phase. + * Type: Event + * Subtype: Fellowship + * Game Text: Fellowship: Exert a Dwarf to reveal the top 3 cards of any draw deck. You may discard 1 Shadow card revealed. + * Return the rest in any order. */ //Pre-game setup diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_019_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_019_Tests.java new file mode 100644 index 000000000..e01c45c86 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_019_Tests.java @@ -0,0 +1,199 @@ +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.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; +import java.util.List; + +import static org.junit.Assert.*; + + +public class Card_01_019_Tests +{ + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap<>() {{ + put("balin", "1_19"); + put("gimli", "1_13"); + + put("runner1", "1_178"); + put("runner2", "1_178"); + put("scout", "1_191"); + + }} + ); + } + + @Test + public void HereLiesBalinStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1 + * Title: Here Lies Balin, Son of Fundin + * Side: Free Peoples + * Culture: Dwarven + * Twilight Cost: 0 + * Type: Event + * Subtype: Maneuver + * Game Text: Maneuver: Exert a Dwarf to wound 2 Orcs or to wound 1 Orc twice. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl balin = scn.GetFreepsCard("balin"); + + assertFalse(balin.getBlueprint().isUnique()); + assertEquals(Side.FREE_PEOPLE, balin.getBlueprint().getSide()); + assertEquals(Culture.DWARVEN, balin.getBlueprint().getCulture()); + assertEquals(CardType.EVENT, balin.getBlueprint().getCardType()); + //assertEquals(Race.CREATURE, balin.getBlueprint().getRace()); + assertTrue(scn.HasKeyword(balin, Keyword.MANEUVER)); // test for keywords as needed + assertEquals(0, balin.getBlueprint().getTwilightCost()); + //assertEquals(, balin.getBlueprint().getStrength()); + //assertEquals(, balin.getBlueprint().getVitality()); + //assertEquals(, balin.getBlueprint().getResistance()); + //assertEquals(Signet., balin.getBlueprint().getSignet()); + //assertEquals(, balin.getBlueprint().getSiteNumber()); // Change this to getAllyHomeSiteNumbers for allies + + } + + @Test + public void BalinCanWound2OrcsOnce() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); + PhysicalCardImpl balin = scn.GetFreepsCard("balin"); + scn.FreepsMoveCharToTable(gimli); + scn.FreepsMoveCardToHand(balin); + + PhysicalCardImpl runner1 = scn.GetShadowCard("runner1"); + PhysicalCardImpl runner2 = scn.GetShadowCard("runner2"); + PhysicalCardImpl scout = scn.GetShadowCard("scout"); + scn.ShadowMoveCharToTable(runner1, runner2); + + scn.StartGame(); + + scn.SkipToPhase(Phase.MANEUVER); + + assertEquals(0, scn.GetWoundsOn(gimli)); + assertEquals(Zone.SHADOW_CHARACTERS, runner1.getZone()); + assertEquals(Zone.SHADOW_CHARACTERS, runner2.getZone()); + + assertTrue(scn.FreepsCardPlayAvailable(balin)); + scn.FreepsPlayCard(balin); + + assertTrue(scn.FreepsDecisionAvailable("Choose action")); + scn.FreepsChooseMultipleChoiceOption("Wound 2 Orcs"); + + assertEquals(1, scn.GetWoundsOn(gimli)); + assertEquals(Zone.DISCARD, runner1.getZone()); + assertEquals(Zone.DISCARD, runner2.getZone()); + } + + @Test + public void BalinCanWound1OrcTwice() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); + PhysicalCardImpl balin = scn.GetFreepsCard("balin"); + scn.FreepsMoveCharToTable(gimli); + scn.FreepsMoveCardToHand(balin); + + PhysicalCardImpl runner1 = scn.GetShadowCard("runner1"); + PhysicalCardImpl runner2 = scn.GetShadowCard("runner2"); + PhysicalCardImpl scout = scn.GetShadowCard("scout"); + scn.ShadowMoveCharToTable(scout); + + scn.StartGame(); + + scn.SkipToPhase(Phase.MANEUVER); + + assertEquals(0, scn.GetWoundsOn(gimli)); + assertEquals(Zone.SHADOW_CHARACTERS, scout.getZone()); + assertEquals(0, scn.GetWoundsOn(scout)); + + assertTrue(scn.FreepsCardPlayAvailable(balin)); + scn.FreepsPlayCard(balin); + + assertEquals(1, scn.GetWoundsOn(gimli)); + assertEquals(Zone.DISCARD, scout.getZone()); + } + + @Test + public void FreepsMustChooseTwoOrcOrOneOrcToWoundTwice() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); + PhysicalCardImpl balin = scn.GetFreepsCard("balin"); + scn.FreepsMoveCharToTable(gimli); + scn.FreepsMoveCardToHand(balin); + + PhysicalCardImpl runner1 = scn.GetShadowCard("runner1"); + PhysicalCardImpl runner2 = scn.GetShadowCard("runner2"); + PhysicalCardImpl scout = scn.GetShadowCard("scout"); + scn.ShadowMoveCharToTable(runner1, runner2, scout); + + scn.StartGame(); + + scn.SkipToPhase(Phase.MANEUVER); + + assertEquals(0, scn.GetWoundsOn(gimli)); + assertEquals(Zone.SHADOW_CHARACTERS, scout.getZone()); + assertEquals(0, scn.GetWoundsOn(scout)); + + assertTrue(scn.FreepsCardPlayAvailable(balin)); + scn.FreepsPlayCard(balin); + + assertTrue(scn.FreepsDecisionAvailable("Choose action")); + assertEquals(2, scn.FreepsGetMultipleChoices().size()); + } + + @Test + public void OneOrcWith1VitalityCanBeHitByHereLiesBalin() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); + PhysicalCardImpl balin = scn.GetFreepsCard("balin"); + scn.FreepsMoveCharToTable(gimli); + scn.FreepsMoveCardToHand(balin); + + PhysicalCardImpl runner1 = scn.GetShadowCard("runner1"); + PhysicalCardImpl runner2 = scn.GetShadowCard("runner2"); + PhysicalCardImpl scout = scn.GetShadowCard("scout"); + scn.ShadowMoveCharToTable(runner1); + + scn.StartGame(); + + scn.SkipToPhase(Phase.MANEUVER); + + assertEquals(0, scn.GetWoundsOn(gimli)); + assertEquals(Zone.SHADOW_CHARACTERS, runner1.getZone()); + assertEquals(0, scn.GetWoundsOn(runner1)); + + assertTrue(scn.FreepsCardPlayAvailable(balin)); + scn.FreepsPlayCard(balin); + + //https://wiki.lotrtcgpc.net/wiki/Comprehensive_Rules_4.1#effect + //"If the effect of a card or special ability requires you to choose one of two different actions, + // you must choose an action that you are fully capable of performing (if possible)." + // As a result, if you can neither "wound 2 orcs" or "wound 1 orc twice", none of the choices are possible. + // You then back up and choose the option you are most capable of performing (I guess) + + assertEquals(Zone.DISCARD, runner1.getZone()); + } + + + + + +} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set08/Card_08_057_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set08/Card_08_057_Tests.java new file mode 100644 index 000000000..eab841a2e --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set08/Card_08_057_Tests.java @@ -0,0 +1,146 @@ +package com.gempukku.lotro.cards.official.set08; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.*; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static org.junit.Assert.*; + +public class Card_08_057_Tests +{ + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap<>() {{ + put("marauder", "8_57"); + put("corsair", "8_56"); + + put("cart", "1_73"); + + put("blacksails1", "8_50"); + put("blacksails2", "8_50"); + }} + ); + } + + @Test + public void CorsairMarauderStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 8 + * Title: Corsair Marauder + * Side: Shadow + * Culture: Raider + * Twilight Cost: 4 + * Type: Minion + * Race: Man + * Strength: 9 + * Vitality: 2 + * Site Number: 4 + * Errata Game Text: Corsair. When you play this minion, if you can spot another corsair, you may discard a + * possession to add 2 [RAIDER] tokens to a card that already has a [RAIDER] token on it. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl marauder = scn.GetFreepsCard("marauder"); + + assertFalse(marauder.getBlueprint().isUnique()); + assertEquals(4, marauder.getBlueprint().getTwilightCost()); + assertEquals(CardType.MINION, marauder.getBlueprint().getCardType()); + assertEquals(Culture.RAIDER, marauder.getBlueprint().getCulture()); + assertTrue(marauder.getBlueprint().hasKeyword(Keyword.CORSAIR)); + assertEquals(Race.MAN, marauder.getBlueprint().getRace()); + assertEquals(9, marauder.getBlueprint().getStrength()); + assertEquals(2, marauder.getBlueprint().getVitality()); + assertEquals(4, marauder.getBlueprint().getSiteNumber()); + } + + @Test + public void IfYouCannotSpotAnotherCorsairOnPlayNothingHappens() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl marauder = scn.GetShadowCard("marauder"); + PhysicalCardImpl corsair = scn.GetShadowCard("corsair"); + PhysicalCardImpl blacksails1 = scn.GetShadowCard("blacksails1"); + PhysicalCardImpl blacksails2 = scn.GetShadowCard("blacksails2"); + scn.ShadowMoveCardToHand(marauder, corsair, blacksails1, blacksails2); + + PhysicalCardImpl cart = scn.GetFreepsCard("cart"); + scn.FreepsMoveCardToSupportArea(cart); + + scn.StartGame(); + + scn.SetTwilight(10); + + scn.FreepsPassCurrentPhaseAction(); + + scn.ShadowPlayCard(blacksails1); + scn.ShadowAcceptOptionalTrigger(); + + assertEquals(1, scn.GetCultureTokensOn(blacksails1)); + assertEquals(Zone.SUPPORT, blacksails1.getZone()); + assertEquals(Zone.SUPPORT, cart.getZone()); + + scn.ShadowPlayCard(marauder); + + assertEquals(1, scn.GetCultureTokensOn(blacksails1)); + assertEquals(Zone.SUPPORT, blacksails1.getZone()); + assertEquals(Zone.SUPPORT, cart.getZone()); + } + + @Test + public void IfAnotherCorsairOnPlayCanDiscardAPossessionToAdd2Tokens() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl marauder = scn.GetShadowCard("marauder"); + PhysicalCardImpl corsair = scn.GetShadowCard("corsair"); + PhysicalCardImpl blacksails1 = scn.GetShadowCard("blacksails1"); + PhysicalCardImpl blacksails2 = scn.GetShadowCard("blacksails2"); + scn.ShadowMoveCardToHand(marauder, blacksails1, blacksails2); + scn.ShadowMoveCharToTable(corsair); + + PhysicalCardImpl cart = scn.GetFreepsCard("cart"); + scn.FreepsMoveCardToSupportArea(cart); + + scn.StartGame(); + + scn.SetTwilight(10); + + scn.FreepsPassCurrentPhaseAction(); + + scn.ShadowPlayCard(blacksails1); + scn.ShadowAcceptOptionalTrigger(); + scn.ShadowPlayCard(blacksails2); + scn.ShadowDeclineOptionalTrigger(); + + assertEquals(1, scn.GetCultureTokensOn(blacksails1)); + assertEquals(0, scn.GetCultureTokensOn(blacksails2)); + assertEquals(Zone.SUPPORT, blacksails1.getZone()); + assertEquals(Zone.SUPPORT, blacksails2.getZone()); + assertEquals(Zone.SUPPORT, cart.getZone()); + + scn.ShadowPlayCard(marauder); + + scn.ShadowAcceptOptionalTrigger(); + assertTrue(scn.ShadowDecisionAvailable("Choose cards to discard")); + assertEquals(3, scn.GetShadowCardChoiceCount()); //1x Gandalf's Cart, 2x Black Sails + + scn.ShadowChooseCard(cart); + + assertEquals(3, scn.GetCultureTokensOn(blacksails1)); // Only valid choice + assertEquals(0, scn.GetCultureTokensOn(blacksails2)); + assertEquals(Zone.SUPPORT, blacksails1.getZone()); + assertEquals(Zone.SUPPORT, blacksails2.getZone()); + assertEquals(Zone.DISCARD, cart.getZone()); + } + + +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set08/Card_08_057_ErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set08/Card_08_057_ErrataTests.java new file mode 100644 index 000000000..c91ad2874 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set08/Card_08_057_ErrataTests.java @@ -0,0 +1,145 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata.set08; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.*; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static org.junit.Assert.*; + +public class Card_08_057_ErrataTests +{ + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap<>() {{ + put("marauder", "78_57"); + put("corsair", "8_56"); + + put("cart", "1_73"); + + put("blacksails1", "8_50"); + put("blacksails2", "8_50"); + }} + ); + } + + @Test + public void CorsairMarauderStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 8E + * Title: Corsair Marauder + * Side: Shadow + * Culture: Raider + * Twilight Cost: 4 + * Type: Minion + * Race: Man + * Strength: 9 + * Vitality: 2 + * Site Number: 4 + * Errata Game Text: Corsair. When you play this minion, if you can spot another corsair, you may discard a + * Shadow possession to add 2 [RAIDER] tokens to a card that already has a [RAIDER] token on it. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl marauder = scn.GetFreepsCard("marauder"); + + assertFalse(marauder.getBlueprint().isUnique()); + assertEquals(4, marauder.getBlueprint().getTwilightCost()); + assertEquals(CardType.MINION, marauder.getBlueprint().getCardType()); + assertEquals(Culture.RAIDER, marauder.getBlueprint().getCulture()); + assertTrue(marauder.getBlueprint().hasKeyword(Keyword.CORSAIR)); + assertEquals(Race.MAN, marauder.getBlueprint().getRace()); + assertEquals(9, marauder.getBlueprint().getStrength()); + assertEquals(2, marauder.getBlueprint().getVitality()); + assertEquals(4, marauder.getBlueprint().getSiteNumber()); + } + + @Test + public void IfYouCannotSpotAnotherCorsairOnPlayNothingHappens() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl marauder = scn.GetShadowCard("marauder"); + PhysicalCardImpl corsair = scn.GetShadowCard("corsair"); + PhysicalCardImpl blacksails1 = scn.GetShadowCard("blacksails1"); + PhysicalCardImpl blacksails2 = scn.GetShadowCard("blacksails2"); + scn.ShadowMoveCardToHand(marauder, corsair, blacksails1, blacksails2); + + PhysicalCardImpl cart = scn.GetFreepsCard("cart"); + scn.FreepsMoveCardToSupportArea(cart); + + scn.StartGame(); + + scn.SetTwilight(10); + + scn.FreepsPassCurrentPhaseAction(); + + scn.ShadowPlayCard(blacksails1); + scn.ShadowAcceptOptionalTrigger(); + + assertEquals(1, scn.GetCultureTokensOn(blacksails1)); + assertEquals(Zone.SUPPORT, blacksails1.getZone()); + assertEquals(Zone.SUPPORT, cart.getZone()); + + scn.ShadowPlayCard(marauder); + + assertEquals(1, scn.GetCultureTokensOn(blacksails1)); + assertEquals(Zone.SUPPORT, blacksails1.getZone()); + assertEquals(Zone.SUPPORT, cart.getZone()); + } + + @Test + public void IfAnotherCorsairOnPlayCanDiscardAShadowPossessionToAdd2Tokens() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl marauder = scn.GetShadowCard("marauder"); + PhysicalCardImpl corsair = scn.GetShadowCard("corsair"); + PhysicalCardImpl blacksails1 = scn.GetShadowCard("blacksails1"); + PhysicalCardImpl blacksails2 = scn.GetShadowCard("blacksails2"); + scn.ShadowMoveCardToHand(marauder, blacksails1, blacksails2); + scn.ShadowMoveCharToTable(corsair); + + PhysicalCardImpl cart = scn.GetFreepsCard("cart"); + scn.FreepsMoveCardToSupportArea(cart); + + scn.StartGame(); + + scn.SetTwilight(10); + + scn.FreepsPassCurrentPhaseAction(); + + scn.ShadowPlayCard(blacksails1); + scn.ShadowAcceptOptionalTrigger(); + scn.ShadowPlayCard(blacksails2); + scn.ShadowDeclineOptionalTrigger(); + + assertEquals(1, scn.GetCultureTokensOn(blacksails1)); + assertEquals(0, scn.GetCultureTokensOn(blacksails2)); + assertEquals(Zone.SUPPORT, blacksails1.getZone()); + assertEquals(Zone.SUPPORT, blacksails2.getZone()); + assertEquals(Zone.SUPPORT, cart.getZone()); + + scn.ShadowPlayCard(marauder); + + scn.ShadowAcceptOptionalTrigger(); + assertTrue(scn.ShadowDecisionAvailable("Choose cards to discard")); + assertEquals(2, scn.GetShadowCardChoiceCount()); //2x Black Sails, no gandalf's cart + + scn.ShadowChooseCard(blacksails2); + + assertEquals(3, scn.GetCultureTokensOn(blacksails1)); // Only valid choice + assertEquals(Zone.SUPPORT, blacksails1.getZone()); + assertEquals(Zone.DISCARD, blacksails2.getZone()); + assertEquals(Zone.SUPPORT, cart.getZone()); + } + + +} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v01/Card_V1_052_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v01/Card_V1_052_Tests.java index 0076cf268..d9eae63f0 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v01/Card_V1_052_Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v01/Card_V1_052_Tests.java @@ -42,7 +42,7 @@ public class Card_V1_052_Tests * Strength: 3 * Vitality: 4 * Signet: Frodo - * Game Text: Assignment: Exert Merry twice to prevent a minion from being assigned to a skirmish until the regroup phase. The Shadow player may exhaust that minion to prevent this. + * Game Text: Assignment: Exert Merry 3 times to prevent a minion from being assigned to a skirmish until the regroup phase. The Shadow player may exhaust that minion to prevent this. */ //Pre-game setup @@ -66,7 +66,7 @@ public class Card_V1_052_Tests } @Test - public void MerryExertsTwiceToPreventMinionSkirmishing() throws DecisionResultInvalidException, CardNotFoundException { + public void MerryExertsThriceToPreventMinionSkirmishing() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); @@ -84,7 +84,7 @@ public class Card_V1_052_Tests assertTrue(scn.FreepsCardActionAvailable(merry)); scn.FreepsUseCardAction(merry); - assertEquals(2, scn.GetWoundsOn(merry)); + assertEquals(3, scn.GetWoundsOn(merry)); scn.ShadowChooseNo(); scn.ShadowPassCurrentPhaseAction(); scn.FreepsPassCurrentPhaseAction(); @@ -113,7 +113,7 @@ public class Card_V1_052_Tests assertTrue(scn.FreepsCardActionAvailable(merry)); scn.FreepsUseCardAction(merry); - assertEquals(2, scn.GetWoundsOn(merry)); + assertEquals(3, scn.GetWoundsOn(merry)); assertTrue(scn.ShadowDecisionAvailable("Would you like to exhaust")); scn.ShadowChooseYes(); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v01/Card_V1_064_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v01/Card_V1_064_Tests.java index 8d295e04a..6720c0a6b 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v01/Card_V1_064_Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v01/Card_V1_064_Tests.java @@ -22,8 +22,10 @@ public class Card_V1_064_Tests return new GenericCardTestHelper( new HashMap<>() {{ put("greenleaf", "1_50"); - put("savage", "1_151"); - put("lord", "4_219"); + put("moriatroop1", "1_177"); + put("moriatroop2", "1_177"); + put("moriatroop3", "1_177"); + put("shelob", "8_26"); }}, new HashMap<>() {{ put("site1", "1_319"); @@ -53,7 +55,7 @@ public class Card_V1_064_Tests * Type: site * Subtype: * Site Number: 9 - * Game Text: Forest. Exhausted minions cannot take wounds. + * Game Text: Forest. Each minion is damage +1 per wound on that minion. */ //Pre-game setup @@ -77,16 +79,15 @@ public class Card_V1_064_Tests } @Test - public void WoundedMinionsTakeNoWoundsAndWoundedCompsCannotExertFromFPCards() throws DecisionResultInvalidException, CardNotFoundException { + public void WoundedMinionsAreDamagePlusOnePerWound() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); - PhysicalCardImpl greenleaf = scn.GetFreepsCard("greenleaf"); - scn.FreepsMoveCharToTable(greenleaf); - - PhysicalCardImpl savage = scn.GetShadowCard("savage"); - PhysicalCardImpl lord = scn.GetShadowCard("lord"); - scn.ShadowMoveCardToHand(savage, lord); + 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)); @@ -135,36 +136,31 @@ public class Card_V1_064_Tests scn.ShadowDeclineReconciliation(); scn.FreepsChooseToMove(); - scn.ShadowMoveCharToTable(savage, lord); + scn.ShadowMoveCharToTable(moriatroop1, moriatroop2, moriatroop3, shelob); + scn.SkipToPhase(Phase.MANEUVER); + + assertFalse(scn.HasKeyword(moriatroop1, Keyword.DAMAGE)); + assertFalse(scn.HasKeyword(moriatroop2, Keyword.DAMAGE)); + assertFalse(scn.HasKeyword(moriatroop3, Keyword.DAMAGE)); + + scn.AddWoundsToChar(moriatroop2, 1); + scn.AddWoundsToChar(moriatroop3, 2); + scn.AddWoundsToChar(shelob, 7); scn.SkipToPhase(Phase.ARCHERY); - assertEquals(0, scn.GetWoundsOn(greenleaf)); - assertEquals(0, scn.GetWoundsOn(savage)); - assertTrue(scn.FreepsCardActionAvailable(greenleaf)); - scn.FreepsUseCardAction(greenleaf); - scn.FreepsChooseCard(savage); + assertEquals(0, scn.GetWoundsOn(moriatroop1)); + assertEquals(1, scn.GetWoundsOn(moriatroop2)); + assertEquals(2, scn.GetWoundsOn(moriatroop3)); + assertEquals(7, scn.GetWoundsOn(shelob)); - assertEquals(1, scn.GetWoundsOn(greenleaf)); - // The Free Peoples player may not exert wounded companions, but Shadow cards may. - scn.ShadowUseCardAction(lord); + assertFalse(scn.HasKeyword(moriatroop1, Keyword.DAMAGE)); + assertTrue(scn.HasKeyword(moriatroop2, Keyword.DAMAGE)); + assertEquals(1, scn.GetKeywordCount(moriatroop2, Keyword.DAMAGE)); + assertTrue(scn.HasKeyword(moriatroop3, Keyword.DAMAGE)); + assertEquals(2, scn.GetKeywordCount(moriatroop3, Keyword.DAMAGE)); + assertTrue(scn.HasKeyword(shelob, Keyword.DAMAGE)); + assertEquals(7, scn.GetKeywordCount(shelob, Keyword.DAMAGE)); - assertFalse(scn.FreepsCardActionAvailable(greenleaf)); - //pass remaining archery actions - scn.PassCurrentPhaseActions(); - //pass assignment actions - scn.PassCurrentPhaseActions(); - - assertEquals(2, scn.GetWoundsOn(greenleaf)); - assertEquals(1, scn.GetWoundsOn(savage)); - - scn.FreepsAssignToMinions(greenleaf, savage); - scn.ShadowPassCurrentPhaseAction(); - scn.FreepsResolveSkirmish(greenleaf); - scn.PassCurrentPhaseActions(); - - //As a wounded minion, the Savage was barred from taking a wound - assertEquals(2, scn.GetWoundsOn(greenleaf)); - assertEquals(1, scn.GetWoundsOn(savage)); } }