diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifyOwnCost.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifyOwnCost.java index 71e73ef76..a7d4082e2 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifyOwnCost.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifyOwnCost.java @@ -27,6 +27,9 @@ public class ModifyOwnCost implements EffectProcessor { return 0; } + if(target == null && onFilterableSource.getFilterable(actionContext) != Filters.any) + return 0; + if (target != null) { if (!Filters.and(onFilterableSource.getFilterable(actionContext)).accepts(actionContext.getGame(), target)) return 0; 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 3a67d9893..bae4afbc9 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 @@ -172,9 +172,11 @@ public class GenericCardTestHelper extends AbstractAtTest { public Boolean FreepsActionAvailable(String action) { return ActionAvailable(P1, action); } public Boolean FreepsCardActionAvailable(PhysicalCardImpl card) { return ActionAvailable(P1, "Use " + GameUtils.getFullName(card)); } public Boolean FreepsCardPlayAvailable(PhysicalCardImpl card) { return ActionAvailable(P1, "Play " + GameUtils.getFullName(card)); } + public Boolean FreepsCardTransferAvailable(PhysicalCardImpl card) { return ActionAvailable(P1, "Transfer " + GameUtils.getFullName(card)); } public Boolean ShadowActionAvailable(String action) { return ActionAvailable(P2, action); } public Boolean ShadowCardActionAvailable(PhysicalCardImpl card) { return ActionAvailable(P2, "Use " + GameUtils.getFullName(card)); } public Boolean ShadowCardPlayAvailable(PhysicalCardImpl card) { return ActionAvailable(P2, "Play " + GameUtils.getFullName(card)); } + public Boolean ShadowCardTransferAvailable(PhysicalCardImpl card) { return ActionAvailable(P2, "Transfer " + GameUtils.getFullName(card)); } public Boolean ActionAvailable(String player, String action) { List actions = GetAvailableActions(player); if(actions == null) @@ -222,8 +224,12 @@ public class GenericCardTestHelper extends AbstractAtTest { public void FreepsUseCardAction(String name) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, name)); } public void FreepsUseCardAction(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, "Use " + GameUtils.getFullName(card))); } + public void FreepsTransferCard(String name) throws DecisionResultInvalidException { FreepsTransferCard(GetFreepsCard(name)); } + public void FreepsTransferCard(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, "Transfer " + GameUtils.getFullName(card))); } public void ShadowUseCardAction(String name) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, name)); } public void ShadowUseCardAction(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, "Use " + GameUtils.getFullName(card))); } + public void ShadowTransferCard(String name) throws DecisionResultInvalidException { ShadowTransferCard(GetShadowCard(name)); } + public void ShadowTransferCard(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, "Transfer " + GameUtils.getFullName(card))); } public void FreepsPlayCard(String name) throws DecisionResultInvalidException { FreepsPlayCard(GetFreepsCard(name)); } public void FreepsPlayCard(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, "Play " + GameUtils.getFullName(card))); } @@ -786,4 +792,39 @@ public class GenericCardTestHelper extends AbstractAtTest { { return _game.getModifiersQuerying().getOverwhelmMultiplier(_game, card); } + + public void SkipToSite(int siteNum) throws DecisionResultInvalidException { + for(int i = GetCurrentSite().getSiteNumber(); i < siteNum; i++) + { + PhysicalCardImpl site = GetCurrentSite(); + + SkipToPhase(Phase.REGROUP); + if(i == 8) + return; // Game finished + PassCurrentPhaseActions(); + if(ShadowDecisionAvailable("reconcile")) + { + ShadowDeclineReconciliation(); + } + FreepsChooseToStay(); + if(FreepsDecisionAvailable("reconcile")) + { + FreepsChoose(""); //decline reconcile + } + + //Shadow player + SkipToPhase(Phase.REGROUP); + FreepsPassCurrentPhaseAction(); // actually shadow with the swap + if(FreepsDecisionAvailable("reconcile")) + { + FreepsChoose(""); //decline reconcile + } + ShadowChoose("1"); // Choose to stay + if(ShadowDecisionAvailable("reconcile")) + { + ShadowDeclineReconciliation(); + } + Assert.assertEquals(Phase.FELLOWSHIP, GetCurrentPhase()); + } + } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_031_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_031_Tests.java new file mode 100644 index 000000000..8420c0a12 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_031_Tests.java @@ -0,0 +1,220 @@ + +package com.gempukku.lotro.cards.official.set01; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.*; +import com.gempukku.lotro.filters.Filters; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import com.gempukku.lotro.logic.modifiers.KeywordModifier; +import com.gempukku.lotro.logic.modifiers.MoveLimitModifier; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class Card_01_031_Tests +{ + + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("asfaloth", "1_31"); + put("arwen", "3_7"); + put("legolas", "1_50"); + put("erestor", "3_14"); + put("orophin", "1_56"); + }}, + GenericCardTestHelper.FellowshipSites, + GenericCardTestHelper.FOTRFrodo, + GenericCardTestHelper.FOTRRing + ); + } + + @Test + public void AsfalothStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1 + * Title: *Asfaloth + * Side: Free Peoples + * Culture: Elven + * Twilight Cost: 2 + * Type: Possession + * Item Class: Mount + * Game Text: Bearer must be an Elf. When played on Arwen, Asfaloth's twilight cost is -2. While at a plains + * site, bearer is strength +2. Discard Asfaloth when at an underground site. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl asfaloth = scn.GetFreepsCard("asfaloth"); + + assertTrue(asfaloth.getBlueprint().isUnique()); + assertEquals(Side.FREE_PEOPLE, asfaloth.getBlueprint().getSide()); + assertEquals(Culture.ELVEN, asfaloth.getBlueprint().getCulture()); + assertEquals(CardType.POSSESSION, asfaloth.getBlueprint().getCardType()); + assertEquals(PossessionClass.MOUNT, asfaloth.getBlueprint().getPossessionClasses().stream().findFirst().get()); + assertEquals(2, asfaloth.getBlueprint().getTwilightCost()); + assertEquals(2, asfaloth.getBlueprint().getStrength()); +// assertEquals(3, asfaloth.getBlueprint().getVitality()); + //assertEquals(, asfaloth.getBlueprint().getResistance()); + //assertEquals(Signet., asfaloth.getBlueprint().getSignet()); + //assertEquals(3, asfaloth.getBlueprint().getAllyHomeSiteNumbers()[0]); // Change this to getAllyHomeSiteNumbers for allies + + } + + @Test + public void BearerMustBeAnElf() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl asfaloth = scn.GetFreepsCard("asfaloth"); + PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); + PhysicalCardImpl erestor = scn.GetFreepsCard("erestor"); + PhysicalCardImpl orophin = scn.GetFreepsCard("orophin"); + scn.FreepsMoveCardToHand(asfaloth, arwen, erestor, orophin); + + scn.StartGame(); + + assertFalse(scn.FreepsCardPlayAvailable(asfaloth)); + scn.FreepsPlayCard(orophin); + assertTrue(scn.FreepsCardPlayAvailable(asfaloth)); + scn.FreepsPlayCard(arwen); + scn.FreepsPlayCard(asfaloth); + assertEquals(2, scn.GetFreepsCardChoiceCount()); // can go on either arwen or orophin + } + + @Test + public void TwilightCost2OnNonArwen() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl asfaloth = scn.GetFreepsCard("asfaloth"); + PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); + PhysicalCardImpl erestor = scn.GetFreepsCard("erestor"); + PhysicalCardImpl orophin = scn.GetFreepsCard("orophin"); + scn.FreepsMoveCharToTable(arwen, erestor, orophin); + scn.FreepsMoveCardToHand(asfaloth); + + scn.StartGame(); + + assertEquals(0, scn.GetTwilight()); + scn.FreepsPlayCard(asfaloth); + scn.FreepsChooseCard(erestor); + assertEquals(2, scn.GetTwilight()); + } + + @Test + public void TwilightCost0OnArwen() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl asfaloth = scn.GetFreepsCard("asfaloth"); + PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); + PhysicalCardImpl erestor = scn.GetFreepsCard("erestor"); + PhysicalCardImpl orophin = scn.GetFreepsCard("orophin"); + scn.FreepsMoveCharToTable(arwen, erestor, orophin); + scn.FreepsMoveCardToHand(asfaloth); + + scn.StartGame(); + + assertEquals(0, scn.GetTwilight()); + scn.FreepsPlayCard(asfaloth); + scn.FreepsChooseCard(arwen); + assertEquals(0, scn.GetTwilight()); + } + + @Test + public void BearerIsStrengthPlus2AtPlains() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl asfaloth = scn.GetFreepsCard("asfaloth"); + PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); + PhysicalCardImpl erestor = scn.GetFreepsCard("erestor"); + PhysicalCardImpl orophin = scn.GetFreepsCard("orophin"); + scn.FreepsMoveCharToTable(arwen, erestor, orophin); + scn.FreepsMoveCardToHand(asfaloth); + + //cheating to ensure site 2 qualifies + scn.ApplyAdHocModifier(new KeywordModifier(null, Filters.siteNumber(2), Keyword.PLAINS)); + + scn.StartGame(); + + assertEquals(6, scn.GetStrength(arwen)); + scn.FreepsPlayCard(asfaloth); + scn.FreepsChooseCard(arwen); + assertEquals(8, scn.GetStrength(arwen)); + scn.FreepsPassCurrentPhaseAction(); + + assertEquals(10, scn.GetStrength(arwen)); + } + + @Test + public void SelfDiscardsAtUnderground() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl asfaloth = scn.GetFreepsCard("asfaloth"); + PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); + PhysicalCardImpl erestor = scn.GetFreepsCard("erestor"); + PhysicalCardImpl orophin = scn.GetFreepsCard("orophin"); + scn.FreepsMoveCharToTable(arwen, erestor, orophin); + scn.FreepsMoveCardToHand(asfaloth); + + //cheating to ensure site 2 qualifies + scn.ApplyAdHocModifier(new KeywordModifier(null, Filters.siteNumber(2), Keyword.UNDERGROUND)); + + scn.StartGame(); + + scn.FreepsPlayCard(asfaloth); + scn.FreepsChooseCard(arwen); + assertEquals(Zone.ATTACHED, asfaloth.getZone()); + scn.FreepsPassCurrentPhaseAction(); + + scn.FreepsChoose("0"); // timing tie between Asfaloth and Site + assertEquals(Zone.DISCARD, asfaloth.getZone()); + } + + @Test + public void TransferBetweenAllyAndCompanionPaysTwilight() throws DecisionResultInvalidException, CardNotFoundException { + // Bug reported: https://play.lotrtcgpc.net/gemp-lotr/game.html?replayId=FallsLover$ilpahhdbsdmp8i2x + // Site 6 permitted multiple transfers between Rumil and Legolas on site 6 with 0 twilight added to the pool. + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl asfaloth = scn.GetFreepsCard("asfaloth"); + PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); + PhysicalCardImpl legolas = scn.GetFreepsCard("legolas"); + PhysicalCardImpl erestor = scn.GetFreepsCard("erestor"); + PhysicalCardImpl orophin = scn.GetFreepsCard("orophin"); + scn.FreepsMoveCharToTable(arwen, legolas, erestor, orophin); + scn.FreepsMoveCardToHand(asfaloth); + + scn.ApplyAdHocModifier(new MoveLimitModifier(null, 10)); + + scn.StartGame(); + + assertEquals(0, scn.GetTwilight()); + scn.FreepsPlayCard(asfaloth); + scn.FreepsChooseCard(erestor); + assertEquals(2, scn.GetTwilight()); + + scn.SkipToSite(3); + + assertEquals(0, scn.GetTwilight()); + assertTrue(scn.FreepsCardTransferAvailable(asfaloth)); + scn.FreepsTransferCard(asfaloth); + scn.FreepsChooseCard(legolas); + assertEquals(2, scn.GetTwilight()); + } + +}