From af642546e79c79166b7169086027a90fff940905 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 6 Feb 2021 15:19:09 -0600 Subject: [PATCH] Bill The Pony Errata Added Bill the Pony errata and unit tests. Added the Pony possession class. --- .../src/main/web/cards/set21/set1-errata.json | 52 +++++++ .../src/main/web/js/gemp-022/set21.js | 3 +- .../lotro/common/PossessionClass.java | 7 +- .../lotro/cards/GenericCardTestHelper.java | 35 +++-- .../errata/set2/FlamingBrandErrataTests.java | 2 + .../errata/set3/Aragorn_HttWCErrataTests.java | 2 +- .../errata/set3/BillThePonyErrataTests.java | 137 ++++++++++++++++++ .../errata/set3/HornOfBoromirErrataTests.java | 3 +- 8 files changed, 224 insertions(+), 17 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index bf87e7051..650dac80c 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -669,4 +669,56 @@ }, + + "21_30106": { + "title": "*Bill the Pony", + "culture": "Shire", + "side": "free_people", + "cost": 0, + "type": "possession", + "possession": "Pony", + "target": "name(Sam)", + "effects": [ + { + "type": "trigger", + "trigger": { + "type": "played", + "filter": "self" + }, + "effect": { + "type": "heal", + "filter": "bearer" + } + }, + { + "type": "modifier", + "modifier": { + "type": "addKeyword", + "filter": "bearer", + "keyword": "concealed" + } + }, + { + "type": "trigger", + "trigger": { + "type": "condition", + "condition": [ + { + "type": "location", + "filter": "underground" + }, + { + "type": "canSpot", + "filter": "self,attachedTo(companion)" + } + ] + }, + "effect": { + "type": "discard", + "filter": "self" + } + } + ] + }, + } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js index 5cd3bff43..c25353bdf 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js @@ -62,5 +62,6 @@ var set21 = { '21_3042': 'https://i.lotrtcgpc.net/errata/FOTR/23_42.jpg', '21_3068': 'https://i.lotrtcgpc.net/errata/FOTR/23_68.jpg', '21_20121': 'https://i.lotrtcgpc.net/errata/FOTR/22_121.jpg', - '21_3038': 'https://i.lotrtcgpc.net/errata/FOTR/23_38.jpg' + '21_3038': 'https://i.lotrtcgpc.net/errata/FOTR/23_38.jpg', + '21_30106': 'https://i.lotrtcgpc.net/errata/FOTR/23_106.jpg' } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/PossessionClass.java b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/PossessionClass.java index 39c2da085..265b5bf97 100644 --- a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/PossessionClass.java +++ b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/PossessionClass.java @@ -4,7 +4,12 @@ public enum PossessionClass implements Filterable { HAND_WEAPON("Hand Weapon"), ARMOR("Armor"), HELM("Helm"), MOUNT("Mount"), RANGED_WEAPON("Ranged Weapon"), CLOAK("Cloak"), PIPE("Pipe"), SHIELD("Shield"), BRACERS("Bracers"), STAFF("Staff"), RING("Ring"), BROOCH("Brooch"), GAUNTLETS("Gauntlets"), BOX("Box"), PALANTIR("Palantir"), PHIAL("Phial"), HORN("Horn"), - CLASSLESS("Classless"); + CLASSLESS("Classless"), + + //PC Classes + PONY("Pony") + + ; private String _humanReadable; 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 e114163aa..2cef73d10 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 @@ -369,6 +369,14 @@ public class GenericCardTestHelper extends AbstractAtTest { return assigns.stream().anyMatch(x -> x.getFellowshipCharacter() == card || x.getShadowCharacters().contains(card)); } + public boolean IsAttachedTo(PhysicalCardImpl card, PhysicalCardImpl bearer) { + if(card.getZone() != Zone.ATTACHED) { + return false; + } + + return bearer == card.getAttachedTo(); + } + public int FreepsGetStrength(String name) { return GetStrength(GetFreepsCard(name)); } public int ShadowGetStrength(String name) { return GetStrength(GetShadowCard(name)); } @@ -396,18 +404,21 @@ public class GenericCardTestHelper extends AbstractAtTest { public void ShadowAcceptOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, "0"); } public void ShadowDeclineOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, "1"); } - public void FreepsAcceptMultipleChoiceOption(String option) throws DecisionResultInvalidException { AcceptMultipleChoiceOption(P1, option); } - public void ShadowAcceptMultipleChoiceOption(String option) throws DecisionResultInvalidException { AcceptMultipleChoiceOption(P2, option); } - public void AcceptMultipleChoiceOption(String playerID, String option) throws DecisionResultInvalidException { - List choices = GetADParamAsList(playerID, "results"); - for(String choice : choices){ - if(choice.toLowerCase().contains(option.toLowerCase())) { - playerDecided(playerID, String.valueOf(choices.indexOf(choice))); - return; - } - } - //couldn't find an exact match, so maybe it's a direct index: - playerDecided(playerID, option); + public void FreepsChooseMultipleChoiceOption(String option) throws DecisionResultInvalidException { ChooseMultipleChoiceOption(P1, option); } + public void ShadowChooseMultipleChoiceOption(String option) throws DecisionResultInvalidException { ChooseMultipleChoiceOption(P2, option); } + public void ChooseMultipleChoiceOption(String playerID, String option) throws DecisionResultInvalidException { ChooseAction(playerID, "results", option); } + public void ChooseAction(String playerID, String paramName, String option) throws DecisionResultInvalidException { + List choices = GetADParamAsList(playerID, paramName); + for(String choice : choices){ + if(choice.toLowerCase().contains(option.toLowerCase())) { + playerDecided(playerID, String.valueOf(choices.indexOf(choice))); + return; + } + } + //couldn't find an exact match, so maybe it's a direct index: + playerDecided(playerID, option); } + public void FreepsResolveActionOrder(String option) throws DecisionResultInvalidException { ChooseAction(P1, "actionText", option); } + } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java index bd82de3ce..094deca74 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java @@ -55,6 +55,8 @@ public class FlamingBrandErrataTests //There are 3 companions in play, but only 2 rangers, so we should only see 2 options assertEquals(2, scn.FreepsGetADParamAsList("cardId").size()); + scn.FreepsChooseCard(aragorn); + assertTrue(scn.IsAttachedTo(brand, aragorn)); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java index 75ac86885..4333401af 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java @@ -174,7 +174,7 @@ public class Aragorn_HttWCErrataTests scn.ShadowAcceptOptionalTrigger(); assertEquals(1, scn.GetShadowHandCount()); assertTrue(scn.ShadowDecisionAvailable("Choose action to perform")); - scn.ShadowAcceptMultipleChoiceOption("Reveal a tracker"); + scn.ShadowChooseMultipleChoiceOption("Reveal a tracker"); assertFalse(scn.FreepsAnyDecisionsAvailable()); assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java new file mode 100644 index 000000000..4ee3f1c17 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java @@ -0,0 +1,137 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata.set3; + +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.filters.Filters; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import com.gempukku.lotro.logic.modifiers.KeywordModifier; +import junit.framework.Assert; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class BillThePonyErrataTests +{ + protected GenericCardTestHelper GetSimpleScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("bill", "21_30106"); + put("sam", "1_311"); + }} + ); + } + + @Test + public void BillCanBeBorneBySam() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetSimpleScenario(); + + PhysicalCardImpl bill = scn.GetFreepsCard("bill"); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + + scn.FreepsMoveCardToHand(bill, sam); + + scn.StartGame(); + + + assertFalse(scn.FreepsCardPlayAvailable(bill)); + scn.FreepsPlayCard(sam); + assertTrue(scn.FreepsCardPlayAvailable(bill)); + scn.FreepsPlayCard(bill); + + Assert.assertTrue(scn.IsAttachedTo(bill, sam)); + } + + @Test + public void BillHealsWhenPlayed() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetSimpleScenario(); + + PhysicalCardImpl bill = scn.GetFreepsCard("bill"); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + + scn.FreepsMoveCardToHand(bill, sam); + + scn.StartGame(); + + scn.FreepsPlayCard(sam); + scn.FreepsUseCardAction(sam); + assertEquals(1, scn.GetWoundsOn(sam)); + scn.FreepsPlayCard(bill); + assertEquals(0, scn.GetWoundsOn(sam)); + } + + @Test + public void BillGrantsConcealed() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetSimpleScenario(); + + PhysicalCardImpl bill = scn.GetFreepsCard("bill"); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + + scn.FreepsMoveCardToHand(bill, sam); + + scn.StartGame(); + + scn.FreepsPlayCard(sam); + scn.FreepsPlayCard(bill); + assertTrue(scn.HasKeyword(sam, Keyword.CONCEALED)); + } + + @Test + public void BillDiscardedWhenMovingToUnderground() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetSimpleScenario(); + + PhysicalCardImpl bill = scn.GetFreepsCard("bill"); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + + scn.FreepsMoveCardToHand(bill, sam); + + scn.InsertAdHocModifier(new KeywordModifier(null, Filters.siteNumber(2), Keyword.UNDERGROUND)); + + scn.StartGame(); + + scn.FreepsPlayCard(sam); + scn.FreepsPlayCard(bill); + + scn.FreepsSkipCurrentPhaseAction(); + //Get a timing choice between resolving concealed or discarding bill + scn.FreepsResolveActionOrder("Concealed"); + assertFalse(scn.IsAttachedTo(bill, sam)); + assertEquals(Zone.DISCARD, bill.getZone()); + } + + @Test + public void BillHealsWhenPlayedAtUnderground() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetSimpleScenario(); + + PhysicalCardImpl bill = scn.GetFreepsCard("bill"); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + + scn.FreepsMoveCardToHand(bill, sam); + + scn.InsertAdHocModifier(new KeywordModifier(null, CardType.SITE, Keyword.UNDERGROUND)); + + scn.StartGame(); + + scn.FreepsPlayCard(sam); + scn.FreepsUseCardAction(sam); + assertEquals(1, scn.GetWoundsOn(sam)); + scn.FreepsPlayCard(bill); + assertEquals(0, scn.GetWoundsOn(sam)); + assertFalse(scn.IsAttachedTo(bill, sam)); + assertEquals(Zone.DISCARD, bill.getZone()); + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java index 8a2c0f633..95ad88ffa 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java @@ -72,8 +72,7 @@ public class HornOfBoromirErrataTests assertTrue(scn.FreepsCardPlayAvailable(horn)); scn.FreepsPlayCard(horn); - Assert.assertEquals(Zone.ATTACHED, horn.getZone()); - Assert.assertEquals(boromir, horn.getAttachedTo()); + Assert.assertTrue(scn.IsAttachedTo(horn, boromir)); } @Test