Alteration to the CopyCard json functionality
- Added a trigger to CopyCard which automatically unapplies/reapplies the copier when the thing they copy is played - Added unit tests for Hobbit Farmer extensively checking each use case; in particular modifier sites vs ability sites - Various minor formatting fixes in other unit tests - Dare I say it? "These stupid site copy allies are finally fixed."
This commit is contained in:
@@ -2,9 +2,13 @@ package com.gempukku.lotro.cards.build.field;
|
|||||||
|
|
||||||
import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
|
import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
|
||||||
import com.gempukku.lotro.common.Side;
|
import com.gempukku.lotro.common.Side;
|
||||||
|
import org.hjson.JsonValue;
|
||||||
import org.json.simple.JSONArray;
|
import org.json.simple.JSONArray;
|
||||||
import org.json.simple.JSONObject;
|
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;
|
import java.util.Set;
|
||||||
|
|
||||||
public class FieldUtils {
|
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) {
|
private static boolean contains(String[] fields, String key) {
|
||||||
for (String field : fields) {
|
for (String field : fields) {
|
||||||
if (field.equals(key))
|
if (field.equals(key))
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.gempukku.lotro.cards.build.FilterableSource;
|
|||||||
import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
|
import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
|
||||||
import com.gempukku.lotro.cards.build.field.EffectProcessor;
|
import com.gempukku.lotro.cards.build.field.EffectProcessor;
|
||||||
import com.gempukku.lotro.cards.build.field.FieldUtils;
|
import com.gempukku.lotro.cards.build.field.FieldUtils;
|
||||||
|
import com.gempukku.lotro.cards.build.field.effect.trigger.TriggerChecker;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
public class CopyCard implements EffectProcessor {
|
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 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);
|
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
|
||||||
|
|
||||||
blueprint.appendCopiedFilter(filterableSource);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,6 +111,7 @@ public class EffectAppenderFactory {
|
|||||||
effectAppenderProducers.put("putstackedcardsintohand", new PutStackedCardsIntoHand());
|
effectAppenderProducers.put("putstackedcardsintohand", new PutStackedCardsIntoHand());
|
||||||
effectAppenderProducers.put("reconcilehand", new ReconcileHand());
|
effectAppenderProducers.put("reconcilehand", new ReconcileHand());
|
||||||
effectAppenderProducers.put("reducearcherytotal", new ReduceArcheryTotal());
|
effectAppenderProducers.put("reducearcherytotal", new ReduceArcheryTotal());
|
||||||
|
effectAppenderProducers.put("refreshself", new RefreshSelf());
|
||||||
effectAppenderProducers.put("reinforcetokens", new ReinforceTokens());
|
effectAppenderProducers.put("reinforcetokens", new ReinforceTokens());
|
||||||
effectAppenderProducers.put("removeburdens", new RemoveBurdens());
|
effectAppenderProducers.put("removeburdens", new RemoveBurdens());
|
||||||
effectAppenderProducers.put("removecardsindiscardfromgame", new RemoveCardsInDiscardFromGame());
|
effectAppenderProducers.put("removecardsindiscardfromgame", new RemoveCardsInDiscardFromGame());
|
||||||
|
|||||||
@@ -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());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -637,6 +637,16 @@ public class GenericCardTestHelper extends AbstractAtTest {
|
|||||||
SkipToPhase(Phase.ASSIGNMENT);
|
SkipToPhase(Phase.ASSIGNMENT);
|
||||||
PassCurrentPhaseActions();
|
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 {
|
public void SkipToPhase(Phase target) throws DecisionResultInvalidException {
|
||||||
for(int attempts = 1; attempts <= 20; attempts++)
|
for(int attempts = 1; attempts <= 20; attempts++)
|
||||||
{
|
{
|
||||||
@@ -1040,7 +1050,7 @@ public class GenericCardTestHelper extends AbstractAtTest {
|
|||||||
{
|
{
|
||||||
ShadowDeclineReconciliation();
|
ShadowDeclineReconciliation();
|
||||||
}
|
}
|
||||||
if(ShadowDecisionAvailable("discard down"))
|
while(ShadowDecisionAvailable("discard down"))
|
||||||
{
|
{
|
||||||
ShadowChooseCard((PhysicalCardImpl) GetShadowHand().get(0));
|
ShadowChooseCard((PhysicalCardImpl) GetShadowHand().get(0));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package com.gempukku.lotro.cards.official.set01;
|
package com.gempukku.lotro.cards.official.set01;
|
||||||
|
|
||||||
import com.gempukku.lotro.cards.GenericCardTestHelper;
|
import com.gempukku.lotro.cards.GenericCardTestHelper;
|
||||||
import com.gempukku.lotro.common.Phase;
|
import com.gempukku.lotro.common.*;
|
||||||
import com.gempukku.lotro.common.SitesBlock;
|
|
||||||
import com.gempukku.lotro.game.CardNotFoundException;
|
import com.gempukku.lotro.game.CardNotFoundException;
|
||||||
import com.gempukku.lotro.game.PhysicalCardImpl;
|
import com.gempukku.lotro.game.PhysicalCardImpl;
|
||||||
import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
|
import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
|
||||||
@@ -72,6 +71,10 @@ public class Card_01_040_Tests
|
|||||||
PhysicalCardImpl elrond = scn.GetFreepsCard("elrond");
|
PhysicalCardImpl elrond = scn.GetFreepsCard("elrond");
|
||||||
|
|
||||||
assertTrue(elrond.getBlueprint().isUnique());
|
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(4, elrond.getBlueprint().getTwilightCost());
|
||||||
assertEquals(8, elrond.getBlueprint().getStrength());
|
assertEquals(8, elrond.getBlueprint().getStrength());
|
||||||
assertEquals(4, elrond.getBlueprint().getVitality());
|
assertEquals(4, elrond.getBlueprint().getVitality());
|
||||||
|
|||||||
@@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ public class Card_03_068_ErrataTests
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void SarumanStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
|
public void SarumanStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,7 +60,7 @@ public class Card_03_068_ErrataTests
|
|||||||
assertEquals(4, saruman.getBlueprint().getTwilightCost());
|
assertEquals(4, saruman.getBlueprint().getTwilightCost());
|
||||||
assertEquals(8, saruman.getBlueprint().getStrength());
|
assertEquals(8, saruman.getBlueprint().getStrength());
|
||||||
assertEquals(4, saruman.getBlueprint().getVitality());
|
assertEquals(4, saruman.getBlueprint().getVitality());
|
||||||
assertEquals(4, saruman.getBlueprint().getSiteNumber()); // Change this to getAllyHomeSiteNumbers for allies
|
assertEquals(4, saruman.getBlueprint().getSiteNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ public class Card_03_090_ErrataTests
|
|||||||
* Twilight Cost: 0
|
* Twilight Cost: 0
|
||||||
* Type: event
|
* Type: event
|
||||||
* Subtype: Maneuver
|
* 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
|
//Pre-game setup
|
||||||
|
|||||||
@@ -65,7 +65,9 @@ public class Card_03_103_ErrataTests
|
|||||||
* Twilight Cost: 0
|
* Twilight Cost: 0
|
||||||
* Type: event
|
* Type: event
|
||||||
* Subtype:
|
* Subtype:
|
||||||
* Game Text: <b>Maneuver:</b> 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: <b>Maneuver:</b> 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
|
//Pre-game setup
|
||||||
|
|||||||
Reference in New Issue
Block a user