diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Gandalf.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Gandalf.hjson index d31252a62..92e4b2f08 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Gandalf.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Gandalf.hjson @@ -1015,7 +1015,7 @@ culture: Gandalf twilight: 1 type: Condition - target: ent + target: ent,canExert effects: [ { type: exertTargetExtraCost diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set05/set05-Sauron.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set05/set05-Sauron.hjson index fe2bea699..d8027879f 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set05/set05-Sauron.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set05/set05-Sauron.hjson @@ -118,11 +118,6 @@ player: fp filter: self } - cost: { - type: discardFromHand - forced: false - select: self - } effect: { type: addBurdens amount: 2 diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/CanMove.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/CanMove.java deleted file mode 100644 index 02a9fb7c4..000000000 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/CanMove.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.gempukku.lotro.cards.build.field.effect.requirement; - -import com.gempukku.lotro.cards.build.CardGenerationEnvironment; -import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; -import com.gempukku.lotro.cards.build.Requirement; -import com.gempukku.lotro.cards.build.field.FieldUtils; -import com.gempukku.lotro.game.state.LotroGame; -import com.gempukku.lotro.logic.modifiers.ModifierFlag; -import org.json.simple.JSONObject; - -public class CanMove implements RequirementProducer { - @Override - public Requirement getPlayRequirement(JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(object); - - return (actionContext) -> { - LotroGame game = actionContext.getGame(); - return !game.getModifiersQuerying().hasFlagActive(game, ModifierFlag.CANT_MOVE) - && game.getGameState().getMoveCount() < game.getModifiersQuerying().getMoveLimit(game, 2); - }; - } -} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/RequirementFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/RequirementFactory.java index ddc10fbb5..e33af5ed1 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/RequirementFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/RequirementFactory.java @@ -22,8 +22,6 @@ public class RequirementFactory { requirementProducers.put("isgreaterthanorequal", new IsGreaterThanOrEqual()); requirementProducers.put("islessthan", new IsLessThan()); requirementProducers.put("islessthanorequal", new IsLessThanOrEqual()); - - requirementProducers.put("canmove", new CanMove()); requirementProducers.put("canplayfromdiscard", new CanPlayFromDiscard()); requirementProducers.put("canselfbeplayed", new CanSelfBePlayed()); requirementProducers.put("canspot", new CanSpot()); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/Exerts.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/Exerts.java deleted file mode 100644 index 87bfdb05e..000000000 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/Exerts.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.gempukku.lotro.cards.build.field.effect.trigger; - -import com.gempukku.lotro.cards.build.ActionContext; -import com.gempukku.lotro.cards.build.CardGenerationEnvironment; -import com.gempukku.lotro.cards.build.FilterableSource; -import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; -import com.gempukku.lotro.cards.build.field.FieldUtils; -import com.gempukku.lotro.common.Filterable; -import com.gempukku.lotro.game.PhysicalCard; -import com.gempukku.lotro.logic.timing.TriggerConditions; -import com.gempukku.lotro.logic.timing.results.ExertResult; -import org.json.simple.JSONObject; - -public class Exerts implements TriggerCheckerProducer { - @Override - public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(value, "filter", "memorize"); - - final String filter = FieldUtils.getString(value.get("filter"), "filter", "any"); - final String memorize = FieldUtils.getString(value.get("memorize"), "memorize"); - - final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment); - - return new TriggerChecker() { - @Override - public boolean isBefore() { - return false; - } - - @Override - public boolean accepts(ActionContext actionContext) { - final Filterable filterable = filterableSource.getFilterable(actionContext); - final boolean result = TriggerConditions.forEachExerted(actionContext.getGame(), actionContext.getEffectResult(), filterable); - if (result && memorize != null) { - final PhysicalCard exertedCard = ((ExertResult) actionContext.getEffectResult()).getExertedCard(); - actionContext.setCardMemory(memorize, exertedCard); - } - return result; - } - }; - } -} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/FPDecidedIfMoving.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/FPDecidedIfMoving.java deleted file mode 100644 index 38ddf5b4f..000000000 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/FPDecidedIfMoving.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gempukku.lotro.cards.build.field.effect.trigger; - -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.logic.timing.TriggerConditions; -import org.json.simple.JSONObject; - -public class FPDecidedIfMoving implements TriggerCheckerProducer { - @Override - public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(value); - - return new TriggerChecker() { - @Override - public boolean accepts(ActionContext actionContext) { - return TriggerConditions.freePlayerDecidedIfMoving(actionContext.getGame(), actionContext.getEffectResult()); - } - - @Override - public boolean isBefore() { - return false; - } - }; - } -} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/FPDecidedToMove.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/FPDecidedToMove.java deleted file mode 100644 index 1370c7168..000000000 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/FPDecidedToMove.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gempukku.lotro.cards.build.field.effect.trigger; - -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.logic.timing.TriggerConditions; -import org.json.simple.JSONObject; - -public class FPDecidedToMove implements TriggerCheckerProducer { - @Override - public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(value); - - return new TriggerChecker() { - @Override - public boolean accepts(ActionContext actionContext) { - return TriggerConditions.freePlayerDecidedToMove(actionContext.getGame(), actionContext.getEffectResult()); - } - - @Override - public boolean isBefore() { - return false; - } - }; - } -} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RevealedCardFromHand.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RevealedCardFromHand.java index ae726d9db..9c7444826 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RevealedCardFromHand.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RevealedCardFromHand.java @@ -32,7 +32,7 @@ public class RevealedCardFromHand implements TriggerCheckerProducer { public boolean accepts(ActionContext actionContext) { if (TriggerConditions.forEachCardRevealedFromHand(actionContext.getEffectResult())) { RevealCardFromHandResult revealCardFromHandResult = (RevealCardFromHandResult) actionContext.getEffectResult(); - if (playerSource != null && !playerSource.getPlayer(actionContext).equals(actionContext.getPerformingPlayer())) + if (playerSource != null && !playerSource.getPlayer(actionContext).equals(revealCardFromHandResult.getSource().getOwner())) return false; final Filterable filterable = filterableSource.getFilterable(actionContext); final PhysicalCard revealedCard = revealCardFromHandResult.getRevealedCard(); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java index e581c1709..ebbf70815 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java @@ -48,8 +48,6 @@ public class TriggerCheckerFactory { triggerCheckers.put("exerted", new Exerted()); triggerCheckers.put("exertsforspecialability", new ExertsForSpecialAbility()); triggerCheckers.put("exertstoplay", new ExertsToPlay()); - triggerCheckers.put("fpdecidedifmoving", new FPDecidedIfMoving()); - triggerCheckers.put("fpdecidedtomove", new FPDecidedToMove()); triggerCheckers.put("fpdecidedtostay", new FPDecidedToStay()); triggerCheckers.put("fpstartedassigning", new FPStartedAssigning()); triggerCheckers.put("heals", new Heals()); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/ToilDiscountEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/ToilDiscountEffect.java index 5d40b3fe7..b93f7828e 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/ToilDiscountEffect.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/ToilDiscountEffect.java @@ -69,7 +69,7 @@ public class ToilDiscountEffect extends AbstractSubActionEffect implements Disco if (_minimalDiscount == 0) { minimalExerts = 0; } else { - minimalExerts = _minimalDiscount / _toilCount + ((_minimalDiscount % _toilCount > 0) ? 1 : 0); + minimalExerts = (_minimalDiscount - _paidToil * _toilCount) / _toilCount + (((_minimalDiscount - _paidToil * _toilCount) % _toilCount > 0) ? 1 : 0); } SubAction subAction = new SubAction(_action); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/cost/ExertTargetExtraPlayCostModifier.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/cost/ExertTargetExtraPlayCostModifier.java index 7574c7f8e..25f2b420c 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/cost/ExertTargetExtraPlayCostModifier.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/cost/ExertTargetExtraPlayCostModifier.java @@ -15,7 +15,7 @@ public class ExertTargetExtraPlayCostModifier extends AbstractExtraPlayCostModif } @Override - public boolean canPayExtraCostsToPlay(LotroGame game, PhysicalCard card) { + public boolean canPayExtraCostsToPlay(LotroGame game, PhysicalCard target) { return true; } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/AbstractAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/AbstractAtTest.java index 48fccc1d9..e32a4b024 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/AbstractAtTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/AbstractAtTest.java @@ -17,7 +17,7 @@ import org.apache.commons.lang3.StringUtils; import java.util.*; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; public abstract class AbstractAtTest { public static LotroCardBlueprintLibrary _cardLibrary; @@ -39,8 +39,28 @@ public abstract class AbstractAtTest { return (PhysicalCardImpl) _game.getGameState().createPhysicalCard(owner, _cardLibrary, blueprintId); } - public void addToZone(PhysicalCard card, Zone zone) { + public PhysicalCard getRingBearer(String player) { + return _game.getGameState().getRingBearer(player); + } + + public PhysicalCard getRing(String player) { + return _game.getGameState().getRing(player); + } + + public PhysicalCard addToZone(PhysicalCard card, Zone zone) { _game.getGameState().addCardToZone(_game, card, zone); + return card; + } + + public PhysicalCard attachTo(PhysicalCard card, PhysicalCard toCard) { + addToZone(card, Zone.ATTACHED); + ((PhysicalCardImpl) card).attachTo((PhysicalCardImpl) toCard); + return card; + } + + public PhysicalCard putOnTopOfDeck(PhysicalCard card) { + _game.getGameState().putCardOnTopOfDeck(card); + return card; } public void selectArbitraryCards(String player, String[] blueprintIds) throws DecisionResultInvalidException { @@ -51,6 +71,14 @@ public abstract class AbstractAtTest { playerDecided(player, getCardActionId(player, card.getCardId())); } + public void hasCardAction(String player, PhysicalCard card) { + assertNotNull(getCardActionId(player, card)); + } + + public void assertNoCardAction(String player, PhysicalCard card) { + assertNull(getCardActionId(player, card)); + } + public void selectCard(String player, PhysicalCard card) throws DecisionResultInvalidException { playerDecided(player, String.valueOf(card.getCardId())); } @@ -67,6 +95,31 @@ public abstract class AbstractAtTest { return _game.getGameState().getWounds(card); } + public void addWounds(PhysicalCard card, int count) { + for (int i = 0; i < count; i++) { + _game.getGameState().addWound(card); + } + } + + public void removeWounds(PhysicalCard card, int count) { + for (int i = 0; i < count; i++) { + if (getWounds(card) > 0) { + _game.getGameState().removeWound(card); + } + } + } + + public void replaceSite(PhysicalCard newSite, int siteNumber) { + PhysicalCard oldSite = _game.getGameState().getSite(siteNumber); + _game.getGameState().removeCardsFromZone(oldSite.getOwner(), Collections.singleton(oldSite)); + oldSite.setSiteNumber(null); + _game.getGameState().addCardToZone(_game, oldSite, Zone.ADVENTURE_DECK); + + _game.getGameState().removeCardsFromZone(newSite.getOwner(), Collections.singleton(newSite)); + newSite.setSiteNumber(siteNumber); + _game.getGameState().addCardToZone(_game, newSite, Zone.ADVENTURE_PATH); + } + public int getTwilightPool() { return _game.getGameState().getTwilightPool(); } @@ -83,6 +136,10 @@ public abstract class AbstractAtTest { return _game.getGameState().getThreats(); } + public int getBurdens() { + return _game.getGameState().getBurdens(); + } + public Phase getPhase() { return _game.getGameState().getCurrentPhase(); } @@ -91,6 +148,10 @@ public abstract class AbstractAtTest { playerDecided(player, ""); } + public int getStrength(PhysicalCard card) { + return _game.getModifiersQuerying().getStrength(_game, card); + } + public void initializeSimplestGame() throws DecisionResultInvalidException { this.initializeSimplestGame(null); } @@ -131,6 +192,23 @@ public abstract class AbstractAtTest { playerDecided(P2, "0"); } + public void passUntil(Phase phase) throws DecisionResultInvalidException { + while (true) { + Phase currentPhase = _game.getGameState().getCurrentPhase(); + if (currentPhase == phase) + break; + switch (currentPhase) { + case BETWEEN_TURNS -> skipMulligans(); + case FELLOWSHIP -> pass(P1); + case SHADOW -> pass(P2); + case MANEUVER, ARCHERY, ASSIGNMENT -> { + pass(P1); + pass(P2); + } + } + } + } + public void validateContents(String[] array1, String[] array2) { if (array1.length != array2.length) fail("Array sizes differ"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/ExtraCostToPlayAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/ExtraCostToPlayAtTest.java index 178b17ecc..34bf3eadb 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/ExtraCostToPlayAtTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/ExtraCostToPlayAtTest.java @@ -2,6 +2,7 @@ package com.gempukku.lotro.at; import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; import org.junit.Test; @@ -45,4 +46,32 @@ public class ExtraCostToPlayAtTest extends AbstractAtTest { String[] actionIds = (String[]) _userFeedback.getAwaitingDecision(P1).getDecisionParameters().get("actionId"); assertEquals(0, actionIds.length); } + + @Test + public void windowsInAStoneWallExertsTarget() throws DecisionResultInvalidException, CardNotFoundException { + initializeSimplestGame(); + + PhysicalCard windowsInAStoneWall = addToZone(createCard(P1, "4_107"), Zone.HAND); + PhysicalCard treebeard = addToZone(createCard(P1, "4_103"), Zone.FREE_CHARACTERS); + + skipMulligans(); + + // Fellowship + selectCardAction(P1, windowsInAStoneWall); + assertEquals(1, getWounds(treebeard)); + } + + @Test + public void windowsInAStoneWallCantPlayOnExhaustedEnt() throws DecisionResultInvalidException, CardNotFoundException { + initializeSimplestGame(); + + PhysicalCard windowsInAStoneWall = addToZone(createCard(P1, "4_107"), Zone.HAND); + PhysicalCard treebeard = addToZone(createCard(P1, "4_103"), Zone.FREE_CHARACTERS); + addWounds(treebeard, 3); + + skipMulligans(); + + // Fellowship + assertNoCardAction(P1, windowsInAStoneWall); + } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/TriggersAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/TriggersAtTest.java index 395111708..48fe05f52 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/TriggersAtTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/TriggersAtTest.java @@ -305,4 +305,234 @@ public class TriggersAtTest extends AbstractAtTest { assertEquals(siteOne, _game.getGameState().getSite(1)); } + + @Test + public void startOfSkirmishInvolving() throws Exception { + initializeSimplestGame(); + + PhysicalCard gimli = addToZone(createCard(P1, "5_7"), Zone.FREE_CHARACTERS); + PhysicalCard hopelessGollum = addToZone(createCard(P2, "15_43"), Zone.SHADOW_CHARACTERS); + + passUntil(Phase.ASSIGNMENT); + pass(P1); + pass(P2); + + playerDecided(P1, gimli.getCardId() + " " + hopelessGollum.getCardId()); + + assertEquals(0, getStrength(hopelessGollum)); + selectCard(P1, gimli); + assertEquals(4, getStrength(hopelessGollum)); + } + + @Test + public void skirmishAboutToEnd() throws Exception { + initializeSimplestGame(); + + PhysicalCard gimli = addToZone(createCard(P1, "5_7"), Zone.FREE_CHARACTERS); + PhysicalCard attea = addToZone(createCard(P2, "1_229"), Zone.SHADOW_CHARACTERS); + PhysicalCard loathsome = addToZone(createCard(P2, "7_182"), Zone.HAND); + + passUntil(Phase.ASSIGNMENT); + pass(P1); + pass(P2); + playerDecided(P1, gimli.getCardId() + " " + attea.getCardId()); + + selectCard(P1, gimli); + pass(P1); + pass(P2); + + selectCardAction(P2, loathsome); + assertEquals(Zone.DISCARD, loathsome.getZone()); + } + + @Test + public void revealedCardFromHand() throws Exception { + initializeSimplestGame(); + + PhysicalCard eyeOfBaradDur = addToZone(createCard(P2, "5_96"), Zone.HAND); + PhysicalCard gandalf = addToZone(createCard(P1, "1_72"), Zone.FREE_CHARACTERS); + PhysicalCard glamdring = attachTo(createCard(P1, "1_75"), gandalf); + + passUntil(Phase.FELLOWSHIP); + selectCardAction(P1, glamdring); + pass(P1); + + assertEquals(1, getBurdens()); + selectCardAction(P2, eyeOfBaradDur); + assertEquals(3, getBurdens()); + } + + @Test + public void playerDrawsCard() throws Exception { + initializeSimplestGame(); + + PhysicalCard verilyICome = attachTo(createCard(P2, "2_94"), _game.getGameState().getRingBearer(P1)); + PhysicalCard elrond = addToZone(createCard(P1, "1_40"), Zone.SUPPORT); + + passUntil(Phase.FELLOWSHIP); + + putOnTopOfDeck(createCard(P1, "1_40")); + + assertEquals(1, getBurdens()); + selectCardAction(P1, elrond); + assertEquals(2, getBurdens()); + } + + @Test + public void beforeToil() throws Exception { + initializeSimplestGame(); + + PhysicalCard enqueaBlackThirst = addToZone(createCard(P2, "12_175"), Zone.SHADOW_CHARACTERS); + PhysicalCard minasMorgulAnswers = addToZone(createCard(P2, "12_167"), Zone.HAND); + + passUntil(Phase.SHADOW); + assertEquals(2, getTwilightPool()); + selectCardAction(P2, minasMorgulAnswers); + selectCardAction(P2, enqueaBlackThirst); + pass(P2); + selectCard(P2, enqueaBlackThirst); + assertEquals(2, getTwilightPool()); + assertEquals(2, getWounds(enqueaBlackThirst)); + assertEquals(Zone.DISCARD, minasMorgulAnswers.getZone()); + } + + @Test + public void usesSpecialAbility() throws Exception { + initializeSimplestGame(); + + PhysicalCard hauntingHerSteps = addToZone(createCard(P2, "4_155"), Zone.HAND); + PhysicalCard grimaWormtongue = addToZone(createCard(P2, "4_154"), Zone.SHADOW_CHARACTERS); + + PhysicalCard elrond = addToZone(createCard(P1, "1_40"), Zone.SUPPORT); + + passUntil(Phase.FELLOWSHIP); + + PhysicalCard cardInDeck = putOnTopOfDeck(createCard(P1, "1_40")); + + selectCardAction(P1, elrond); + selectCardAction(P2, hauntingHerSteps); + + assertEquals(1, getWounds(grimaWormtongue)); + assertEquals(Zone.DECK, cardInDeck.getZone()); + } + + @Test + public void takesWound() throws Exception { + initializeSimplestGame(); + + PhysicalCard promiseKeeping = addToZone(createCard(P2, "8_24"), Zone.SUPPORT); + PhysicalCard gollum = addToZone(createCard(P2, "7_58"), Zone.SHADOW_CHARACTERS); + + PhysicalCard ringBearer = getRingBearer(P1); + + passUntil(Phase.ASSIGNMENT); + pass(P1); + pass(P2); + playerDecided(P1, ringBearer.getCardId() + " " + gollum.getCardId()); + selectCard(P1, ringBearer); + pass(P1); + pass(P2); + + // Don't use Ring + pass(P1); + assertEquals(2, getWounds(ringBearer)); + } + + @Test + public void takesOffRing() throws Exception { + initializeSimplestGame(); + + PhysicalCard iSeeYou = addToZone(createCard(P2, "101_46"), Zone.SUPPORT); + PhysicalCard gollum = addToZone(createCard(P2, "7_58"), Zone.SHADOW_CHARACTERS); + + PhysicalCard ringBearer = getRingBearer(P1); + PhysicalCard ring = getRing(P1); + + passUntil(Phase.ASSIGNMENT); + pass(P1); + pass(P2); + playerDecided(P1, ringBearer.getCardId() + " " + gollum.getCardId()); + selectCard(P1, ringBearer); + pass(P1); + pass(P2); + assertEquals(Zone.SUPPORT, iSeeYou.getZone()); + selectCardAction(P1, ring); + assertEquals(Zone.DISCARD, iSeeYou.getZone()); + } + + @Test + public void siteLiberated() throws Exception { + initializeSimplestGame(); + + PhysicalCard drivenIntoTheHills = addToZone(createCard(P2, "102_1"), Zone.SUPPORT); + PhysicalCard theodenSonOfThengel = addToZone(createCard(P1, "4_292"), Zone.FREE_CHARACTERS); + PhysicalCard guma = addToZone(createCard(P1, "4_277"), Zone.SUPPORT); + + passUntil(Phase.SHADOW); + _game.getGameState().takeControlOfCard(P2, _game, _game.getGameState().getSite(1), Zone.SUPPORT); + _game.getGameState().setPlayerPosition(P2, 2); + + passUntil(Phase.REGROUP); + assertEquals(Zone.SUPPORT, drivenIntoTheHills.getZone()); + selectCardAction(P1, theodenSonOfThengel); + assertEquals(Zone.DISCARD, drivenIntoTheHills.getZone()); + } + + @Test + public void siteControlled() throws Exception { + initializeSimplestGame(); + + PhysicalCard youDoNotKnowPain = addToZone(createCard(P2, "17_138"), Zone.SUPPORT); + PhysicalCard whiteHandIntruder = addToZone(createCard(P2, "17_127"), Zone.SHADOW_CHARACTERS); + PhysicalCard gimli = addToZone(createCard(P1, "5_7"), Zone.FREE_CHARACTERS); + for (int i = 0; i < 2; i++) { + addToZone(createCard(P2, "17_119"), Zone.SHADOW_CHARACTERS); + } + + passUntil(Phase.SHADOW); + _game.getGameState().setPlayerPosition(P2, 2); + + passUntil(Phase.ASSIGNMENT); + pass(P1); + pass(P2); + playerDecided(P1, gimli.getCardId() + " " + whiteHandIntruder.getCardId()); + pass(P2); + selectCard(P1, gimli); + + pass(P1); + pass(P2); + selectCardAction(P2, whiteHandIntruder); + assertEquals(2, getWounds(gimli)); + removeWounds(gimli, 1); + assertEquals(1, getWounds(gimli)); + selectCardAction(P2, youDoNotKnowPain); + assertEquals(2, getWounds(gimli)); + } + + @Test + public void replacesSite() throws Exception { + initializeSimplestGame(); + + PhysicalCard riddermarkTactician = addToZone(createCard(P1, "13_133"), Zone.FREE_CHARACTERS); + PhysicalCard theoden = addToZone(createCard(P1, "13_137"), Zone.FREE_CHARACTERS); + PhysicalCard nelya = addToZone(createCard(P2, "11_222"), Zone.SHADOW_CHARACTERS); + + passUntil(Phase.SHADOW); + replaceSite(_game.getGameState().getAdventureDeck(P1).get(0), 2); + selectCardAction(P2, nelya); + hasCardAction(P1, riddermarkTactician); + } + + @Test + public void removesBurden() throws Exception { + initializeSimplestGame(); + + PhysicalCard theShireCountryside = addToZone(createCard(P1, "3_113"), Zone.SUPPORT); + PhysicalCard elfSong = addToZone(createCard(P1, "1_39"), Zone.HAND); + PhysicalCard elrond = addToZone(createCard(P1, "1_40"), Zone.FREE_CHARACTERS); + + passUntil(Phase.FELLOWSHIP); + selectCardAction(P1, elfSong); + hasCardAction(P1, theShireCountryside); + } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/PlayCardFromDiscardAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/PlayCardFromDiscardAtTest.java index 8aa33d23b..3d40b9cee 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/PlayCardFromDiscardAtTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/PlayCardFromDiscardAtTest.java @@ -3,15 +3,14 @@ package com.gempukku.lotro.at.effects; import com.gempukku.lotro.at.AbstractAtTest; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.common.Zone; +import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.AwaitingDecisionType; import org.junit.Test; import java.util.Map; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; +import static org.junit.Assert.*; public class PlayCardFromDiscardAtTest extends AbstractAtTest { @Test @@ -117,39 +116,38 @@ public class PlayCardFromDiscardAtTest extends AbstractAtTest { assertEquals(Zone.SHADOW_CHARACTERS, goblinSneakInDiscard.getZone()); } - //Migrated to the Ulaire Nertea tests in cards/official/set01/Card_01_234_Tests -// @Test -// public void ulaireNerteaCantPlayMinionsOnGreatRiver() throws Exception { -// initializeSimplestGame(); -// -// for (int i=0; i<4; i++) { -// final PhysicalCardImpl greatRiver = createCard(P1, "1_306"); -// _game.getGameState().addCardToZone(_game, greatRiver, Zone.FREE_CHARACTERS); -// } -// -// skipMulligans(); -// -// final PhysicalCardImpl greatRiver = createCard(P2, "3_118"); -// greatRiver.setSiteNumber(2); -// _game.getGameState().addCardToZone(_game, greatRiver, Zone.ADVENTURE_PATH); -// -// final PhysicalCardImpl ulaireNertea = createCard(P2, "1_234"); -// _game.getGameState().addCardToZone(_game, ulaireNertea, Zone.HAND); -// -// final PhysicalCardImpl goblinRunner = createCard(P2, "1_178"); -// _game.getGameState().addCardToZone(_game, goblinRunner, Zone.DISCARD); -// -// _game.getGameState().setTwilight(20); -// -// // Fellowship phase -// playerDecided(P1, ""); -// -// assertEquals(greatRiver, _game.getGameState().getCurrentSite()); -// -// playerDecided(P2, getCardActionId(P2, "Play Úlairë Nertëa")); -// -// assertFalse(_userFeedback.getAwaitingDecision(P2).getDecisionType() == AwaitingDecisionType.MULTIPLE_CHOICE); -// } + @Test + public void ulaireNerteaCantPlayMinionsOnGreatRiver() throws Exception { + initializeSimplestGame(); + + for (int i = 0; i < 4; i++) { + final PhysicalCardImpl greatRiver = createCard(P1, "1_306"); + _game.getGameState().addCardToZone(_game, greatRiver, Zone.FREE_CHARACTERS); + } + + skipMulligans(); + + final PhysicalCardImpl greatRiver = createCard(P2, "3_118"); + greatRiver.setSiteNumber(2); + _game.getGameState().addCardToZone(_game, greatRiver, Zone.ADVENTURE_PATH); + + final PhysicalCardImpl ulaireNertea = createCard(P2, "1_234"); + _game.getGameState().addCardToZone(_game, ulaireNertea, Zone.HAND); + + final PhysicalCardImpl goblinRunner = createCard(P2, "1_178"); + _game.getGameState().addCardToZone(_game, goblinRunner, Zone.DISCARD); + + _game.getGameState().setTwilight(20); + + // Fellowship phase + playerDecided(P1, ""); + + assertEquals(greatRiver, _game.getGameState().getCurrentSite()); + + playerDecided(P2, getCardActionId(P2, "Play Úlairë Nertëa")); + + assertFalse(_userFeedback.getAwaitingDecision(P2).getDecisionType() == AwaitingDecisionType.MULTIPLE_CHOICE); + } @Test public void azogCantPlayTrollFromDiscardInRivendell() throws Exception { @@ -184,4 +182,18 @@ public class PlayCardFromDiscardAtTest extends AbstractAtTest { assertNull(getCardActionId(P2, "Use Azog")); } + + @Test + public void activatedInDiscard() throws Exception { + initializeSimplestGame(); + + PhysicalCard gollumPlottingDeceiver = addToZone(createCard(P2, "7_58"), Zone.DISCARD); + + passUntil(Phase.FELLOWSHIP); + setTwilightPool(10); + passUntil(Phase.SHADOW); + + selectCardAction(P2, gollumPlottingDeceiver); + assertEquals(Zone.SHADOW_CHARACTERS, gollumPlottingDeceiver.getZone()); + } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/PlayCardFromStackedAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/PlayCardFromStackedAtTest.java index 92253bb6f..f75481689 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/PlayCardFromStackedAtTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/PlayCardFromStackedAtTest.java @@ -1,6 +1,7 @@ package com.gempukku.lotro.at.effects; import com.gempukku.lotro.at.AbstractAtTest; +import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.PhysicalCardImpl; @@ -55,4 +56,22 @@ public class PlayCardFromStackedAtTest extends AbstractAtTest { assertEquals(Zone.SHADOW_CHARACTERS, dunlendingLooter.getZone()); assertEquals(0, _game.getGameState().getTwilightPool()); } + + @Test + public void playFromStacked() throws Exception { + initializeSimplestGame(); + + PhysicalCard gimli = addToZone(createCard(P1, "5_7"), Zone.FREE_CHARACTERS); + PhysicalCard urukSavage = addToZone(createCard(P2, "1_151"), Zone.SHADOW_CHARACTERS); + + PhysicalCard greatestKingdomOfMyPeople = addToZone(createCard(P1, "1_16"), Zone.SUPPORT); + PhysicalCard slakedThirsts = addToZone(createCard(P1, "7_14"), Zone.STACKED); + ((PhysicalCardImpl) slakedThirsts).stackOn((PhysicalCardImpl) greatestKingdomOfMyPeople); + + passUntil(Phase.MANEUVER); + + selectCardAction(P1, slakedThirsts); + assertEquals(2, getWounds(urukSavage)); + assertEquals(Zone.DISCARD, slakedThirsts.getZone()); + } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/PlayCardInOtherPhaseAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/PlayCardInOtherPhaseAtTest.java new file mode 100644 index 000000000..522e2bf6f --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/PlayCardInOtherPhaseAtTest.java @@ -0,0 +1,41 @@ +package com.gempukku.lotro.at.effects; + +import com.gempukku.lotro.at.AbstractAtTest; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Zone; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class PlayCardInOtherPhaseAtTest extends AbstractAtTest { + @Test + public void playErkenbrandDuringSkirmish() throws DecisionResultInvalidException, CardNotFoundException { + initializeSimplestGame(); + + PhysicalCard erkebrand = addToZone(createCard(P1, "0_59"), Zone.HAND); + PhysicalCard soldierOfEdoras = addToZone(createCard(P1, "4_262"), Zone.SUPPORT); + + PhysicalCard gimli = addToZone(createCard(P1, "5_7"), Zone.FREE_CHARACTERS); + PhysicalCard goblinRunner = addToZone(createCard(P2, "1_178"), Zone.SHADOW_CHARACTERS); + + passUntil(Phase.FELLOWSHIP); + + assertNotNull(getCardActionId(P1, erkebrand)); + + passUntil(Phase.ASSIGNMENT); + + // Assign + pass(P1); + pass(P2); + playerDecided(P1, gimli.getCardId() + " " + goblinRunner.getCardId()); + + // Start skirmish + playerDecided(P1, String.valueOf(gimli.getCardId())); + selectCardAction(P1, erkebrand); + assertEquals(Zone.FREE_CHARACTERS, erkebrand.getZone()); + } +}