diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_048_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_048_Tests.java index 8e985e975..81cc97b7d 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_048_Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_048_Tests.java @@ -1,10 +1,7 @@ package com.gempukku.lotro.cards.unofficial.pc.vsets.set_v02; import com.gempukku.lotro.cards.GenericCardTestHelper; -import com.gempukku.lotro.common.CardType; -import com.gempukku.lotro.common.Culture; -import com.gempukku.lotro.common.Keyword; -import com.gempukku.lotro.common.Side; +import com.gempukku.lotro.common.*; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; import org.junit.Test; @@ -20,8 +17,16 @@ public class Card_V2_048_Tests return new GenericCardTestHelper( new HashMap<>() {{ - put("card", "102_48"); - // put other cards in here as needed for the test case + put("stronghold", "102_48"); + put("eowyn", "5_122"); //valiant + put("guard", "5_83"); //valiant + put("elite", "4_265"); + put("rider", "4_286"); + + put("sword", "4_272"); + put("helm", "5_89"); + + put("bowman", "2_60"); }}, GenericCardTestHelper.FellowshipSites, GenericCardTestHelper.FOTRFrodo, @@ -47,7 +52,7 @@ public class Card_V2_048_Tests var scn = GetScenario(); - var card = scn.GetFreepsCard("card"); + var card = scn.GetFreepsCard("stronghold"); assertEquals("Stronghold of My Fathers", card.getBlueprint().getTitle()); assertNull(card.getBlueprint().getSubtitle()); @@ -60,18 +65,113 @@ public class Card_V2_048_Tests assertEquals(1, card.getBlueprint().getTwilightCost()); } - // Uncomment any @Test markers below once this is ready to be used - //@Test - public void StrongholdofMyFathersTest1() throws DecisionResultInvalidException, CardNotFoundException { + @Test + public void StrongholdofMyFathersCanSpot3RohanCompanionsToPlay() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup var scn = GetScenario(); - var card = scn.GetFreepsCard("card"); - scn.FreepsMoveCardToHand(card); + var stronghold = scn.GetFreepsCard("stronghold"); + var eowyn = scn.GetFreepsCard("eowyn"); + var elite = scn.GetFreepsCard("elite"); + var rider = scn.GetFreepsCard("rider"); + scn.FreepsMoveCardToHand(stronghold, eowyn, elite, rider); scn.StartGame(); - scn.FreepsPlayCard(card); - assertEquals(1, scn.GetTwilight()); + assertFalse(scn.FreepsPlayAvailable(stronghold)); + scn.FreepsPlayCard(eowyn); + assertFalse(scn.FreepsPlayAvailable(stronghold)); + scn.FreepsPlayCard(elite); + assertFalse(scn.FreepsPlayAvailable(stronghold)); + scn.FreepsPlayCard(rider); + assertTrue(scn.FreepsPlayAvailable(stronghold)); + } + + @Test + public void StrongholdofMyFathersCanSpot2ValiantCompanionsToPlay() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var stronghold = scn.GetFreepsCard("stronghold"); + var eowyn = scn.GetFreepsCard("eowyn"); + var guard = scn.GetFreepsCard("guard"); + scn.FreepsMoveCardToHand(stronghold, eowyn, guard); + + scn.StartGame(); + + assertFalse(scn.FreepsPlayAvailable(stronghold)); + scn.FreepsPlayCard(eowyn); + assertFalse(scn.FreepsPlayAvailable(stronghold)); + scn.FreepsPlayCard(guard); + assertTrue(scn.FreepsPlayAvailable(stronghold)); + } + + @Test + public void StrongholdofMyFathersCanDiscardSelfToPreventWoundToRohanCompanion() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var stronghold = scn.GetFreepsCard("stronghold"); + var eowyn = scn.GetFreepsCard("eowyn"); + scn.FreepsMoveCharToTable(eowyn); + scn.FreepsMoveCardToSupportArea(stronghold); + + var bowman = scn.GetShadowCard("bowman"); + scn.ShadowMoveCharToTable(bowman); + + scn.StartGame(); + + scn.SkipToArcheryWounds(); + + assertEquals(0, scn.GetWoundsOn(eowyn)); + assertEquals(Zone.SUPPORT, stronghold.getZone()); + + scn.FreepsChooseCard(eowyn); + assertTrue(scn.FreepsHasOptionalTriggerAvailable()); + scn.FreepsAcceptOptionalTrigger(); + + assertEquals(0, scn.GetWoundsOn(eowyn)); + assertEquals(Zone.DISCARD, stronghold.getZone()); + } + + @Test + public void StrongholdofMyFathersCanDiscard2OtherRohanPossessionsToPreventWoundToRohanCompanion() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var stronghold = scn.GetFreepsCard("stronghold"); + var eowyn = scn.GetFreepsCard("eowyn"); + var sword = scn.GetFreepsCard("sword"); + var helm = scn.GetFreepsCard("helm"); + scn.FreepsMoveCharToTable(eowyn); + scn.AttachCardsTo(eowyn, sword); + scn.AttachCardsTo(eowyn, helm); + scn.FreepsMoveCardToSupportArea(stronghold); + + var bowman = scn.GetShadowCard("bowman"); + scn.ShadowMoveCharToTable(bowman); + + scn.StartGame(); + + scn.SkipToArcheryWounds(); + + assertEquals(0, scn.GetWoundsOn(eowyn)); + assertEquals(Zone.SUPPORT, stronghold.getZone()); + assertEquals(Zone.ATTACHED, sword.getZone()); + assertEquals(Zone.ATTACHED, helm.getZone()); + + scn.FreepsChooseCard(eowyn); + assertTrue(scn.FreepsHasOptionalTriggerAvailable()); + scn.FreepsAcceptOptionalTrigger(); + + assertTrue(scn.FreepsChoiceAvailable("Discard Stronghold")); + assertTrue(scn.FreepsChoiceAvailable("Discard 2 other")); + + scn.FreepsChoose("Discard 2 other"); + + assertEquals(0, scn.GetWoundsOn(eowyn)); + assertEquals(Zone.SUPPORT, stronghold.getZone()); + assertEquals(Zone.DISCARD, sword.getZone()); + assertEquals(Zone.DISCARD, helm.getZone()); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_049_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_049_Tests.java index 5881af844..c0e5ebd4c 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_049_Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_049_Tests.java @@ -3,7 +3,6 @@ package com.gempukku.lotro.cards.unofficial.pc.vsets.set_v02; 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; @@ -18,8 +17,12 @@ public class Card_V2_049_Tests return new GenericCardTestHelper( new HashMap<>() {{ - put("card", "102_49"); - // put other cards in here as needed for the test case + put("guthwine", "102_49"); + put("eowyn", "5_122"); + put("eomer", "4_267"); + put("condition", "6_97"); + + put("runner", "1_178"); }}, GenericCardTestHelper.FellowshipSites, GenericCardTestHelper.FOTRFrodo, @@ -46,7 +49,7 @@ public class Card_V2_049_Tests var scn = GetScenario(); - var card = scn.GetFreepsCard("card"); + var card = scn.GetFreepsCard("guthwine"); assertEquals("Gúthwinë", card.getBlueprint().getTitle()); assertEquals("Eomer's Blade", card.getBlueprint().getSubtitle()); @@ -59,18 +62,125 @@ public class Card_V2_049_Tests assertEquals(2, card.getBlueprint().getStrength()); } - // Uncomment any @Test markers below once this is ready to be used - //@Test - public void GuthwineTest1() throws DecisionResultInvalidException, CardNotFoundException { + @Test + public void GuthwineCanBeBorneByAnyRohanCompanion() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup var scn = GetScenario(); - var card = scn.GetFreepsCard("card"); - scn.FreepsMoveCardToHand(card); + var guthwine = scn.GetFreepsCard("guthwine"); + var eomer = scn.GetFreepsCard("eomer"); + var eowyn = scn.GetFreepsCard("eowyn"); + scn.FreepsMoveCardToHand(guthwine); + scn.FreepsMoveCharToTable(eomer, eowyn); scn.StartGame(); - scn.FreepsPlayCard(card); + scn.FreepsPlayCard(guthwine); - assertEquals(2, scn.GetTwilight()); + assertTrue(scn.FreepsHasCardChoiceAvailable(eomer)); + assertTrue(scn.FreepsHasCardChoiceAvailable(eowyn)); + + scn.FreepsChooseCard(eowyn); + assertEquals(Zone.ATTACHED, guthwine.getZone()); + assertEquals(eowyn, guthwine.getAttachedTo()); + } + + @Test + public void GuthwineMakesEomerBearerDamagePlus1() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var guthwine = scn.GetFreepsCard("guthwine"); + var eomer = scn.GetFreepsCard("eomer"); + scn.FreepsMoveCardToHand(guthwine); + scn.FreepsMoveCharToTable(eomer); + + scn.StartGame(); + + assertFalse(scn.hasKeyword(eomer, Keyword.DAMAGE)); + + scn.FreepsPlayCard(guthwine); + + assertEquals(Zone.ATTACHED, guthwine.getZone()); + assertEquals(eomer, guthwine.getAttachedTo()); + assertTrue(scn.hasKeyword(eomer, Keyword.DAMAGE)); + assertEquals(1, scn.GetKeywordCount(eomer, Keyword.DAMAGE)); + } + + @Test + public void GuthwineDoesNotMakeNonEomerBearerDamagePlus1() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var guthwine = scn.GetFreepsCard("guthwine"); + var eowyn = scn.GetFreepsCard("eowyn"); + scn.FreepsMoveCardToHand(guthwine); + scn.FreepsMoveCharToTable(eowyn); + + scn.StartGame(); + + assertFalse(scn.hasKeyword(eowyn, Keyword.DAMAGE)); + + scn.FreepsPlayCard(guthwine); + + assertEquals(Zone.ATTACHED, guthwine.getZone()); + assertEquals(eowyn, guthwine.getAttachedTo()); + assertFalse(scn.hasKeyword(eowyn, Keyword.DAMAGE)); + } + + @Test + public void GuthwineReinforcesRohanTokenWhenEomerWinsSkirmish() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var guthwine = scn.GetFreepsCard("guthwine"); + var eomer = scn.GetFreepsCard("eomer"); + var condition = scn.GetFreepsCard("condition"); + scn.FreepsMoveCharToTable(eomer); + scn.AttachCardsTo(eomer, guthwine); + scn.FreepsMoveCardToSupportArea(condition); + scn.AddTokensToCard(condition, 1); + + var runner = scn.GetShadowCard("runner"); + scn.ShadowMoveCharToTable(runner); + + scn.StartGame(); + + scn.SkipToAssignments(); + scn.FreepsAssignAndResolve(eomer, runner); + scn.PassSkirmishActions(); + + assertEquals(1, scn.GetCultureTokensOn(condition)); + assertTrue(scn.FreepsHasOptionalTriggerAvailable()); + scn.FreepsAcceptOptionalTrigger(); + + assertEquals(2, scn.GetCultureTokensOn(condition)); + } + + @Test + public void GuthwineDoesNotReinforceRohanTokenWhenNonEomerWinsSkirmish() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var guthwine = scn.GetFreepsCard("guthwine"); + var eowyn = scn.GetFreepsCard("eowyn"); + var condition = scn.GetFreepsCard("condition"); + scn.FreepsMoveCharToTable(eowyn); + scn.AttachCardsTo(eowyn, guthwine); + scn.FreepsMoveCardToSupportArea(condition); + scn.AddTokensToCard(condition, 1); + + var runner = scn.GetShadowCard("runner"); + scn.ShadowMoveCharToTable(runner); + + scn.StartGame(); + + scn.SkipToAssignments(); + scn.FreepsAssignAndResolve(eowyn, runner); + scn.PassSkirmishActions(); + + assertEquals(1, scn.GetCultureTokensOn(condition)); + assertFalse(scn.FreepsHasOptionalTriggerAvailable()); + + assertEquals(1, scn.GetCultureTokensOn(condition)); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_052_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_052_Tests.java index c37d354f0..2dccd480a 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_052_Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_052_Tests.java @@ -2,11 +2,18 @@ package com.gempukku.lotro.cards.unofficial.pc.vsets.set_v02; import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.*; +import com.gempukku.lotro.game.AbstractActionProxy; import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.actions.RequiredTriggerAction; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import com.gempukku.lotro.logic.effects.WoundCharactersEffect; +import com.gempukku.lotro.logic.timing.Action; import org.junit.Test; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import static org.junit.Assert.*; @@ -19,9 +26,18 @@ public class Card_V2_052_Tests {{ put("ruin", "102_52"); put("eowyn", "13_124"); - put("arrowslits", "5_80"); + put("vhaldir", "102_8"); + put("vgimli", "55_7"); - //NEEDS MORE TESTS + put("arrowslits", "5_80"); + put("possession", "102_48"); + put("maneuver", "7_238"); + put("archery", "18_101"); + put("skirmish", "4_273"); + put("regroup", "12_114"); + + put("runner", "1_178"); + put("sauron", "9_48"); }}, GenericCardTestHelper.FellowshipSites, @@ -60,6 +76,336 @@ public class Card_V2_052_Tests assertEquals(1, card.getBlueprint().getTwilightCost()); } + @Test + public void NowforRuinAddsNoTokenToSelfWhenMinionKilledIf0ValiantCompanions() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var frodo = scn.GetRingBearer(); + var ruin = scn.GetFreepsCard("ruin"); + scn.FreepsMoveCardToSupportArea(ruin); + + var runner = scn.GetShadowCard("runner"); + scn.ShadowMoveCharToTable(runner); + + //Cheating and adding an all-phases action on frodo to wound the Goblin Runner directly + scn.ApplyAdHocAction(new AbstractActionProxy() { + @Override + public List getPhaseActions(String playerId, LotroGame game) { + RequiredTriggerAction action = new RequiredTriggerAction(frodo); + action.appendEffect(new WoundCharactersEffect(frodo, runner)); + action.setText("Wound Runner"); + return Collections.singletonList(action); + } + }); + + scn.StartGame(); + + assertEquals(Zone.SHADOW_CHARACTERS, runner.getZone()); + assertEquals(0, scn.GetCultureTokensOn(ruin)); + scn.FreepsUseCardAction(frodo); + + assertEquals(Zone.DISCARD, runner.getZone()); + assertEquals(0, scn.GetCultureTokensOn(ruin)); + } + + @Test + public void NowforRuinAddsNoTokenToSelfWhenMinionKilledIf1ValiantCompanion() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var frodo = scn.GetRingBearer(); + var ruin = scn.GetFreepsCard("ruin"); + scn.FreepsMoveCardToSupportArea(ruin); + scn.FreepsMoveCharToTable("vhaldir"); + + var runner = scn.GetShadowCard("runner"); + scn.ShadowMoveCharToTable(runner); + + //Cheating and adding an all-phases action on frodo to wound the Goblin Runner directly + scn.ApplyAdHocAction(new AbstractActionProxy() { + @Override + public List getPhaseActions(String playerId, LotroGame game) { + RequiredTriggerAction action = new RequiredTriggerAction(frodo); + action.appendEffect(new WoundCharactersEffect(frodo, runner)); + action.setText("Wound Runner"); + return Collections.singletonList(action); + } + }); + + scn.StartGame(); + + assertEquals(Zone.SHADOW_CHARACTERS, runner.getZone()); + assertEquals(0, scn.GetCultureTokensOn(ruin)); + scn.FreepsUseCardAction(frodo); + + assertEquals(Zone.DISCARD, runner.getZone()); + assertEquals(0, scn.GetCultureTokensOn(ruin)); + } + + @Test + public void NowforRuinAdds1TokenToSelfWhenMinionKilledIf2ValiantCompanions() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var frodo = scn.GetRingBearer(); + var ruin = scn.GetFreepsCard("ruin"); + scn.FreepsMoveCardToSupportArea(ruin); + scn.FreepsMoveCharToTable("vhaldir", "vgimli"); + + var runner = scn.GetShadowCard("runner"); + scn.ShadowMoveCharToTable(runner); + + //Cheating and adding an all-phases action on frodo to wound the Goblin Runner directly + scn.ApplyAdHocAction(new AbstractActionProxy() { + @Override + public List getPhaseActions(String playerId, LotroGame game) { + RequiredTriggerAction action = new RequiredTriggerAction(frodo); + action.appendEffect(new WoundCharactersEffect(frodo, runner)); + action.setText("Wound Runner"); + return Collections.singletonList(action); + } + }); + + scn.StartGame(); + + assertEquals(Zone.SHADOW_CHARACTERS, runner.getZone()); + assertEquals(0, scn.GetCultureTokensOn(ruin)); + scn.FreepsUseCardAction(frodo); + + assertEquals(Zone.DISCARD, runner.getZone()); + assertEquals(1, scn.GetCultureTokensOn(ruin)); + } + + + @Test + public void NowforRuinPermitsPlayOfEitherRohanConditionOrManeuverEventAndShadowMinion() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var frodo = scn.GetRingBearer(); + var ruin = scn.GetFreepsCard("ruin"); + var arrowslits = scn.GetFreepsCard("arrowslits"); + var maneuver = scn.GetFreepsCard("maneuver"); + scn.FreepsMoveCardToSupportArea(ruin); + scn.FreepsMoveCharToTable("vhaldir", "vgimli"); + scn.FreepsMoveCardToDiscard(arrowslits, maneuver); + + scn.AddTokensToCard(ruin, 2); + + var runner = scn.GetShadowCard("runner"); + var sauron = scn.GetShadowCard("sauron"); + scn.ShadowMoveCharToTable(runner); + scn.ShadowMoveCardToDiscard(sauron); + + //Cheating and adding an all-phases action on frodo to wound the Goblin Runner directly + scn.ApplyAdHocAction(new AbstractActionProxy() { + @Override + public List getPhaseActions(String playerId, LotroGame game) { + RequiredTriggerAction action = new RequiredTriggerAction(frodo); + action.appendEffect(new WoundCharactersEffect(frodo, runner)); + action.setText("Wound Runner"); + return Collections.singletonList(action); + } + }); + + scn.StartGame(); + scn.SetTwilight(20); + + scn.SkipToPhase(Phase.MANEUVER); + + assertEquals(Zone.SHADOW_CHARACTERS, runner.getZone()); + assertEquals(Zone.DISCARD, sauron.getZone()); + assertEquals(Zone.DISCARD, arrowslits.getZone()); + assertEquals(Zone.DISCARD, maneuver.getZone()); + assertEquals(2, scn.GetCultureTokensOn(ruin)); + scn.FreepsUseCardAction(frodo); + + assertTrue(scn.FreepsDecisionAvailable("Choose card from discard")); + assertTrue(scn.FreepsHasCardChoicesAvailable(arrowslits, maneuver)); + scn.FreepsChooseCard(arrowslits); + assertEquals(Zone.SUPPORT, arrowslits.getZone()); + + assertTrue(scn.ShadowDecisionAvailable("Choose card from discard")); + assertEquals(0, scn.ShadowGetChoiceMin()); + assertTrue(scn.ShadowHasCardChoicesAvailable(runner, sauron)); + scn.ShadowChooseCard(sauron); + assertEquals(Zone.DISCARD, runner.getZone()); + assertEquals(Zone.SHADOW_CHARACTERS, sauron.getZone()); + } + + @Test + public void NowforRuinPermitsPlayOfEitherRohanConditionOrArcheryEventAndShadowMinion() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var frodo = scn.GetRingBearer(); + var ruin = scn.GetFreepsCard("ruin"); + var arrowslits = scn.GetFreepsCard("arrowslits"); + var archery = scn.GetFreepsCard("archery"); + scn.FreepsMoveCardToSupportArea(ruin); + scn.FreepsMoveCharToTable("vhaldir", "vgimli"); + scn.FreepsMoveCardToSupportArea("possession"); //needed prereq for the archery event + scn.FreepsMoveCardToDiscard(arrowslits, archery); + + scn.AddTokensToCard(ruin, 2); + + var runner = scn.GetShadowCard("runner"); + var sauron = scn.GetShadowCard("sauron"); + scn.ShadowMoveCharToTable(runner); + scn.ShadowMoveCardToDiscard(sauron); + + //Cheating and adding an all-phases action on frodo to wound the Goblin Runner directly + scn.ApplyAdHocAction(new AbstractActionProxy() { + @Override + public List getPhaseActions(String playerId, LotroGame game) { + RequiredTriggerAction action = new RequiredTriggerAction(frodo); + action.appendEffect(new WoundCharactersEffect(frodo, runner)); + action.setText("Wound Runner"); + return Collections.singletonList(action); + } + }); + + scn.StartGame(); + scn.SetTwilight(20); + + scn.SkipToPhase(Phase.ARCHERY); + + assertEquals(Zone.SHADOW_CHARACTERS, runner.getZone()); + assertEquals(Zone.DISCARD, sauron.getZone()); + assertEquals(Zone.DISCARD, arrowslits.getZone()); + assertEquals(Zone.DISCARD, archery.getZone()); + assertEquals(2, scn.GetCultureTokensOn(ruin)); + scn.FreepsUseCardAction(frodo); + + assertTrue(scn.FreepsDecisionAvailable("Choose card from discard")); + assertTrue(scn.FreepsHasCardChoicesAvailable(arrowslits, archery)); + scn.FreepsChooseCard(arrowslits); + assertEquals(Zone.SUPPORT, arrowslits.getZone()); + + assertTrue(scn.ShadowDecisionAvailable("Choose card from discard")); + assertEquals(0, scn.ShadowGetChoiceMin()); + assertTrue(scn.ShadowHasCardChoicesAvailable(runner, sauron)); + scn.ShadowChooseCard(sauron); + assertEquals(Zone.DISCARD, runner.getZone()); + assertEquals(Zone.SHADOW_CHARACTERS, sauron.getZone()); + } + + @Test + public void NowforRuinPermitsPlayOfEitherRohanConditionOrSkirmishEventAndShadowMinion() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var frodo = scn.GetRingBearer(); + var ruin = scn.GetFreepsCard("ruin"); + var arrowslits = scn.GetFreepsCard("arrowslits"); + var skirmish = scn.GetFreepsCard("skirmish"); + scn.FreepsMoveCardToSupportArea(ruin); + scn.FreepsMoveCharToTable("vhaldir", "vgimli", "eowyn"); + scn.FreepsMoveCardToDiscard(arrowslits, skirmish); + + scn.AddTokensToCard(ruin, 2); + + var runner = scn.GetShadowCard("runner"); + var sauron = scn.GetShadowCard("sauron"); + scn.ShadowMoveCharToTable(runner); + scn.ShadowMoveCardToDiscard(sauron); + + //Cheating and adding an all-phases action on frodo to wound the Goblin Runner directly + scn.ApplyAdHocAction(new AbstractActionProxy() { + @Override + public List getPhaseActions(String playerId, LotroGame game) { + RequiredTriggerAction action = new RequiredTriggerAction(frodo); + action.appendEffect(new WoundCharactersEffect(frodo, runner)); + action.setText("Wound Runner"); + return Collections.singletonList(action); + } + }); + + scn.StartGame(); + scn.SetTwilight(20); + + scn.SkipToAssignments(); + scn.FreepsAssignAndResolve(frodo, runner); + + assertEquals(Zone.SHADOW_CHARACTERS, runner.getZone()); + assertEquals(Zone.DISCARD, sauron.getZone()); + assertEquals(Zone.DISCARD, arrowslits.getZone()); + assertEquals(Zone.DISCARD, skirmish.getZone()); + assertEquals(2, scn.GetCultureTokensOn(ruin)); + scn.FreepsUseCardAction(frodo); + + assertTrue(scn.FreepsDecisionAvailable("Choose card from discard")); + assertTrue(scn.FreepsHasCardChoicesAvailable(arrowslits, skirmish)); + scn.FreepsChooseCard(arrowslits); + assertEquals(Zone.SUPPORT, arrowslits.getZone()); + + assertTrue(scn.ShadowDecisionAvailable("Choose card from discard")); + assertEquals(0, scn.ShadowGetChoiceMin()); + assertTrue(scn.ShadowHasCardChoicesAvailable(runner, sauron)); + scn.ShadowChooseCard(sauron); + assertEquals(Zone.DISCARD, runner.getZone()); + assertEquals(Zone.SHADOW_CHARACTERS, sauron.getZone()); + } + + @Test + public void NowforRuinPermitsPlayOfEitherRohanConditionOrRegroupEventAndShadowMinion() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + var scn = GetScenario(); + + var frodo = scn.GetRingBearer(); + var ruin = scn.GetFreepsCard("ruin"); + var arrowslits = scn.GetFreepsCard("arrowslits"); + var regroup = scn.GetFreepsCard("regroup"); + scn.FreepsMoveCardToSupportArea(ruin); + scn.FreepsMoveCharToTable("vhaldir", "vgimli", "eowyn"); + scn.FreepsMoveCardToDiscard(arrowslits, regroup); + + scn.AddTokensToCard(ruin, 2); + + var runner = scn.GetShadowCard("runner"); + var sauron = scn.GetShadowCard("sauron"); + scn.ShadowMoveCharToTable(runner); + scn.ShadowMoveCardToDiscard(sauron); + + //Cheating and adding an all-phases action on frodo to wound the Goblin Runner directly + scn.ApplyAdHocAction(new AbstractActionProxy() { + @Override + public List getPhaseActions(String playerId, LotroGame game) { + RequiredTriggerAction action = new RequiredTriggerAction(frodo); + action.appendEffect(new WoundCharactersEffect(frodo, runner)); + action.setText("Wound Runner"); + return Collections.singletonList(action); + } + }); + + scn.StartGame(); + scn.SetTwilight(20); + + scn.SkipToAssignments(); + scn.FreepsDeclineAssignments(); + scn.ShadowDeclineAssignments(); + + assertEquals(Zone.SHADOW_CHARACTERS, runner.getZone()); + assertEquals(Zone.DISCARD, sauron.getZone()); + assertEquals(Zone.DISCARD, arrowslits.getZone()); + assertEquals(Zone.DISCARD, regroup.getZone()); + assertEquals(2, scn.GetCultureTokensOn(ruin)); + scn.FreepsUseCardAction(frodo); + + assertTrue(scn.FreepsDecisionAvailable("Choose card from discard")); + assertTrue(scn.FreepsHasCardChoicesAvailable(arrowslits, regroup)); + scn.FreepsChooseCard(arrowslits); + assertEquals(Zone.SUPPORT, arrowslits.getZone()); + + assertTrue(scn.ShadowDecisionAvailable("Choose card from discard")); + assertEquals(0, scn.ShadowGetChoiceMin()); + assertTrue(scn.ShadowHasCardChoicesAvailable(runner, sauron)); + scn.ShadowChooseCard(sauron); + assertEquals(Zone.DISCARD, runner.getZone()); + assertEquals(Zone.SHADOW_CHARACTERS, sauron.getZone()); + } + @Test public void NowforRuinTriggersOnReinforceOfSecondToken() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup