diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/errata/set15/set15-Gondor-errata-playtest.hjson b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/errata/set15/set15-Gondor-errata-playtest.hjson
index 885a41ab0..44bdb1be4 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/errata/set15/set15-Gondor-errata-playtest.hjson
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/errata/set15/set15-Gondor-errata-playtest.hjson
@@ -50,7 +50,6 @@
}
{
type: trigger
- optional: true
trigger: {
type: startOfPhase
phase: maneuver
@@ -59,11 +58,20 @@
type: canSpotThreats
}
effect: {
- type: modifySiteNumber
- filter: all(minion)
- amount: 1
- until: start(regroup)
+ type: repeat
+ amount: {
+ type: forEachThreat
+ }
+ effect: {
+ type: modifySiteNumber
+ filter: choose(minion)
+ count: 1
+ amount: 1
+ until: start(regroup)
+ }
}
+
+
}
]
gametext: Ranger. Hunter 1.
While you can spot 2 [gondor] rangers, Madril is twilight cost –2.
At the start of the Maneuver phase, for each threat you can spot, make a minion's site number +1 until the start of the regroup phase.
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 f12ec9cf6..917fe113f 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
@@ -531,6 +531,19 @@ public class GenericCardTestHelper extends AbstractAtTest {
_game.getGameState().addTokens(card, Token.findTokenForCulture(card.getBlueprint().getCulture()), count);
}
+
+ public void AddThreats(int count) {
+ _game.getGameState().addThreats(_game.getGameState().getCurrentPlayerId(), count);
+ }
+
+ public void RemoveThreats(int count) {
+ _game.getGameState().removeThreats(_game.getGameState().getCurrentPlayerId(), count);
+ }
+
+ public int GetThreats() {
+ return _game.getGameState().getThreats();
+ }
+
public void FreepsRemoveWoundsFromChar(String cardName, int count) { RemoveWoundsFromChar(GetFreepsCard(cardName), count); }
public void ShadowRemoveWoundsFromChar(String cardName, int count) { RemoveWoundsFromChar(GetShadowCard(cardName), count); }
public void RemoveWoundsFromChar(PhysicalCardImpl card, int count) {
@@ -592,6 +605,8 @@ public class GenericCardTestHelper extends AbstractAtTest {
}
}
+ public void FreepsDeclineAssignments() throws DecisionResultInvalidException { FreepsPassCurrentPhaseAction(); }
+ public void ShadowDeclineAssignments() throws DecisionResultInvalidException { ShadowPassCurrentPhaseAction(); }
public void FreepsAssignToMinions(PhysicalCardImpl comp, PhysicalCardImpl...minions) throws DecisionResultInvalidException { AssignToMinions(P1, comp, minions); }
public void ShadowAssignToMinions(PhysicalCardImpl comp, PhysicalCardImpl...minions) throws DecisionResultInvalidException { AssignToMinions(P2, comp, minions); }
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set15/Card_15_064_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set15/Card_15_064_Tests.java
new file mode 100644
index 000000000..e0a8683f9
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set15/Card_15_064_Tests.java
@@ -0,0 +1,187 @@
+package com.gempukku.lotro.cards.official.set15;
+
+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.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class Card_15_064_Tests
+{
+
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("madril", "15_64");
+ put("arwen", "1_30");
+ put("ranger1", "7_116");
+ put("ranger2", "7_116");
+
+ put("runner1", "1_178");
+ put("runner2", "1_178");
+ put("runner3", "1_178");
+ }},
+ GenericCardTestHelper.FellowshipSites,
+ GenericCardTestHelper.FOTRFrodo,
+ GenericCardTestHelper.FOTRRing
+ );
+ }
+
+ @Test
+ public void MadrilStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 15
+ * Title: *Madril, Defender of Osgiliath
+ * Side: Free Peoples
+ * Culture: Gondor
+ * Twilight Cost: 2
+ * Type: companion
+ * Subtype: Man
+ * Strength: 5
+ * Vitality: 3
+ * Resistance: 6
+ * Game Text: Ranger. Hunter 1.
+ * While you can spot 2 [gondor] rangers, Madril is twilight cost -2.
+ * At the start of the maneuver phase, each minion is site number +1 for each threat you can spot until the start of the regroup phase.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl madril = scn.GetFreepsCard("madril");
+
+ assertTrue(madril.getBlueprint().isUnique());
+ assertEquals(Side.FREE_PEOPLE, madril.getBlueprint().getSide());
+ assertEquals(Culture.GONDOR, madril.getBlueprint().getCulture());
+ assertEquals(CardType.COMPANION, madril.getBlueprint().getCardType());
+ assertEquals(Race.MAN, madril.getBlueprint().getRace());
+ assertTrue(scn.HasKeyword(madril, Keyword.RANGER));
+ assertTrue(scn.HasKeyword(madril, Keyword.HUNTER));
+ assertEquals(1, scn.GetKeywordCount(madril, Keyword.HUNTER));
+ assertEquals(2, madril.getBlueprint().getTwilightCost());
+ assertEquals(5, madril.getBlueprint().getStrength());
+ assertEquals(3, madril.getBlueprint().getVitality());
+ assertEquals(6, madril.getBlueprint().getResistance());
+ //assertEquals(Signet., madril.getBlueprint().getSignet());
+ //assertEquals(, madril.getBlueprint().getSiteNumber()); // Change this to getAllyHomeSiteNumbers for allies
+
+ }
+
+ @Test
+ public void MadrilCosts2LessWith2GondorRangers() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ var madril = scn.GetFreepsCard("madril");
+ var arwen = scn.GetFreepsCard("arwen");
+ var ranger1 = scn.GetFreepsCard("ranger1");
+ var ranger2 = scn.GetFreepsCard("ranger2");
+ scn.FreepsMoveCardToHand(madril, arwen, ranger1, ranger2);
+
+ scn.StartGame();
+
+ assertEquals(0, scn.GetTwilight());
+ scn.FreepsPlayCard(madril);
+ assertEquals(2, scn.GetTwilight());
+
+ scn.FreepsMoveCardToHand(madril);
+ scn.SetTwilight(0);
+ scn.FreepsPlayCard(arwen);
+ assertEquals(2, scn.GetTwilight());
+ scn.FreepsPlayCard(madril);
+ assertEquals(4, scn.GetTwilight()); // no discount from arwen
+
+ scn.FreepsMoveCardToHand(madril);
+ scn.SetTwilight(0);
+ scn.FreepsPlayCard(ranger1);
+ assertEquals(2, scn.GetTwilight());
+ scn.FreepsPlayCard(madril);
+ assertEquals(4, scn.GetTwilight()); // no discount from arwen + gondor ranger
+
+ scn.FreepsMoveCardToHand(madril);
+ scn.SetTwilight(0);
+ scn.FreepsPlayCard(ranger2);
+ assertEquals(2, scn.GetTwilight());
+ scn.FreepsPlayCard(madril);
+ assertEquals(2, scn.GetTwilight()); // discount from 2 gondor rangers
+ }
+
+ @Test
+ public void ManeuverTriggerMakesEachMinionSiteNumberPlusOnePerThreatUntilRegroup() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ var madril = scn.GetFreepsCard("madril");
+ scn.FreepsMoveCharToTable(madril);
+
+ var runner1 = scn.GetShadowCard("runner1");
+ var runner2 = scn.GetShadowCard("runner2");
+ var runner3 = scn.GetShadowCard("runner3");
+ scn.ShadowMoveCharToTable(runner1, runner2, runner3);
+
+ scn.StartGame();
+
+ scn.AddThreats(5);
+
+ assertEquals(4, scn.GetMinionSiteNumber(runner1));
+ assertEquals(4, scn.GetMinionSiteNumber(runner2));
+ assertEquals(4, scn.GetMinionSiteNumber(runner3));
+
+
+ scn.SkipToPhase(Phase.MANEUVER);
+ assertEquals(5, scn.GetThreats());
+
+ assertEquals(9, scn.GetMinionSiteNumber(runner1));
+ assertEquals(9, scn.GetMinionSiteNumber(runner2));
+ assertEquals(9, scn.GetMinionSiteNumber(runner3));
+
+ scn.SkipToPhase(Phase.ASSIGNMENT);
+
+ assertEquals(9, scn.GetMinionSiteNumber(runner1));
+ assertEquals(9, scn.GetMinionSiteNumber(runner2));
+ assertEquals(9, scn.GetMinionSiteNumber(runner3));
+
+ scn.PassCurrentPhaseActions();
+ scn.FreepsDeclineAssignments();
+ scn.ShadowDeclineAssignments();
+
+ assertEquals(4, scn.GetMinionSiteNumber(runner1));
+ assertEquals(4, scn.GetMinionSiteNumber(runner2));
+ assertEquals(4, scn.GetMinionSiteNumber(runner3));
+ }
+
+ @Test
+ public void ManeuverAbilityDoesNothingWithZeroThreats() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ var madril = scn.GetFreepsCard("madril");
+ scn.FreepsMoveCardToHand(madril);
+
+ var runner1 = scn.GetShadowCard("runner1");
+ var runner2 = scn.GetShadowCard("runner2");
+ var runner3 = scn.GetShadowCard("runner3");
+ scn.ShadowMoveCharToTable(runner1, runner2, runner3);
+
+ scn.StartGame();
+
+ assertEquals(4, scn.GetMinionSiteNumber(runner1));
+ assertEquals(4, scn.GetMinionSiteNumber(runner2));
+ assertEquals(4, scn.GetMinionSiteNumber(runner3));
+
+ scn.SkipToPhase(Phase.MANEUVER);
+ assertTrue(scn.FreepsDecisionAvailable("Play Maneuver action or Pass"));
+
+ assertEquals(4, scn.GetMinionSiteNumber(runner1));
+ assertEquals(4, scn.GetMinionSiteNumber(runner2));
+ assertEquals(4, scn.GetMinionSiteNumber(runner3));
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set15/Card_15_064_ErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set15/Card_15_064_ErrataTests.java
index 4c12585d2..bea5e4cb8 100644
--- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set15/Card_15_064_ErrataTests.java
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set15/Card_15_064_ErrataTests.java
@@ -21,8 +21,14 @@ public class Card_15_064_ErrataTests
return new GenericCardTestHelper(
new HashMap()
{{
- put("card", "85_64");
- // put other cards in here as needed for the test case
+ put("madril", "85_64");
+ put("arwen", "1_30");
+ put("ranger1", "7_116");
+ put("ranger2", "7_116");
+
+ put("runner1", "1_178");
+ put("runner2", "1_178");
+ put("runner3", "1_178");
}},
GenericCardTestHelper.FellowshipSites,
GenericCardTestHelper.FOTRFrodo,
@@ -30,9 +36,7 @@ public class Card_15_064_ErrataTests
);
}
- // Uncomment both @Test markers below once this is ready to be used
-
- //@Test
+ @Test
public void MadrilStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
/**
@@ -54,34 +58,130 @@ public class Card_15_064_ErrataTests
//Pre-game setup
GenericCardTestHelper scn = GetScenario();
- PhysicalCardImpl card = scn.GetFreepsCard("card");
+ PhysicalCardImpl madril = scn.GetFreepsCard("madril");
- assertTrue(card.getBlueprint().isUnique());
- assertEquals(Side.FREE_PEOPLE, card.getBlueprint().getSide());
- assertEquals(Culture.GONDOR, card.getBlueprint().getCulture());
- assertEquals(CardType.COMPANION, card.getBlueprint().getCardType());
- assertEquals(Race.CREATURE, card.getBlueprint().getRace());
- assertTrue(scn.HasKeyword(card, Keyword.SUPPORT_AREA));
- assertEquals(2, card.getBlueprint().getTwilightCost());
- assertEquals(5, card.getBlueprint().getStrength());
- assertEquals(3, card.getBlueprint().getVitality());
- assertEquals(6, card.getBlueprint().getResistance());
- //assertEquals(Signet., card.getBlueprint().getSignet());
- //assertEquals(, card.getBlueprint().getSiteNumber()); // Change this to getAllyHomeSiteNumbers for allies
+ assertTrue(madril.getBlueprint().isUnique());
+ assertEquals(Side.FREE_PEOPLE, madril.getBlueprint().getSide());
+ assertEquals(Culture.GONDOR, madril.getBlueprint().getCulture());
+ assertEquals(CardType.COMPANION, madril.getBlueprint().getCardType());
+ assertEquals(Race.MAN, madril.getBlueprint().getRace());
+ assertTrue(scn.HasKeyword(madril, Keyword.RANGER));
+ assertTrue(scn.HasKeyword(madril, Keyword.HUNTER));
+ assertEquals(1, scn.GetKeywordCount(madril, Keyword.HUNTER));
+ assertEquals(2, madril.getBlueprint().getTwilightCost());
+ assertEquals(5, madril.getBlueprint().getStrength());
+ assertEquals(3, madril.getBlueprint().getVitality());
+ assertEquals(6, madril.getBlueprint().getResistance());
+ //assertEquals(Signet., madril.getBlueprint().getSignet());
+ //assertEquals(, madril.getBlueprint().getSiteNumber()); // Change this to getAllyHomeSiteNumbers for allies
}
- //@Test
- public void MadrilTest1() throws DecisionResultInvalidException, CardNotFoundException {
+ @Test
+ public void MadrilCosts2LessWith2GondorRangers() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
GenericCardTestHelper scn = GetScenario();
- PhysicalCardImpl card = scn.GetFreepsCard("card");
- scn.FreepsMoveCardToHand(card);
+ var madril = scn.GetFreepsCard("madril");
+ var arwen = scn.GetFreepsCard("arwen");
+ var ranger1 = scn.GetFreepsCard("ranger1");
+ var ranger2 = scn.GetFreepsCard("ranger2");
+ scn.FreepsMoveCardToHand(madril, arwen, ranger1, ranger2);
scn.StartGame();
- scn.FreepsPlayCard(card);
+ assertEquals(0, scn.GetTwilight());
+ scn.FreepsPlayCard(madril);
assertEquals(2, scn.GetTwilight());
+
+ scn.FreepsMoveCardToHand(madril);
+ scn.SetTwilight(0);
+ scn.FreepsPlayCard(arwen);
+ assertEquals(2, scn.GetTwilight());
+ scn.FreepsPlayCard(madril);
+ assertEquals(4, scn.GetTwilight()); // no discount from arwen
+
+ scn.FreepsMoveCardToHand(madril);
+ scn.SetTwilight(0);
+ scn.FreepsPlayCard(ranger1);
+ assertEquals(2, scn.GetTwilight());
+ scn.FreepsPlayCard(madril);
+ assertEquals(4, scn.GetTwilight()); // no discount from arwen + gondor ranger
+
+ scn.FreepsMoveCardToHand(madril);
+ scn.SetTwilight(0);
+ scn.FreepsPlayCard(ranger2);
+ assertEquals(2, scn.GetTwilight());
+ scn.FreepsPlayCard(madril);
+ assertEquals(2, scn.GetTwilight()); // discount from 2 gondor rangers
+ }
+
+ @Test
+ public void ManeuverAbilityAllowsDistributionOfSiteNumberIncreases() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ var madril = scn.GetFreepsCard("madril");
+ scn.FreepsMoveCharToTable(madril);
+
+ var runner1 = scn.GetShadowCard("runner1");
+ var runner2 = scn.GetShadowCard("runner2");
+ var runner3 = scn.GetShadowCard("runner3");
+ scn.ShadowMoveCharToTable(runner1, runner2, runner3);
+
+ scn.StartGame();
+
+ scn.AddThreats(5);
+
+ assertEquals(4, scn.GetMinionSiteNumber(runner1));
+ assertEquals(4, scn.GetMinionSiteNumber(runner2));
+ assertEquals(4, scn.GetMinionSiteNumber(runner3));
+
+
+ scn.SkipToPhase(Phase.MANEUVER);
+ assertEquals(5, scn.GetThreats());
+
+ scn.FreepsChooseCard(runner1);
+ scn.FreepsChooseCard(runner1);
+ scn.FreepsChooseCard(runner1);
+ scn.FreepsChooseCard(runner2);
+ scn.FreepsChooseCard(runner2);
+
+ assertEquals(7, scn.GetMinionSiteNumber(runner1));
+ assertEquals(6, scn.GetMinionSiteNumber(runner2));
+ assertEquals(4, scn.GetMinionSiteNumber(runner3));
+
+ scn.SkipToPhase(Phase.ASSIGNMENT);
+
+ assertEquals(7, scn.GetMinionSiteNumber(runner1));
+ assertEquals(6, scn.GetMinionSiteNumber(runner2));
+ assertEquals(4, scn.GetMinionSiteNumber(runner3));
+
+ scn.PassCurrentPhaseActions();
+ scn.FreepsDeclineAssignments();
+ scn.ShadowDeclineAssignments();
+
+ assertEquals(4, scn.GetMinionSiteNumber(runner1));
+ assertEquals(4, scn.GetMinionSiteNumber(runner2));
+ assertEquals(4, scn.GetMinionSiteNumber(runner3));
+ }
+
+ @Test
+ public void ManeuverAbilityDoesNothingWithZeroThreats() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ var madril = scn.GetFreepsCard("madril");
+ scn.FreepsMoveCardToHand(madril);
+
+ var runner1 = scn.GetShadowCard("runner1");
+ var runner2 = scn.GetShadowCard("runner2");
+ var runner3 = scn.GetShadowCard("runner3");
+ scn.ShadowMoveCharToTable(runner1, runner2, runner3);
+
+ scn.StartGame();
+
+ scn.SkipToPhase(Phase.MANEUVER);
+ assertTrue(scn.FreepsDecisionAvailable("Play Maneuver action or Pass"));
}
}