diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/FieldUtils.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/FieldUtils.java
index 65b4dcf42..706ba7dec 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/FieldUtils.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/FieldUtils.java
@@ -2,9 +2,13 @@ package com.gempukku.lotro.cards.build.field;
import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
import com.gempukku.lotro.common.Side;
+import org.hjson.JsonValue;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import java.util.Map;
import java.util.Set;
public class FieldUtils {
@@ -106,6 +110,13 @@ public class FieldUtils {
}
}
+ private static final JSONParser parser = new JSONParser();
+ public static JSONObject parseSubObject(String jsonString) throws ParseException {
+ String json = JsonValue.readHjson(jsonString).toString();
+ var subObject = (JSONObject) parser.parse(json);
+ return subObject;
+ }
+
private static boolean contains(String[] fields, String key) {
for (String field : fields) {
if (field.equals(key))
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/CopyCard.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/CopyCard.java
index 4dc0f6258..ec738dd9a 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/CopyCard.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/CopyCard.java
@@ -6,6 +6,7 @@ import com.gempukku.lotro.cards.build.FilterableSource;
import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
import com.gempukku.lotro.cards.build.field.EffectProcessor;
import com.gempukku.lotro.cards.build.field.FieldUtils;
+import com.gempukku.lotro.cards.build.field.effect.trigger.TriggerChecker;
import org.json.simple.JSONObject;
public class CopyCard implements EffectProcessor {
@@ -15,8 +16,42 @@ public class CopyCard implements EffectProcessor {
final String filter = FieldUtils.getString(value.get("filter"), "filter");
+ final String autoRefreshTriggerString = """
+ {
+ type: trigger
+ trigger: {
+ type: played
+ filter: """ + filter + """
+
+ }
+ effect: {
+ type: RefreshSelf
+ }
+ }
+ """;
+
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
blueprint.appendCopiedFilter(filterableSource);
+
+ //Now we add an automatic trigger that unapplies/reapplies this card so that
+ // modifiers etc do not get stuck.
+
+ try {
+ var action = FieldUtils.parseSubObject(autoRefreshTriggerString);
+ var trigger = (JSONObject) action.get("trigger");
+ final var triggerChecker = environment
+ .getTriggerCheckerFactory().getTriggerChecker(trigger, environment);
+
+ var triggerActionSource = new DefaultActionSource();
+ triggerActionSource.addPlayRequirement(triggerChecker);
+ EffectUtils.processRequirementsCostsAndEffects(action, environment, triggerActionSource);
+
+ blueprint.appendRequiredAfterTrigger(triggerActionSource);
+ }
+ catch(Exception ex) {
+ throw new InvalidCardDefinitionException("CopyCard could not create auto refresh trigger.", ex);
+ }
+
}
}
\ No newline at end of file
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java
index 636c376c9..af4f92d61 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java
@@ -111,6 +111,7 @@ public class EffectAppenderFactory {
effectAppenderProducers.put("putstackedcardsintohand", new PutStackedCardsIntoHand());
effectAppenderProducers.put("reconcilehand", new ReconcileHand());
effectAppenderProducers.put("reducearcherytotal", new ReduceArcheryTotal());
+ effectAppenderProducers.put("refreshself", new RefreshSelf());
effectAppenderProducers.put("reinforcetokens", new ReinforceTokens());
effectAppenderProducers.put("removeburdens", new RemoveBurdens());
effectAppenderProducers.put("removecardsindiscardfromgame", new RemoveCardsInDiscardFromGame());
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RefreshSelf.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RefreshSelf.java
new file mode 100644
index 000000000..d7ab5efa7
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RefreshSelf.java
@@ -0,0 +1,38 @@
+package com.gempukku.lotro.cards.build.field.effect.appender;
+
+import com.gempukku.lotro.cards.build.ActionContext;
+import com.gempukku.lotro.cards.build.CardGenerationEnvironment;
+import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
+import com.gempukku.lotro.cards.build.field.FieldUtils;
+import com.gempukku.lotro.cards.build.field.effect.EffectAppender;
+import com.gempukku.lotro.cards.build.field.effect.EffectAppenderProducer;
+import com.gempukku.lotro.game.state.LotroGame;
+import com.gempukku.lotro.logic.actions.CostToEffectAction;
+import com.gempukku.lotro.logic.effects.PutOnTheOneRingEffect;
+import com.gempukku.lotro.logic.timing.Effect;
+import com.gempukku.lotro.logic.timing.PlayConditions;
+import com.gempukku.lotro.logic.timing.UnrespondableEffect;
+import org.json.simple.JSONObject;
+
+public class RefreshSelf implements EffectAppenderProducer {
+ @Override
+ public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
+ FieldUtils.validateAllowedFields(effectObject);
+
+ //This is intended to be used with cards using CopyCard, such as Hobbit Farmer.
+ // This very well might have side-effects including removing modifiers applied this turn.
+ return new DelayedAppender() {
+ @Override
+ protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext ac) {
+ return new UnrespondableEffect() {
+ @Override
+ protected void doPlayEffect(LotroGame game) {
+ ac.getGame().getGameState().reapplyAffectingForCard(ac.getGame(), ac.getSource());
+ }
+ };
+ }
+
+ };
+ }
+
+}
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 e1b4020e2..8a2ceefa4 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
@@ -637,6 +637,16 @@ public class GenericCardTestHelper extends AbstractAtTest {
SkipToPhase(Phase.ASSIGNMENT);
PassCurrentPhaseActions();
}
+ public void SkipToMovementDecision() throws DecisionResultInvalidException {
+ SkipToPhase(Phase.REGROUP);
+ PassCurrentPhaseActions();
+ if(ShadowDecisionAvailable("reconcile")) {
+ ShadowDeclineReconciliation();
+ }
+ while(ShadowDecisionAvailable("discard down")) {
+ ShadowChooseCard((PhysicalCardImpl) GetShadowHand().get(0));
+ }
+ }
public void SkipToPhase(Phase target) throws DecisionResultInvalidException {
for(int attempts = 1; attempts <= 20; attempts++)
{
@@ -1040,7 +1050,7 @@ public class GenericCardTestHelper extends AbstractAtTest {
{
ShadowDeclineReconciliation();
}
- if(ShadowDecisionAvailable("discard down"))
+ while(ShadowDecisionAvailable("discard down"))
{
ShadowChooseCard((PhysicalCardImpl) GetShadowHand().get(0));
}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_040_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_040_Tests.java
index d8fffa28b..fa2ca472d 100644
--- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_040_Tests.java
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_040_Tests.java
@@ -1,8 +1,7 @@
package com.gempukku.lotro.cards.official.set01;
import com.gempukku.lotro.cards.GenericCardTestHelper;
-import com.gempukku.lotro.common.Phase;
-import com.gempukku.lotro.common.SitesBlock;
+import com.gempukku.lotro.common.*;
import com.gempukku.lotro.game.CardNotFoundException;
import com.gempukku.lotro.game.PhysicalCardImpl;
import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
@@ -72,6 +71,10 @@ public class Card_01_040_Tests
PhysicalCardImpl elrond = scn.GetFreepsCard("elrond");
assertTrue(elrond.getBlueprint().isUnique());
+ assertEquals(Side.FREE_PEOPLE, elrond.getBlueprint().getSide());
+ assertEquals(Culture.ELVEN, elrond.getBlueprint().getCulture());
+ assertEquals(CardType.ALLY, elrond.getBlueprint().getCardType());
+ assertEquals(Race.ELF, elrond.getBlueprint().getRace());
assertEquals(4, elrond.getBlueprint().getTwilightCost());
assertEquals(8, elrond.getBlueprint().getStrength());
assertEquals(4, elrond.getBlueprint().getVitality());
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_295_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_295_Tests.java
new file mode 100644
index 000000000..a45e60165
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_295_Tests.java
@@ -0,0 +1,347 @@
+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 static org.junit.Assert.*;
+
+public class Card_01_295_Tests
+{
+
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap<>()
+ {{
+ put("farmer", "1_295");
+ put("farmer2", "1_295");
+ put("merry", "4_310");
+ put("pippin", "4_314");
+
+ }},
+ new HashMap<>() {{
+ put("site1", "1_321");
+ put("site2", "1_327");
+ put("site3", "1_337");
+ put("site4", "1_343");
+ put("site5", "1_349");
+ put("site6", "1_350");
+ put("site7", "1_353");
+ put("site8", "1_356");
+ put("site9", "1_360");
+ }},
+ GenericCardTestHelper.FOTRFrodo,
+ GenericCardTestHelper.RulingRing
+ );
+ }
+
+ protected GenericCardTestHelper GetDiscountScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap<>()
+ {{
+ put("farmer", "1_295");
+ put("farmer2", "1_295");
+ put("merry", "4_310");
+ put("pippin", "4_314");
+ put("sam", "1_311");
+ }},
+ new HashMap<>() {{
+ put("site1", "1_323");
+ put("site2", "1_327");
+ put("site3", "1_337");
+ put("site4", "1_343");
+ put("site5", "1_349");
+ put("site6", "1_350");
+ put("site7", "1_353");
+ put("site8", "1_356");
+ put("site9", "1_360");
+ }},
+ GenericCardTestHelper.FOTRFrodo,
+ GenericCardTestHelper.RulingRing
+ );
+ }
+
+ @Test
+ public void FarmerStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 1
+ * Title: Hobbit Farmer
+ * Unique: false
+ * Side: Free Peoples
+ * Culture: Shire
+ * Twilight Cost: 1
+ * Type: Ally
+ * Race: Hobbit
+ * Game Text: While you can spot your site 1, this ally has the game text of that site.
+ * Fellowship: Exert this ally and spot your opponent's site 1 to replace it with your site 1.
+ */
+
+ //Pre-game setup
+ var scn = GetScenario();
+
+ var farmer = scn.GetFreepsCard("farmer");
+
+ assertFalse(farmer.getBlueprint().isUnique());
+ assertEquals(Side.FREE_PEOPLE, farmer.getBlueprint().getSide());
+ assertEquals(Culture.SHIRE, farmer.getBlueprint().getCulture());
+ assertEquals(CardType.ALLY, farmer.getBlueprint().getCardType());
+ assertEquals(Race.HOBBIT, farmer.getBlueprint().getRace());
+ assertEquals(1, farmer.getBlueprint().getTwilightCost());
+ assertEquals(2, farmer.getBlueprint().getStrength());
+ assertEquals(2, farmer.getBlueprint().getVitality());
+ assertEquals(1, farmer.getBlueprint().getAllyHomeSiteNumbers()[0]);
+ assertEquals(SitesBlock.FELLOWSHIP, farmer.getBlueprint().getAllyHomeSiteBlock());
+
+ }
+
+ @Test
+ public void FarmerCopiesAbilitiesOnOwnSite1ButNotOpponentSite1() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ var scn = GetScenario();
+
+ //Player 1 version of the Farmer will test copying one's own site
+ var freepsFarmer = scn.GetFreepsCard("farmer");
+ var merry = scn.GetFreepsCard("merry");
+ var pippin = scn.GetFreepsCard("pippin");
+ scn.FreepsMoveCardToSupportArea(freepsFarmer);
+ scn.AddWoundsToChar(freepsFarmer, 1); // To ensure the exert ability isn't available
+ scn.FreepsMoveCardsToTopOfDeck(merry, pippin);
+
+ //Player 2 version of the Farmer will test copying the enemy site
+ var evilFarmer = scn.GetShadowCard("farmer");
+ var evilMerry = scn.GetShadowCard("merry");
+ var evilPippin = scn.GetShadowCard("pippin");
+ scn.ShadowMoveCardToSupportArea(evilFarmer);
+ scn.AddWoundsToChar(evilFarmer, 1); // To ensure the exert ability isn't available
+
+ scn.StartGame();
+
+ assertTrue(scn.FreepsActionAvailable("Farmer Maggot's Fields"));
+ assertTrue(scn.FreepsActionAvailable("Use Hobbit Farmer"));
+
+ scn.SkipToMovementDecision();
+ scn.ShadowMoveCardsToTopOfDeck(evilMerry, evilPippin);
+ scn.FreepsChooseToStay();
+
+ assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase());
+ assertEquals(1, scn.GetVitality(evilFarmer));
+
+ //Since the site is player 1's, player 2 should not have access to it via Hobbit Farmer, only natively
+ assertTrue(scn.ShadowActionAvailable("Farmer Maggot's Fields"));
+ assertFalse(scn.ShadowActionAvailable("Use Hobbit Farmer"));
+ }
+
+ @Test
+ public void FarmerCopiesModifiersOnOwnSite1ButNotOpponentSite1() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ var scn = GetDiscountScenario();
+
+ //Player 1 version of the Farmer will test copying one's own site
+ var freepsFarmer = scn.GetFreepsCard("farmer");
+ var sam = scn.GetFreepsCard("sam");
+ scn.FreepsMoveCardToSupportArea(freepsFarmer);
+ scn.FreepsMoveCardToHand(sam);
+
+ //Player 2 version of the Farmer will test copying the enemy site
+ var evilFarmer = scn.GetShadowCard("farmer");
+ var evilSam = scn.GetShadowCard("sam");
+ scn.ShadowMoveCardToSupportArea(evilFarmer);
+ scn.ShadowMoveCardToHand(evilSam);
+
+ scn.StartGame();
+
+ assertEquals(2, sam.getBlueprint().getTwilightCost());
+ assertEquals(0, scn.GetTwilight());
+ scn.FreepsPlayCard(sam);
+ //Both the Green Hill Country and Hobbit Farmer should have stacked to make Sam -2.
+ assertEquals(0, scn.GetTwilight());
+
+ scn.SkipToMovementDecision();
+ scn.FreepsChooseToStay();
+
+ assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase());
+
+ //Since the site is player 1's, player 2 should not have access to it via Hobbit Farmer, only natively
+ assertEquals(2, evilSam.getBlueprint().getTwilightCost());
+ assertEquals(0, scn.GetTwilight());
+ scn.ShadowPlayCard(evilSam);
+ assertEquals(1, scn.GetTwilight());
+ }
+
+ @Test
+ public void FarmerAbilityExertsToReplaceOpponentsSite1() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ var scn = GetScenario();
+
+ var opponentSite1 = scn.GetCurrentSite();
+ scn.FreepsMoveCardToSupportArea("farmer");
+
+ //Player 2 version of the Farmer will test replacing
+ var evilFarmer = scn.GetShadowCard("farmer");
+ var evilMerry = scn.GetShadowCard("merry");
+ var evilPippin = scn.GetShadowCard("pippin");
+ var site1 = scn.GetShadowSite("site1");
+
+ scn.ShadowMoveCardToSupportArea(evilFarmer);
+
+ scn.StartGame();
+
+ assertFalse(scn.FreepsDecisionAvailable("Use Hobbit Farmer"));
+
+ scn.SkipToMovementDecision();
+ scn.ShadowMoveCardsToTopOfDeck(evilMerry, evilPippin);
+ scn.FreepsChooseToStay();
+
+ assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase());
+
+ assertSame(opponentSite1, scn.GetCurrentSite());
+ assertEquals(Zone.ADVENTURE_DECK, site1.getZone());
+ assertTrue(scn.ShadowActionAvailable(evilFarmer));
+ assertEquals(2, scn.GetVitality(evilFarmer));
+
+ scn.ShadowUseCardAction(evilFarmer);
+
+ assertSame(site1, scn.GetCurrentSite());
+ assertEquals(Zone.ADVENTURE_DECK, opponentSite1.getZone());
+ assertEquals(1, scn.GetVitality(evilFarmer));
+
+ //Now that we have replaced the site, the Hobbit Farmer should now automatically be copying it.
+ assertTrue(scn.ShadowActionAvailable("Farmer Maggot's Fields"));
+ assertTrue(scn.ShadowActionAvailable("Use Hobbit Farmer"));
+ }
+
+ @Test
+ public void FarmerImmediatelyCopiesAbilitiesAfterReplacingDownThePath() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ var scn = GetScenario();
+
+ var opponentSite1 = scn.GetCurrentSite();
+ scn.FreepsMoveCardToSupportArea("farmer");
+
+ //Player 2 version of the Farmer will test replacing
+ var evilFarmer = scn.GetShadowCard("farmer");
+ var evilMerry = scn.GetShadowCard("merry");
+ var evilPippin = scn.GetShadowCard("pippin");
+ var site1 = scn.GetShadowSite("site1");
+
+ scn.ShadowMoveCardToSupportArea(evilFarmer);
+
+ scn.StartGame();
+
+ assertFalse(scn.FreepsDecisionAvailable("Use Hobbit Farmer"));
+
+ //Getting everyone far away from site 1
+ scn.SkipToSite(3);
+
+ scn.SkipToMovementDecision();
+ scn.ShadowMoveCardsToTopOfDeck(evilMerry, evilPippin);
+ scn.FreepsChooseToStay();
+ scn.FreepsDeclineReconciliation();
+
+ assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase());
+
+ assertEquals(Zone.ADVENTURE_PATH, opponentSite1.getZone());
+ assertEquals(Zone.ADVENTURE_DECK, site1.getZone());
+ assertTrue(scn.ShadowActionAvailable(evilFarmer));
+ assertEquals(2, scn.GetVitality(evilFarmer));
+
+ scn.ShadowUseCardAction(evilFarmer);
+
+ assertEquals(Zone.ADVENTURE_PATH, site1.getZone());
+ assertEquals(Zone.ADVENTURE_DECK, opponentSite1.getZone());
+ assertEquals(1, scn.GetVitality(evilFarmer));
+
+ //Now that we have replaced the site, the Hobbit Farmer should now automatically be copying it.
+ assertTrue(scn.ShadowActionAvailable("Use Hobbit Farmer"));
+ }
+
+ @Test
+ public void FarmerCopiesModifiersDownThePath() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ var scn = GetDiscountScenario();
+
+ var farmer = scn.GetFreepsCard("farmer");
+ var merry = scn.GetFreepsCard("merry");
+ var pippin = scn.GetFreepsCard("pippin");
+ var site1 = scn.GetCurrentSite();
+ scn.FreepsMoveCardToSupportArea("farmer");
+ scn.FreepsMoveCardToHand(merry, pippin);
+
+ var opponentSite1 = scn.GetShadowSite("site1");
+
+ scn.StartGame();
+
+ //Ensuring Green Hill Country's -1 twilight discount is working natively.
+ assertEquals(1, pippin.getBlueprint().getTwilightCost());
+ assertEquals(0, scn.GetTwilight());
+ scn.FreepsPlayCard(pippin);
+ assertEquals(0, scn.GetTwilight());
+
+ //Getting everyone far away from site 1
+ scn.SkipToSite(3);
+
+ assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase());
+
+ assertEquals(Zone.ADVENTURE_DECK, opponentSite1.getZone());
+ assertEquals(Zone.ADVENTURE_PATH, site1.getZone());
+
+ //We've never replaced the site, but the Hobbit Farmer should still automatically be copying the twilight discount.
+ assertEquals(1, merry.getBlueprint().getTwilightCost());
+ assertEquals(0, scn.GetTwilight());
+ scn.FreepsPlayCard(merry);
+ assertEquals(0, scn.GetTwilight());
+ }
+
+ @Test
+ public void FarmerImmediatelyCopiesModifiersAfterReplacingDownThePath() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ var scn = GetDiscountScenario();
+
+ var opponentSite1 = scn.GetCurrentSite();
+ scn.FreepsMoveCardToSupportArea("farmer");
+
+ //Player 2 version of the Farmer will test replacing
+ var evilFarmer = scn.GetShadowCard("farmer");
+ var evilMerry = scn.GetShadowCard("merry");
+ var site1 = scn.GetShadowSite("site1");
+
+ scn.ShadowMoveCardToSupportArea(evilFarmer);
+
+ scn.StartGame();
+
+ assertFalse(scn.FreepsDecisionAvailable("Use Hobbit Farmer"));
+
+ //Getting everyone far away from site 1
+ scn.SkipToSite(3);
+
+ scn.SkipToMovementDecision();
+ scn.FreepsChooseToStay();
+ scn.FreepsDeclineReconciliation();
+
+ assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase());
+
+ assertEquals(Zone.ADVENTURE_PATH, opponentSite1.getZone());
+ assertEquals(Zone.ADVENTURE_DECK, site1.getZone());
+ assertTrue(scn.ShadowActionAvailable(evilFarmer));
+ assertEquals(2, scn.GetVitality(evilFarmer));
+
+ scn.ShadowUseCardAction(evilFarmer);
+
+ assertEquals(Zone.ADVENTURE_PATH, site1.getZone());
+ assertEquals(Zone.ADVENTURE_DECK, opponentSite1.getZone());
+ assertEquals(1, scn.GetVitality(evilFarmer));
+
+ //Now that we have replaced the site, the Hobbit Farmer should now automatically be copying the twilight discount.
+ assertEquals(1, evilMerry.getBlueprint().getTwilightCost());
+ assertEquals(0, scn.GetTwilight());
+ scn.ShadowPlayCard(evilMerry);
+ assertEquals(0, scn.GetTwilight());
+ }
+
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_068_ErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_068_ErrataTests.java
index 64ed5ac90..15cd143aa 100644
--- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_068_ErrataTests.java
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_068_ErrataTests.java
@@ -27,6 +27,7 @@ public class Card_03_068_ErrataTests
);
}
+ @Test
public void SarumanStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
/**
@@ -59,7 +60,7 @@ public class Card_03_068_ErrataTests
assertEquals(4, saruman.getBlueprint().getTwilightCost());
assertEquals(8, saruman.getBlueprint().getStrength());
assertEquals(4, saruman.getBlueprint().getVitality());
- assertEquals(4, saruman.getBlueprint().getSiteNumber()); // Change this to getAllyHomeSiteNumbers for allies
+ assertEquals(4, saruman.getBlueprint().getSiteNumber());
}
@Test
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_090_ErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_090_ErrataTests.java
index 48088d8d2..4fd7825f8 100644
--- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_090_ErrataTests.java
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_090_ErrataTests.java
@@ -45,7 +45,9 @@ public class Card_03_090_ErrataTests
* Twilight Cost: 0
* Type: event
* Subtype: Maneuver
- * Game Text: Exert a unique [sauron] minion to exert a companion (except the Ring-bearer) and discard a possession attached to that companion. The Free Peoples player may discard 1 hand at random from their hand to prevent this.
+ * Game Text: Exert a unique [sauron] minion to exert a companion (except the Ring-bearer) and
+ * discard a possession attached to that companion. The Free Peoples player may discard 1
+ * card at random from their hand to prevent this.
*/
//Pre-game setup
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_103_ErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_103_ErrataTests.java
index 793e198d6..b59d3a38d 100644
--- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_103_ErrataTests.java
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set03/Card_03_103_ErrataTests.java
@@ -65,7 +65,9 @@ public class Card_03_103_ErrataTests
* Twilight Cost: 0
* Type: event
* Subtype:
- * Game Text: Maneuver: Spot a [sauron] minion to wound Galadriel 3 times. The Free Peoples player may discard 2 Elves to prevent this. If Galadriel is Ring-bound, 2 burdens may be added instead.
+ * Game Text: Maneuver: Spot a [sauron] minion to wound Galadriel 3 times.
+ * The Free Peoples player may discard 2 Elves to prevent this. If Galadriel is
+ * Ring-bound, 2 burdens may be added instead.
*/
//Pre-game setup