diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/set101_dwarven_playtest.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/set101_dwarven_playtest.json index 082890cf0..a3c617084 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/set101_dwarven_playtest.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/set101_dwarven_playtest.json @@ -17,18 +17,18 @@ "type": "location", "filter": "siteBlock(fellowship),or(siteNumber(4),siteNumber(5),siteNumber(6),siteNumber(7),siteNumber(8))" }, - "filter": "dwarf,hasAttachedCount(2,or(possession,artifact))" + "filter": "dwarf,hasAttachedCount(2,or(item))" } }, { "type": "trigger", "optional": true, "trigger": { - "type": "moves", + "type": "moves" }, "condition": { "type": "canSpot", - "filter": "dwarf,hasAttachedCount(2,or(possession,artifact))" + "filter": "dwarf,hasAttachedCount(2,item)" }, "effect": { "type": "drawCards", @@ -47,24 +47,22 @@ "support area" ], "effects": [ - { - "type": "extraCost", - "cost": { - "type": "exert", - "filter": "choose(dwarf)" - } - }, { "type": "trigger", + "optional": true, "trigger": { - "type": "played", - "filter": "orc", - "memorize": "playedOrc" + "type": "discardfromdeck", + "filter": "your,culture(dwarven)", + "memorize": "topcard" + }, + "cost":{ + "type": "addTwilight", + "amount": 2 }, "effect": { - "type": "discardTopCardsFromDeck", - "forced": true, - "deck": "ownerFromMemory(playedOrc)" + "type": "stackcardsfromdiscard", + "where": "self", + "filter": "memory(topcard)" } } ] diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java index ffc69626e..79d5f0940 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java @@ -37,6 +37,7 @@ public class FilterFactory { simpleFilters.put("character", (actionContext) -> Filters.character); simpleFilters.put("mounted", (actionContext) -> Filters.mounted); simpleFilters.put("weapon", (actionContext) -> Filters.weapon); + simpleFilters.put("item", (actionContext) -> Filters.item); simpleFilters.put("wounded", (actionContext) -> Filters.wounded); simpleFilters.put("unwounded", (actionContext) -> Filters.unwounded); simpleFilters.put("exhausted", (actionContext) -> Filters.exhausted); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/DiscardFromDeck.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/DiscardFromDeck.java new file mode 100644 index 000000000..49de853d9 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/DiscardFromDeck.java @@ -0,0 +1,36 @@ +package com.gempukku.lotro.cards.build.field.effect.trigger; + +import com.gempukku.lotro.cards.build.*; +import com.gempukku.lotro.cards.build.field.FieldUtils; +import com.gempukku.lotro.logic.timing.TriggerConditions; +import com.gempukku.lotro.logic.timing.results.DiscardCardFromDeckResult; +import org.json.simple.JSONObject; + +public class DiscardFromDeck 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) { + boolean result = TriggerConditions.forEachDiscardedFromDeck(actionContext.getGame(), actionContext.getEffectResult(), + filterableSource.getFilterable(actionContext)); + if (result && memorize != null) { + actionContext.setCardMemory(memorize, ((DiscardCardFromDeckResult) actionContext.getEffectResult()).getDiscardedCard()); + } + return result; + } + }; + } +} 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 2b4e69dc9..2789138e2 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 @@ -37,6 +37,7 @@ public class TriggerCheckerFactory { triggerCheckers.put("exerts", new Exerts()); triggerCheckers.put("discarded", new Discarded()); triggerCheckers.put("discardfromhand", new DiscardFromHand()); + triggerCheckers.put("discardfromdeck", new DiscardFromDeck()); triggerCheckers.put("putsonring", new PutsOnRing()); triggerCheckers.put("addsburden", new AddsBurden()); triggerCheckers.put("removesburden", new RemovesBurden()); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java index 3737963f4..51605efea 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java @@ -410,6 +410,7 @@ public class Filters { public static final Filter galadriel = Filters.name("Galadriel"); public static final Filter weapon = Filters.or(PossessionClass.HAND_WEAPON, PossessionClass.RANGED_WEAPON); + public static final Filter item = Filters.or(CardType.ARTIFACT, CardType.POSSESSION); public static final Filter character = Filters.or(CardType.ALLY, CardType.COMPANION, CardType.MINION); public static final Filter ringBearer = new Filter() { diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/DiscardTopCardFromDeckEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/DiscardTopCardFromDeckEffect.java index 9b6def2e9..97ae0971f 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/DiscardTopCardFromDeckEffect.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/DiscardTopCardFromDeckEffect.java @@ -6,6 +6,8 @@ import com.gempukku.lotro.game.state.GameState; import com.gempukku.lotro.game.state.LotroGame; import com.gempukku.lotro.logic.timing.AbstractEffect; import com.gempukku.lotro.logic.timing.Effect; +import com.gempukku.lotro.logic.timing.results.DiscardCardFromDeckResult; +import com.gempukku.lotro.logic.timing.results.DiscardCardFromPlayResult; import java.util.Collection; import java.util.LinkedList; @@ -61,6 +63,9 @@ public class DiscardTopCardFromDeckEffect extends AbstractEffect { cardsDiscardedCallback(cardsDiscarded); } + for (PhysicalCard discardedCard : cardsDiscarded)//PhysicalCard source, PhysicalCard card, String handPlayerId, boolean forced + game.getActionsEnvironment().emitEffectResult(new DiscardCardFromDeckResult(_source, discardedCard, _forced)); + return new FullEffectResult(_count == cardsDiscarded.size()); } return new FullEffectResult(false); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/EffectResult.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/EffectResult.java index 6f942188e..b176a0ece 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/EffectResult.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/EffectResult.java @@ -15,6 +15,7 @@ public abstract class EffectResult { FOR_EACH_RETURNED_TO_HAND, FOR_EACH_DISCARDED_FROM_HAND, + FOR_EACH_DISCARDED_FROM_DECK, FREE_PEOPLE_PLAYER_STARTS_ASSIGNING, SKIRMISH_ABOUT_TO_END, diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java index a89701c00..bbf8eb942 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java @@ -197,6 +197,12 @@ public class TriggerConditions { return false; } + public static boolean forEachDiscardedFromDeck(LotroGame game, EffectResult effectResult, Filterable... filters) { + if (effectResult.getType() == EffectResult.Type.FOR_EACH_DISCARDED_FROM_DECK) + return Filters.and(filters).accepts(game, ((DiscardCardFromDeckResult) effectResult).getDiscardedCard()); + return false; + } + public static boolean forEachWounded(LotroGame game, EffectResult effectResult, Filterable... filters) { if (effectResult.getType() == EffectResult.Type.FOR_EACH_WOUNDED) return Filters.and(filters).accepts(game, ((WoundResult) effectResult).getWoundedCard()); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/results/DiscardCardFromDeckResult.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/results/DiscardCardFromDeckResult.java new file mode 100644 index 000000000..930ebac3a --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/results/DiscardCardFromDeckResult.java @@ -0,0 +1,30 @@ +package com.gempukku.lotro.logic.timing.results; + +import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.logic.timing.EffectResult; + +public class DiscardCardFromDeckResult extends EffectResult { + private PhysicalCard _source; + private PhysicalCard _card; + private boolean _forced; + + public DiscardCardFromDeckResult(PhysicalCard source, PhysicalCard card, boolean forced) { + super(Type.FOR_EACH_DISCARDED_FROM_DECK); + _source = source; + _card = card; + _forced = forced; + } + + public PhysicalCard getSource() { + return _source; + } + + public boolean isForced() { + return _forced; + } + + + public PhysicalCard getDiscardedCard() { + return _card; + } +} \ No newline at end of file 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 d00444cd3..8410ce9f3 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 @@ -238,6 +238,9 @@ public class GenericCardTestHelper extends AbstractAtTest { public void AttachCard(PhysicalCardImpl card, PhysicalCardImpl bearer) { _game.getGameState().attachCard(_game, card, bearer); } + public void AttachCardsTo(PhysicalCardImpl holder, PhysicalCardImpl...cards) { + Arrays.stream(cards).forEach(card -> _game.getGameState().attachCard(_game, card, holder)); + } public void FreepsMoveCardToDeck(String...cardNames) { Arrays.stream(cardNames).forEach(cardName -> FreepsMoveCardToDeck(GetFreepsCard(cardName))); @@ -270,15 +273,17 @@ public class GenericCardTestHelper extends AbstractAtTest { Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.SUPPORT)); } - public void FreepsMoveCardToDiscard(String cardName) { FreepsMoveCardToSupportArea(GetFreepsCard(cardName)); } + public void FreepsMoveCardToDiscard(String cardName) { FreepsMoveCardToDiscard(GetFreepsCard(cardName)); } public void FreepsMoveCardToDiscard(PhysicalCardImpl...cards) { Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.DISCARD)); } - public void ShadowMoveCardToDiscard(String cardName) { ShadowMoveCardToSupportArea(GetShadowCard(cardName)); } + public void ShadowMoveCardToDiscard(String cardName) { ShadowMoveCardToDiscard(GetShadowCard(cardName)); } public void ShadowMoveCardToDiscard(PhysicalCardImpl...cards) { Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.DISCARD)); } + + public void MoveCardToZone(String player, PhysicalCardImpl card, Zone zone) { if(card.getZone() != null) { @@ -428,6 +433,7 @@ public class GenericCardTestHelper extends AbstractAtTest { public void FreepsChoose(String choice) throws DecisionResultInvalidException { playerDecided(P1, choice); } public void ShadowChoose(String choice) throws DecisionResultInvalidException { playerDecided(P2, choice); } + public void FreepsChooseToMove() throws DecisionResultInvalidException { playerDecided(P1, "0"); } public void FreepsChooseToStay() throws DecisionResultInvalidException { playerDecided(P1, "1"); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java index 3188125b9..907d22231 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java @@ -41,7 +41,7 @@ public class Card_V1_001Tests /** * Set: VSet1, VPack1 - * Title: Hospitality of the Dwarves + * Title: *Hospitality of the Dwarves * Side: Free Peoples * Culture: Dwarven * Twilight Cost: 1 diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java index 702475e33..048363432 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java @@ -20,12 +20,15 @@ public class Card_V1_002Tests return new GenericCardTestHelper( new HashMap() {{ - put("aragorn", "1_89"); - put("boromir", "1_97"); - put("whitecity", "101_2"); + put("gimli", "1_13"); + put("axe", "1_9"); + put("axe2", "1_9"); + put("deep", "151_2"); + put("beneath", "2_1"); + + put("runner", "1_178"); + put("plunder", "1_193"); - put("attea", "1_229"); - put("cantea", "1_230"); }} ); } @@ -36,14 +39,14 @@ public class Card_V1_002Tests /** * Set: VSet1, VPack1 - * Title: *I Will Not Let the White City Fall + * Title: *Deepest Delvings * Side: Free Peoples - * Culture: Gondor - * Twilight Cost: 2 + * Culture: Dwarven + * Twilight Cost: 1 * Type: Condition * Subtype: Support Area - * Game Text: Each time Boromir loses a skirmish, make Aragorn strength +2 until the regroup phase. - * Each time Aragorn loses a skirmish, make Boromir strength +2 until the regroup phase. + * Game Text: Each time you discard a [dwarven] card from the top of your deck you may add (1) to stack that card here. + * Maneuver: Exert a dwarf to take a card stacked here into hand. */ //Pre-game setup @@ -57,68 +60,26 @@ public class Card_V1_002Tests } @Test - public void OneIsBuffedWhenOtherLosesSkirmish() throws DecisionResultInvalidException, CardNotFoundException { + public void topdecktest() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); - PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); - PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); - PhysicalCardImpl whitecity = scn.GetFreepsCard("whitecity"); - - scn.FreepsMoveCharToTable(aragorn); - scn.FreepsMoveCharToTable(boromir); - scn.FreepsMoveCardToHand(whitecity); - - PhysicalCardImpl cantea = scn.GetShadowCard("cantea"); - PhysicalCardImpl attea = scn.GetShadowCard("attea"); - scn.ShadowMoveCharToTable(cantea, attea); + PhysicalCardImpl beneath = scn.GetFreepsCard("beneath"); + PhysicalCardImpl deep = scn.GetFreepsCard("deep"); + scn.FreepsMoveCardToSupportArea(beneath); + scn.FreepsMoveCardToSupportArea(deep); + scn.FreepsMoveCharToTable("gimli"); + scn.FreepsMoveCardToDiscard("axe"); scn.StartGame(); - scn.FreepsPlayCard(whitecity); + + scn.FreepsUseCardAction(beneath); + + scn.SkipToPhase(Phase.ASSIGNMENT); - - assertEquals(7, scn.GetStrength(boromir)); - assertEquals(8, scn.GetStrength(aragorn)); - scn.SkipCurrentPhaseActions(); - //Standard assignment - scn.FreepsAssignToMinions(new PhysicalCardImpl[] { aragorn, cantea}, new PhysicalCardImpl[] { boromir, attea}); - scn.FreepsResolveSkirmish(aragorn); - scn.SkipCurrentPhaseActions(); - scn.FreepsAcceptOptionalTrigger(); //Have to resolve the skirmish and the condition trigger - // 14 > 8, Aragorn lost, Boromir should be buffed - assertEquals(9, scn.GetStrength(boromir)); - assertEquals(8, scn.GetStrength(aragorn)); - - scn.FreepsResolveSkirmish(boromir); - scn.SkipCurrentPhaseActions(); - scn.FreepsAcceptOptionalTrigger(); //Have to resolve the skirmish and the condition trigger - // 12 > 9, Boromir lost, Aragorn should be buffed - assertEquals(9, scn.GetStrength(boromir)); - assertEquals(10, scn.GetStrength(aragorn)); - - //Fierce assignment - scn.FreepsSkipCurrentPhaseAction(); - scn.ShadowSkipCurrentPhaseAction(); - - scn.FreepsAssignToMinions(new PhysicalCardImpl[] { aragorn, cantea}, new PhysicalCardImpl[] { boromir, attea}); - scn.FreepsResolveSkirmish(boromir); - scn.SkipCurrentPhaseActions(); - scn.FreepsAcceptOptionalTrigger(); //Have to resolve the skirmish and the condition trigger - // 10 > 9, Boromir lost again, Aragorn should be buffed again - assertEquals(9, scn.GetStrength(boromir)); - assertEquals(12, scn.GetStrength(aragorn)); - - scn.FreepsResolveSkirmish(aragorn); - //Aragorn now wins his skirmish, so there's no loss trigger to evaluate - - scn.SkipToPhase(Phase.REGROUP); - - //strength should be back to normal - assertEquals(7, scn.GetStrength(boromir)); - assertEquals(8, scn.GetStrength(aragorn)); }