diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set11/set11-site.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set11/set11-site.json new file mode 100644 index 000000000..a51547276 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set11/set11-site.json @@ -0,0 +1,24 @@ +{ + + "11_235": { + "title": "Dammed Gate-stream", + "type": "site", + "block": "Shadows", + "cost": 3, + "keyword": "Marsh", + "direction": "right", + "effects": { + "type": "trigger", + "trigger": { + "type": "startOfPhase", + "phase": "fellowship" + }, + "optional": true, + "effect": { + "type": "playCardFromDrawDeck", + "filter": "choose(culture(gollum),side(free peoples))" + } + } + }, + +} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/includes/changeLog.html b/gemp-lotr/gemp-lotr-async/src/main/web/includes/changeLog.html index 33a4f44f3..6b6ac8cf8 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/includes/changeLog.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/includes/changeLog.html @@ -1,12 +1,18 @@
Most recent update
+2022 August 04
+- New players now have all of the library decks in the main hall to use for matches, which persist until they make their first deck.
+- Adjusted the canonical ordering of formats and decks to keep the 3 most-used formats at the top, and the rest in chronological order
+- Fixed Dammed Gate-stream (11U235) causing a crash by selecting a Response event.
+- Due to the above, if you see any issues with playing Response events in general, please let us know ASAP
+
2022 August 03
- Added Library Decks, which are a shared set of decks that anyone can load (tho not save or edit)
- Added all starter decks and as many Worlds championship 1/2 decks that we could find to the Library
- Improved the format listings so that all formats are sorted according to chronological order, rather than alphabetical.
- Added ability to rename decks while on the deck selection window
-- New players now have all of the library decks in the main hall, which persist until they make their first deck.
+
2022 August 02
- Fixed each card draw pausing between cards
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set11/site/Card11_235.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set11/site/Card11_235.java
deleted file mode 100644
index daccecd89..000000000
--- a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set11/site/Card11_235.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.gempukku.lotro.cards.set11.site;
-
-import com.gempukku.lotro.logic.cardtype.AbstractShadowsSite;
-import com.gempukku.lotro.logic.timing.TriggerConditions;
-import com.gempukku.lotro.logic.effects.choose.ChooseAndPlayCardFromDeckEffect;
-import com.gempukku.lotro.common.Culture;
-import com.gempukku.lotro.common.Keyword;
-import com.gempukku.lotro.common.Phase;
-import com.gempukku.lotro.common.Side;
-import com.gempukku.lotro.game.PhysicalCard;
-import com.gempukku.lotro.game.state.LotroGame;
-import com.gempukku.lotro.logic.actions.OptionalTriggerAction;
-import com.gempukku.lotro.logic.timing.EffectResult;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Set: Shadows
- * Twilight Cost: 3
- * Type: Site
- * Game Text: Marsh. At the start of your fellowship phase, you may play a [GOLLUM] Free Peoples card from your draw
- * deck.
- */
-public class Card11_235 extends AbstractShadowsSite {
- public Card11_235() {
- super("Dammed Gate-stream", 3, Direction.RIGHT);
- addKeyword(Keyword.MARSH);
- }
-
- @Override
- public List getOptionalAfterTriggers(String playerId, LotroGame game, EffectResult effectResult, PhysicalCard self) {
- if (TriggerConditions.startOfPhase(game, effectResult, Phase.FELLOWSHIP)
- && playerId.equals(game.getGameState().getCurrentPlayerId())) {
- OptionalTriggerAction action = new OptionalTriggerAction(self);
- action.appendEffect(
- new ChooseAndPlayCardFromDeckEffect(playerId, Culture.GOLLUM, Side.FREE_PEOPLE));
- return Collections.singletonList(action);
- }
- return null;
- }
-}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/BuiltLotroCardBlueprint.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/BuiltLotroCardBlueprint.java
index 4367c5a7a..fd02958fc 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/BuiltLotroCardBlueprint.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/BuiltLotroCardBlueprint.java
@@ -802,7 +802,7 @@ public class BuiltLotroCardBlueprint implements LotroCardBlueprint {
for (Requirement playInOtherPhaseCondition : playInOtherPhaseConditions) {
DefaultActionContext actionContext = new DefaultActionContext(playerId, game, self, null, null);
if (playInOtherPhaseCondition.accepts(actionContext)
- && PlayUtils.checkPlayRequirements(game, self, Filters.any, 0, 0, false, false))
+ && PlayUtils.checkPlayRequirements(game, self, Filters.any, 0, 0, false, false, false))
playCardActions.add(PlayUtils.getPlayCardAction(game, self, 0, Filters.any, false));
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromDiscard.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromDiscard.java
index dc130ff2b..f858c6cdb 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromDiscard.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromDiscard.java
@@ -64,10 +64,10 @@ public class PlayCardFromDiscard implements EffectAppenderProducer {
final int costModifier = costModifierSource.getEvaluator(actionContext).evaluateExpression(game, actionContext.getSource());
if (onFilterableSource != null) {
final Filterable onFilterable = onFilterableSource.getFilterable(actionContext);
- return Filters.and(Filters.playable(actionContext.getGame(), removedTwilight, costModifier, false, false), ExtraFilters.attachableTo(actionContext.getGame(), onFilterable));
+ return Filters.and(Filters.playable(actionContext.getGame(), removedTwilight, costModifier, false, false, true), ExtraFilters.attachableTo(actionContext.getGame(), onFilterable));
}
- return Filters.playable(actionContext.getGame(), removedTwilight, costModifier, false, false);
+ return Filters.playable(actionContext.getGame(), removedTwilight, costModifier, false, false, true);
},
countSource, memorize, "you", "Choose card to play", environment));
result.addEffectAppender(
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromDrawDeck.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromDrawDeck.java
index 7e0c8e7b1..5421191ae 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromDrawDeck.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromDrawDeck.java
@@ -56,7 +56,7 @@ public class PlayCardFromDrawDeck implements EffectAppenderProducer {
final Filterable onFilterable = onFilterableSource.getFilterable(actionContext);
return Filters.and(Filters.playable(game, costModifier), ExtraFilters.attachableTo(game, onFilterable));
}
- return Filters.playable(actionContext.getGame(), costModifier);
+ return Filters.playable(actionContext.getGame(), costModifier, false, false, true);
},
countSource, memorize, "you", "you", "Choose card to play", environment));
result.addEffectAppender(
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromStacked.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromStacked.java
index 8d48dbf52..cdb53d70f 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromStacked.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromStacked.java
@@ -44,7 +44,7 @@ public class PlayCardFromStacked implements EffectAppenderProducer {
result.addEffectAppender(
CardResolver.resolveStackedCards(filter,
actionContext -> Filters.playable(actionContext.getGame()),
- actionContext -> Filters.playable(actionContext.getGame(), removedTwilight, 0, false, false),
+ actionContext -> Filters.playable(actionContext.getGame(), removedTwilight, 0, false, false, true),
countSource, onFilterableSource, "_temp", "you", "Choose card to play", environment));
result.addEffectAppender(
new DelayedAppender() {
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/CanPlayStackedCards.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/CanPlayStackedCards.java
index 18e275481..1f09acb30 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/CanPlayStackedCards.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/CanPlayStackedCards.java
@@ -36,7 +36,7 @@ public class CanPlayStackedCards implements ModifierSourceProducer {
new RequirementCondition(requirements, actionContext), ModifierEffect.EXTRA_ACTION_MODIFIER) {
@Override
public List extends Action> getExtraPhaseActionFromStacked(LotroGame game, PhysicalCard card) {
- if (PlayUtils.checkPlayRequirements(game, card, Filters.any, 0, 0, false, false))
+ if (PlayUtils.checkPlayRequirements(game, card, Filters.any, 0, 0, false, false, false))
return Collections.singletonList(
PlayUtils.getPlayCardAction(game, card, 0, Filters.any, false));
return null;
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 2a647e8f0..06445e0fd 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
@@ -589,10 +589,14 @@ public class Filters {
}
public static Filter playable(final LotroGame game, final int twilightModifier, final boolean ignoreRoamingPenalty, final boolean ignoreCheckingDeadPile) {
- return playable(game, 0, twilightModifier, ignoreRoamingPenalty, ignoreCheckingDeadPile);
+ return playable(game, 0, twilightModifier, ignoreRoamingPenalty, ignoreCheckingDeadPile, false);
}
- public static Filter playable(final LotroGame game, final int withTwilightRemoved, final int twilightModifier, final boolean ignoreRoamingPenalty, final boolean ignoreCheckingDeadPile) {
+ public static Filter playable(final LotroGame game, final int twilightModifier, final boolean ignoreRoamingPenalty, final boolean ignoreCheckingDeadPile, final boolean ignoreResponseEvents) {
+ return playable(game, 0, twilightModifier, ignoreRoamingPenalty, ignoreCheckingDeadPile, ignoreResponseEvents);
+ }
+
+ public static Filter playable(final LotroGame game, final int withTwilightRemoved, final int twilightModifier, final boolean ignoreRoamingPenalty, final boolean ignoreCheckingDeadPile, final boolean ignoreResponseEvents) {
return new Filter() {
@Override
public boolean accepts(LotroGame game, PhysicalCard physicalCard) {
@@ -601,7 +605,7 @@ public class Filters {
if (blueprint.getSide() != expectedSide)
return false;
- return PlayUtils.checkPlayRequirements(game, physicalCard, Filters.any, withTwilightRemoved, twilightModifier, ignoreRoamingPenalty, ignoreCheckingDeadPile);
+ return PlayUtils.checkPlayRequirements(game, physicalCard, Filters.any, withTwilightRemoved, twilightModifier, ignoreRoamingPenalty, ignoreCheckingDeadPile, ignoreResponseEvents);
}
};
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/PlayUtils.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/PlayUtils.java
index 7f91e5c59..e1f2fe456 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/PlayUtils.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/PlayUtils.java
@@ -1,20 +1,25 @@
package com.gempukku.lotro.logic;
-import com.gempukku.lotro.common.CardType;
-import com.gempukku.lotro.common.Filterable;
-import com.gempukku.lotro.common.Side;
-import com.gempukku.lotro.common.Zone;
+import com.gempukku.lotro.common.*;
import com.gempukku.lotro.filters.Filter;
import com.gempukku.lotro.filters.Filters;
import com.gempukku.lotro.game.LotroCardBlueprint;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.game.state.LotroGame;
+import com.gempukku.lotro.game.state.actions.DefaultActionsEnvironment;
import com.gempukku.lotro.logic.actions.AttachPermanentAction;
import com.gempukku.lotro.logic.actions.CostToEffectAction;
import com.gempukku.lotro.logic.actions.PlayEventAction;
import com.gempukku.lotro.logic.actions.PlayPermanentAction;
+import com.gempukku.lotro.logic.timing.Action;
import com.gempukku.lotro.logic.timing.PlayConditions;
import com.gempukku.lotro.logic.timing.RuleUtils;
+import com.google.common.collect.ImmutableMap;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
public class PlayUtils {
private static Zone getPlayToZone(PhysicalCard card) {
@@ -29,6 +34,27 @@ public class PlayUtils {
}
}
+ public static Map PhaseKeywordMap = ImmutableMap.copyOf(new HashMap() {{
+ put(Phase.FELLOWSHIP, Keyword.FELLOWSHIP);
+ put(Phase.SHADOW, Keyword.SHADOW);
+ put(Phase.MANEUVER, Keyword.MANEUVER);
+ put(Phase.ARCHERY, Keyword.ARCHERY);
+ put(Phase.ASSIGNMENT, Keyword.ASSIGNMENT);
+ put(Phase.SKIRMISH, Keyword.SKIRMISH);
+ put(Phase.REGROUP, Keyword.REGROUP);
+ }});
+
+// static {
+// phaseKeywordMap = new HashMap<>();
+// phaseKeywordMap.put(Phase.FELLOWSHIP, Keyword.FELLOWSHIP);
+// phaseKeywordMap.put(Phase.SHADOW, Keyword.SHADOW);
+// phaseKeywordMap.put(Phase.MANEUVER, Keyword.MANEUVER);
+// phaseKeywordMap.put(Phase.ARCHERY, Keyword.ARCHERY);
+// phaseKeywordMap.put(Phase.ASSIGNMENT, Keyword.ASSIGNMENT);
+// phaseKeywordMap.put(Phase.SKIRMISH, Keyword.SKIRMISH);
+// phaseKeywordMap.put(Phase.REGROUP, Keyword.REGROUP);
+// }
+
private static Filter getFullAttachValidTargetFilter(final LotroGame game, final PhysicalCard card, int twilightModifier, int withTwilightRemoved) {
return Filters.and(RuleUtils.getFullValidTargetFilter(card.getOwner(), game, card),
@@ -84,6 +110,10 @@ public class PlayUtils {
}
public static boolean checkPlayRequirements(LotroGame game, PhysicalCard card, Filterable additionalAttachmentFilter, int withTwilightRemoved, int twilightModifier, boolean ignoreRoamingPenalty, boolean ignoreCheckingDeadPile) {
+ return checkPlayRequirements(game, card, additionalAttachmentFilter, withTwilightRemoved, twilightModifier, ignoreRoamingPenalty, ignoreCheckingDeadPile, false);
+ }
+
+ public static boolean checkPlayRequirements(LotroGame game, PhysicalCard card, Filterable additionalAttachmentFilter, int withTwilightRemoved, int twilightModifier, boolean ignoreRoamingPenalty, boolean ignoreCheckingDeadPile, boolean ignoreResponseEvents) {
final LotroCardBlueprint blueprint = card.getBlueprint();
// Check if card's own play requirements are met
@@ -113,9 +143,22 @@ public class PlayUtils {
return false;
if (blueprint.getCardType() == CardType.COMPANION
- && !(PlayConditions.checkRuleOfNine(game, card) && PlayConditions.checkPlayRingBearer(game, card)))
+ && !(PlayConditions.checkRuleOfNine(game, card) && PlayConditions.checkPlayRingBearer(game, card)))
return false;
+ if(blueprint.getCardType() == CardType.EVENT)
+ {
+ if(game.getModifiersQuerying().hasKeyword(game, card, Keyword.RESPONSE)) {
+ if (ignoreResponseEvents)
+ return false;
+ }
+ else {
+ final Keyword phaseKeyword = PhaseKeywordMap.get(game.getGameState().getCurrentPhase());
+ if (phaseKeyword != null && !game.getModifiersQuerying().hasKeyword(game, card, phaseKeyword))
+ return false;
+ }
+ }
+
return (blueprint.getSide() != Side.SHADOW || PlayConditions.canPayForShadowCard(game, card, finalTargetFilter, withTwilightRemoved, twilightModifier, ignoreRoamingPenalty));
}
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/ExtraFilters.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/ExtraFilters.java
index 97b8e6a76..2f3a11d18 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/ExtraFilters.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/ExtraFilters.java
@@ -19,7 +19,7 @@ public class ExtraFilters {
public boolean accepts(LotroGame game, PhysicalCard physicalCard) {
if (physicalCard.getBlueprint().getValidTargetFilter(physicalCard.getOwner(), game, physicalCard) == null)
return false;
- return PlayUtils.checkPlayRequirements(game, physicalCard, Filters.and(filters), 0, twilightModifier, false, false);
+ return PlayUtils.checkPlayRequirements(game, physicalCard, Filters.and(filters), 0, twilightModifier, false, false, true);
}
});
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/PlayConditions.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/PlayConditions.java
index 0d226bb36..a194179db 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/PlayConditions.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/PlayConditions.java
@@ -327,7 +327,7 @@ public class PlayConditions {
}
public static boolean canPlayFromHand(String playerId, LotroGame game, int withTwilightRemoved, int twilightModifier, boolean ignoreRoamingPenalty, boolean ignoreCheckingDeadPile, Filterable... filters) {
- return Filters.filter(game.getGameState().getHand(playerId), game, Filters.and(filters, Filters.playable(game, withTwilightRemoved, twilightModifier, ignoreRoamingPenalty, ignoreCheckingDeadPile))).size() > 0;
+ return Filters.filter(game.getGameState().getHand(playerId), game, Filters.and(filters, Filters.playable(game, withTwilightRemoved, twilightModifier, ignoreRoamingPenalty, ignoreCheckingDeadPile, false))).size() > 0;
}
public static boolean canPlayFromDeadPile(String playerId, LotroGame game, Filterable... filters) {
@@ -347,7 +347,7 @@ public class PlayConditions {
public static boolean canPlayFromStacked(String playerId, LotroGame game, int withTwilightRemoved, Filterable stackedOn, Filterable... filters) {
final Collection matchingStackedOn = Filters.filterActive(game, stackedOn);
for (PhysicalCard stackedOnCard : matchingStackedOn) {
- if (Filters.filter(game.getGameState().getStackedCards(stackedOnCard), game, Filters.and(filters, Filters.playable(game, withTwilightRemoved, 0, false, false))).size() > 0)
+ if (Filters.filter(game.getGameState().getStackedCards(stackedOnCard), game, Filters.and(filters, Filters.playable(game, withTwilightRemoved, 0, false, false, false))).size() > 0)
return true;
}
@@ -357,7 +357,7 @@ public class PlayConditions {
public static boolean canPlayFromStacked(String playerId, LotroGame game, int withTwilightRemoved, int twilightModifier, Filterable stackedOn, Filterable... filters) {
final Collection matchingStackedOn = Filters.filterActive(game, stackedOn);
for (PhysicalCard stackedOnCard : matchingStackedOn) {
- if (Filters.filter(game.getGameState().getStackedCards(stackedOnCard), game, Filters.and(filters, Filters.playable(game, withTwilightRemoved, twilightModifier, false, false))).size() > 0)
+ if (Filters.filter(game.getGameState().getStackedCards(stackedOnCard), game, Filters.and(filters, Filters.playable(game, withTwilightRemoved, twilightModifier, false, false, false))).size() > 0)
return true;
}
@@ -379,7 +379,7 @@ public class PlayConditions {
public static boolean canPlayFromDiscard(String playerId, LotroGame game, int withTwilightRemoved, int modifier, Filterable... filters) {
if (game.getModifiersQuerying().hasFlagActive(game, ModifierFlag.CANT_PLAY_FROM_DISCARD_OR_DECK))
return false;
- return Filters.filter(game.getGameState().getDiscard(playerId), game, Filters.and(filters, Filters.playable(game, withTwilightRemoved, modifier, false, false))).size() > 0;
+ return Filters.filter(game.getGameState().getDiscard(playerId), game, Filters.and(filters, Filters.playable(game, withTwilightRemoved, modifier, false, false, false))).size() > 0;
}
public static boolean canDiscardFromPlay(final PhysicalCard source, LotroGame game, final PhysicalCard card) {
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/pregame/PlayerPlaysStartingFellowshipGameProcess.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/pregame/PlayerPlaysStartingFellowshipGameProcess.java
index 12e592913..8ddd2c2c0 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/pregame/PlayerPlaysStartingFellowshipGameProcess.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/pregame/PlayerPlaysStartingFellowshipGameProcess.java
@@ -46,7 +46,7 @@ public class PlayerPlaysStartingFellowshipGameProcess implements GameProcess {
public boolean accepts(LotroGame game, PhysicalCard physicalCard) {
int twilightCost = game.getModifiersQuerying().getTwilightCost(game, physicalCard, null, 0, false);
return game.getGameState().getTwilightPool() + twilightCost <= 4
- && PlayUtils.checkPlayRequirements(game, physicalCard, Filters.any, 0, 0, false, false);
+ && PlayUtils.checkPlayRequirements(game, physicalCard, Filters.any, 0, 0, false, false, true);
}
});
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/PlayCardInPhaseRule.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/PlayCardInPhaseRule.java
index 3ece27502..d6cff60f0 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/PlayCardInPhaseRule.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/PlayCardInPhaseRule.java
@@ -19,19 +19,9 @@ import java.util.List;
public class PlayCardInPhaseRule {
private DefaultActionsEnvironment actionsEnvironment;
- private final HashMap phaseKeywordMap;
public PlayCardInPhaseRule(DefaultActionsEnvironment actionsEnvironment) {
this.actionsEnvironment = actionsEnvironment;
-
- phaseKeywordMap = new HashMap<>();
- phaseKeywordMap.put(Phase.FELLOWSHIP, Keyword.FELLOWSHIP);
- phaseKeywordMap.put(Phase.SHADOW, Keyword.SHADOW);
- phaseKeywordMap.put(Phase.MANEUVER, Keyword.MANEUVER);
- phaseKeywordMap.put(Phase.ARCHERY, Keyword.ARCHERY);
- phaseKeywordMap.put(Phase.ASSIGNMENT, Keyword.ASSIGNMENT);
- phaseKeywordMap.put(Phase.SKIRMISH, Keyword.SKIRMISH);
- phaseKeywordMap.put(Phase.REGROUP, Keyword.REGROUP);
}
public void applyRule() {
@@ -46,7 +36,7 @@ public class PlayCardInPhaseRule {
List result = new LinkedList<>();
for (PhysicalCard card : Filters.filter(game.getGameState().getHand(playerId), game, side,
Filters.or(Filters.and(CardType.EVENT, Keyword.FELLOWSHIP), Filters.not(CardType.EVENT)))) {
- if (PlayUtils.checkPlayRequirements(game, card, Filters.any, 0, 0, false, false))
+ if (PlayUtils.checkPlayRequirements(game, card, Filters.any, 0, 0, false, false, true))
result.add(PlayUtils.getPlayCardAction(game, card, 0, Filters.any, false));
}
return result;
@@ -56,18 +46,18 @@ public class PlayCardInPhaseRule {
List result = new LinkedList<>();
for (PhysicalCard card : Filters.filter(game.getGameState().getHand(playerId), game, side,
Filters.or(Filters.and(CardType.EVENT, Keyword.SHADOW), Filters.not(CardType.EVENT)))) {
- if (PlayUtils.checkPlayRequirements(game, card, Filters.any, 0, 0, false, false))
+ if (PlayUtils.checkPlayRequirements(game, card, Filters.any, 0, 0, false, false, true))
result.add(PlayUtils.getPlayCardAction(game, card, 0, Filters.any, false));
}
return result;
}
} else {
- final Keyword phaseKeyword = phaseKeywordMap.get(game.getGameState().getCurrentPhase());
+ final Keyword phaseKeyword = PlayUtils.PhaseKeywordMap.get(game.getGameState().getCurrentPhase());
if (phaseKeyword != null) {
List result = new LinkedList<>();
for (PhysicalCard card : Filters.filter(game.getGameState().getHand(playerId), game, side,
Filters.and(CardType.EVENT, phaseKeyword))) {
- if (PlayUtils.checkPlayRequirements(game, card, Filters.any, 0, 0, false, false))
+ if (PlayUtils.checkPlayRequirements(game, card, Filters.any, 0, 0, false, false, true))
result.add(PlayUtils.getPlayCardAction(game, card, 0, Filters.any, false));
}
return result;
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/PlayResponseEventRule.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/PlayResponseEventRule.java
index 912e069a8..1b67ee2fb 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/PlayResponseEventRule.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/PlayResponseEventRule.java
@@ -33,7 +33,7 @@ public class PlayResponseEventRule {
List result = new LinkedList<>();
final Side side = GameUtils.getSide(game, playerId);
for (PhysicalCard responseEvent : Filters.filter(game.getGameState().getHand(playerId), game, side, CardType.EVENT, Keyword.RESPONSE)) {
- if (PlayUtils.checkPlayRequirements(game, responseEvent, Filters.any, 0, 0, false, false)) {
+ if (PlayUtils.checkPlayRequirements(game, responseEvent, Filters.any, 0, 0, false, false, false)) {
final List actions = responseEvent.getBlueprint().getPlayResponseEventAfterActions(playerId, game, effectResult, responseEvent);
if (actions != null)
result.addAll(actions);
@@ -47,7 +47,7 @@ public class PlayResponseEventRule {
List result = new LinkedList<>();
final Side side = GameUtils.getSide(game, playerId);
for (PhysicalCard responseEvent : Filters.filter(game.getGameState().getHand(playerId), game, side, CardType.EVENT, Keyword.RESPONSE)) {
- if (PlayUtils.checkPlayRequirements(game, responseEvent, Filters.any, 0, 0, false, false)) {
+ if (PlayUtils.checkPlayRequirements(game, responseEvent, Filters.any, 0, 0, false, false, false)) {
final List actions = responseEvent.getBlueprint().getPlayResponseEventBeforeActions(playerId, game, effect, responseEvent);
if (actions != null)
result.addAll(actions);
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 63a258bfe..8b77b7910 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
@@ -51,10 +51,14 @@ public abstract class AbstractAtTest {
}
protected void initializeGameWithDecks(Map decks) throws DecisionResultInvalidException {
+ initializeGameWithDecks(decks, "multipath");
+ }
+
+ protected void initializeGameWithDecks(Map decks, String formatName) throws DecisionResultInvalidException {
_userFeedback = new DefaultUserFeedback();
LotroFormatLibrary formatLibrary = new LotroFormatLibrary(new DefaultAdventureLibrary(), _library);
- LotroFormat format = formatLibrary.getFormat("multipath");
+ LotroFormat format = formatLibrary.getFormat(formatName);
_game = new DefaultLotroGame(format, decks, _userFeedback, _library);
_userFeedback.setGame(_game);
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 44702fdb3..13be94267 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
@@ -69,14 +69,16 @@ public class GenericCardTestHelper extends AbstractAtTest {
public Map> Cards = new HashMap<>();
public GenericCardTestHelper(HashMap cardIDs) throws CardNotFoundException, DecisionResultInvalidException {
- this(cardIDs, null, null, null);
+ this(cardIDs, null, null, null, "multipath");
}
public GenericCardTestHelper(HashMap cardIDs, HashMap siteIDs, String ringBearerID, String ringID) throws CardNotFoundException, DecisionResultInvalidException {
+ this(cardIDs, siteIDs, ringBearerID, ringID, "multipath");
+ }
+
+ public GenericCardTestHelper(HashMap cardIDs, HashMap siteIDs, String ringBearerID, String ringID, String path) throws CardNotFoundException, DecisionResultInvalidException {
super();
-
-
if(siteIDs == null || ringBearerID == null || ringID == null) {
initializeSimplestGame();
}
@@ -97,7 +99,7 @@ public class GenericCardTestHelper extends AbstractAtTest {
decks.get(P1).setRing(ringID);
decks.get(P2).setRing(ringID);
- initializeGameWithDecks(decks);
+ initializeGameWithDecks(decks, path);
}
Cards.put(P1, new HashMap<>());
@@ -122,6 +124,15 @@ public class GenericCardTestHelper extends AbstractAtTest {
skipMulligans();
}
+ public void SkipStartingFellowships() throws DecisionResultInvalidException {
+ if(FreepsDecisionAvailable("Starting fellowship")) {
+ FreepsChoose("");
+ }
+ if(ShadowDecisionAvailable("Starting fellowship")) {
+ ShadowChoose("");
+ }
+ }
+
public PhysicalCardImpl GetFreepsCard(String cardName) { return Cards.get(P1).get(cardName); }
public PhysicalCardImpl GetShadowCard(String cardName) { return Cards.get(P2).get(cardName); }
public PhysicalCardImpl GetFreepsCardByID(String id) { return GetCardByID(P1, Integer.parseInt(id)); }
@@ -145,6 +156,14 @@ public class GenericCardTestHelper extends AbstractAtTest {
List advDeck = (List)_game.getGameState().getAdventureDeck(playerID);
return advDeck.stream().filter(x -> x.getBlueprint().getSiteNumber() == siteNum).findFirst().get();
}
+ public PhysicalCardImpl GetFreepsSite(String name) { return GetSiteByName(P1, name); }
+ public PhysicalCardImpl GetShadowSite(String name) { return GetSiteByName(P2, name); }
+ public PhysicalCardImpl GetSiteByName(String playerID, String name)
+ {
+ final String lowername = name.toLowerCase();
+ List advDeck = (List)_game.getGameState().getAdventureDeck(playerID);
+ return advDeck.stream().filter(x -> x.getBlueprint().getTitle().toLowerCase().contains(lowername)).findFirst().get();
+ }
public List FreepsGetAvailableActions() { return GetAvailableActions(P1); }
public List ShadowGetAvailableActions() { return GetAvailableActions(P2); }
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set11/Card_11_235_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set11/Card_11_235_Tests.java
new file mode 100644
index 000000000..39af18070
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set11/Card_11_235_Tests.java
@@ -0,0 +1,119 @@
+
+package com.gempukku.lotro.cards.official.set11;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.CardType;
+import com.gempukku.lotro.common.Keyword;
+import com.gempukku.lotro.common.Zone;
+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 junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class Card_11_235_Tests
+{
+
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("dontlook", "6_39");
+ put("smeagol", "7_71");
+ put("boat", "13_48");
+ put("slippery", "6_43");
+ put("clever", "7_54");
+ }},
+ new HashMap() {{
+ put("site1", "11_235");
+ put("site2", "18_138");
+ put("site3", "18_138");
+ put("site4", "18_138");
+ put("site5", "18_138");
+ put("site6", "18_138");
+ put("site7", "18_138");
+ put("site8", "18_138");
+ put("site9", "18_138");
+ }},
+ GenericCardTestHelper.FOTRFrodo,
+ GenericCardTestHelper.FOTRRing,
+ "open"
+ );
+ }
+
+ @Test
+ public void DammedGateStreamStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 11
+ * Title: Dammed Gate-stream
+ * Side: Site
+ * Culture: Site
+ * Twilight Cost: 3
+ * Type: Site
+ * Site Number: *
+ * Game Text: Marsh. At the start of your fellowship phase, you may play a [GOLLUM] Free Peoples card from your draw deck.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl site1 = scn.GetFreepsSite("Dammed Gate-stream");
+
+ assertFalse(site1.getBlueprint().isUnique());
+ //assertEquals(Side.FREE_PEOPLE, site1.getBlueprint().getSide());
+ //assertEquals(Culture., site1.getBlueprint().getCulture());
+ assertEquals(CardType.SITE, site1.getBlueprint().getCardType());
+ //assertEquals(Race.CREATURE, site1.getBlueprint().getRace());
+ assertTrue(scn.HasKeyword(site1, Keyword.MARSH)); // test for keywords as needed
+ assertEquals(3, site1.getBlueprint().getTwilightCost());
+ //assertEquals(, site1.getBlueprint().getStrength());
+ //assertEquals(, site1.getBlueprint().getVitality());
+ //assertEquals(, site1.getBlueprint().getResistance());
+ //assertEquals(Signet., site1.getBlueprint().getSignet());
+ assertEquals(0, site1.getBlueprint().getSiteNumber()); // Change this to getAllyHomeSiteNumbers for allies
+
+ }
+
+ @Test
+ public void StartOfFellowshipPhaseActionAllowsPlayFromDrawDeck() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl frodo = scn.GetRingBearer();
+ PhysicalCardImpl dontlook = scn.GetFreepsCard("dontlook");
+ PhysicalCardImpl smeagol = scn.GetFreepsCard("smeagol");
+ PhysicalCardImpl slippery = scn.GetFreepsCard("slippery");
+ PhysicalCardImpl boat = scn.GetFreepsCard("boat");
+ PhysicalCardImpl clever = scn.GetFreepsCard("clever");
+ PhysicalCardImpl site1 = scn.GetFreepsSite("Dammed Gate-stream");
+
+ scn.FreepsChooseCardBPFromSelection(site1);
+ scn.SkipStartingFellowships();
+ //Apparently it's drawing cards now. It doesn't do this in other formats.
+ scn.FreepsMoveCardsToBottomOfDeck(dontlook, smeagol, slippery, boat, clever);
+ scn.StartGame();
+
+ assertTrue(scn.FreepsHasOptionalTriggerAvailable());
+ scn.FreepsAcceptOptionalTrigger();
+
+ //Not Listening is a response event, it shouldn't show up
+ //Clever Hobbits is a skirmish event, also shouldn't show
+ //Smeagol and Don't Look At Them are valid. Fishing Boat would theoretically be valid if Smeagol were in play.
+ assertEquals(2, scn.GetFreepsCardChoiceCount());
+
+ assertEquals(Zone.DECK, dontlook.getZone());
+ assertEquals(Zone.DECK, smeagol.getZone());
+ scn.FreepsChooseCardBPFromSelection(dontlook);
+
+ assertEquals(Zone.SUPPORT, dontlook.getZone());
+ assertEquals(Zone.DECK, smeagol.getZone());
+
+ }
+
+}