Fixed issues with discard from top of deck or hand
This commit is contained in:
@@ -32,7 +32,8 @@
|
|||||||
},
|
},
|
||||||
"effect": {
|
"effect": {
|
||||||
"type": "discardTopCardFromDeck",
|
"type": "discardTopCardFromDeck",
|
||||||
"deck": "owner(skirmishLoser)"
|
"deck": "owner(skirmishLoser)",
|
||||||
|
"forced": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -50,7 +50,8 @@
|
|||||||
"filter": "choose(hasAttached(self))"
|
"filter": "choose(hasAttached(self))"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "discardCardAtRandomFromHand"
|
"type": "discardCardAtRandomFromHand",
|
||||||
|
"forced": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -44,6 +44,14 @@ public class FieldUtils {
|
|||||||
return (String) value;
|
return (String) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean getBoolean(Object value, String key) throws InvalidCardDefinitionException {
|
||||||
|
if (value == null)
|
||||||
|
throw new InvalidCardDefinitionException("Value of " + key + " is required");
|
||||||
|
if (!(value instanceof Boolean))
|
||||||
|
throw new InvalidCardDefinitionException("Unknown type in " + key + " field");
|
||||||
|
return (Boolean) value;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean getBoolean(Object value, String key, boolean defaultValue) throws InvalidCardDefinitionException {
|
public static boolean getBoolean(Object value, String key, boolean defaultValue) throws InvalidCardDefinitionException {
|
||||||
if (value == null)
|
if (value == null)
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
|
|||||||
@@ -17,24 +17,31 @@ import org.json.simple.JSONObject;
|
|||||||
public class DiscardCardAtRandomFromHand implements EffectAppenderProducer {
|
public class DiscardCardAtRandomFromHand implements EffectAppenderProducer {
|
||||||
@Override
|
@Override
|
||||||
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
|
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
|
||||||
FieldUtils.validateAllowedFields(effectObject);
|
FieldUtils.validateAllowedFields(effectObject, "forced");
|
||||||
|
|
||||||
|
final boolean forced = FieldUtils.getBoolean(effectObject.get("forced"), "forced");
|
||||||
|
|
||||||
return new DelayedAppender() {
|
return new DelayedAppender() {
|
||||||
@Override
|
@Override
|
||||||
protected Effect createEffect(CostToEffectAction action, String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) {
|
protected Effect createEffect(CostToEffectAction action, String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) {
|
||||||
return new DiscardCardAtRandomFromHandEffect(self, self.getOwner(), false);
|
return new DiscardCardAtRandomFromHandEffect(self, self.getOwner(), forced);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlayableInFull(String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) {
|
public boolean isPlayableInFull(String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) {
|
||||||
return game.getGameState().getHand(self.getOwner()).size() >= 1;
|
return game.getGameState().getHand(self.getOwner()).size() >= 1
|
||||||
|
&& (!forced || game.getModifiersQuerying().canDiscardCardsFromHand(game, playerId, self));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Requirement createCostRequirement(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
|
public Requirement createCostRequirement(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
|
||||||
FieldUtils.validateAllowedFields(effectObject);
|
FieldUtils.validateAllowedFields(effectObject, "forced");
|
||||||
return (playerId, game, self, effectResult, effect) -> game.getGameState().getHand(self.getOwner()).size() >= 1;
|
|
||||||
|
final boolean forced = FieldUtils.getBoolean(effectObject.get("forced"), "forced");
|
||||||
|
|
||||||
|
return (playerId, game, self, effectResult, effect) -> game.getGameState().getHand(self.getOwner()).size() >= 1
|
||||||
|
&& (!forced || game.getModifiersQuerying().canDiscardCardsFromHand(game, playerId, self));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ import org.json.simple.JSONObject;
|
|||||||
public class DiscardTopCardFromDeck implements EffectAppenderProducer {
|
public class DiscardTopCardFromDeck implements EffectAppenderProducer {
|
||||||
@Override
|
@Override
|
||||||
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
|
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
|
||||||
FieldUtils.validateAllowedFields(effectObject, "deck", "count");
|
FieldUtils.validateAllowedFields(effectObject, "deck", "count", "forced");
|
||||||
|
|
||||||
final String deck = FieldUtils.getString(effectObject.get("deck"), "deck", "owner");
|
final String deck = FieldUtils.getString(effectObject.get("deck"), "deck", "owner");
|
||||||
final int count = FieldUtils.getInteger(effectObject.get("count"), "count", 1);
|
final int count = FieldUtils.getInteger(effectObject.get("count"), "count", 1);
|
||||||
|
final boolean forced = FieldUtils.getBoolean(effectObject.get("forced"), "forced");
|
||||||
|
|
||||||
final PlayerSource playerSource = PlayerResolver.resolvePlayer(deck, environment);
|
final PlayerSource playerSource = PlayerResolver.resolvePlayer(deck, environment);
|
||||||
|
|
||||||
@@ -34,15 +35,16 @@ public class DiscardTopCardFromDeck implements EffectAppenderProducer {
|
|||||||
public boolean isPlayableInFull(String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) {
|
public boolean isPlayableInFull(String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) {
|
||||||
final String deckId = playerSource.getPlayer(playerId, game, self, effectResult, effect);
|
final String deckId = playerSource.getPlayer(playerId, game, self, effectResult, effect);
|
||||||
|
|
||||||
|
// Don't check if can discard top cards, since it's a cost
|
||||||
return game.getGameState().getDeck(deckId).size() >= count
|
return game.getGameState().getDeck(deckId).size() >= count
|
||||||
&& game.getModifiersQuerying().canDiscardCardsFromTopOfDeck(game, deckId, self);
|
&& (!forced || game.getModifiersQuerying().canDiscardCardsFromTopOfDeck(game, playerId, self));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Effect createEffect(CostToEffectAction action, String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) {
|
protected Effect createEffect(CostToEffectAction action, String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) {
|
||||||
final String deckId = playerSource.getPlayer(playerId, game, self, effectResult, effect);
|
final String deckId = playerSource.getPlayer(playerId, game, self, effectResult, effect);
|
||||||
|
|
||||||
return new DiscardTopCardFromDeckEffect(self, deckId, count, true);
|
return new DiscardTopCardFromDeckEffect(self, deckId, count, forced);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -51,17 +53,19 @@ public class DiscardTopCardFromDeck implements EffectAppenderProducer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Requirement createCostRequirement(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
|
public Requirement createCostRequirement(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
|
||||||
FieldUtils.validateAllowedFields(effectObject, "deck", "count");
|
FieldUtils.validateAllowedFields(effectObject, "deck", "count", "forced");
|
||||||
|
|
||||||
final String deck = FieldUtils.getString(effectObject.get("deck"), "deck", "owner");
|
final String deck = FieldUtils.getString(effectObject.get("deck"), "deck", "owner");
|
||||||
final int count = FieldUtils.getInteger(effectObject.get("count"), "count", 1);
|
final int count = FieldUtils.getInteger(effectObject.get("count"), "count", 1);
|
||||||
|
final boolean forced = FieldUtils.getBoolean(effectObject.get("forced"), "forced");
|
||||||
|
|
||||||
final PlayerSource playerSource = PlayerResolver.resolvePlayer(deck, environment);
|
final PlayerSource playerSource = PlayerResolver.resolvePlayer(deck, environment);
|
||||||
|
|
||||||
|
// Don't check if can discard top cards, since it's a cost
|
||||||
return (playerId, game, self, effectResult, effect) -> {
|
return (playerId, game, self, effectResult, effect) -> {
|
||||||
final String deckId = playerSource.getPlayer(playerId, game, self, effectResult, effect);
|
final String deckId = playerSource.getPlayer(playerId, game, self, effectResult, effect);
|
||||||
return game.getGameState().getDeck(deckId).size() >= count
|
return game.getGameState().getDeck(deckId).size() >= count
|
||||||
&& game.getModifiersQuerying().canDiscardCardsFromTopOfDeck(game, deckId, self);
|
&& (!forced || game.getModifiersQuerying().canDiscardCardsFromTopOfDeck(game, playerId, self));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,29 @@
|
|||||||
package com.gempukku.lotro.logic.modifiers;
|
package com.gempukku.lotro.logic.modifiers;
|
||||||
|
|
||||||
import com.gempukku.lotro.common.Filterable;
|
import com.gempukku.lotro.common.Filterable;
|
||||||
import com.gempukku.lotro.filters.Filter;
|
|
||||||
import com.gempukku.lotro.filters.Filters;
|
import com.gempukku.lotro.filters.Filters;
|
||||||
import com.gempukku.lotro.game.PhysicalCard;
|
import com.gempukku.lotro.game.PhysicalCard;
|
||||||
import com.gempukku.lotro.game.state.LotroGame;
|
import com.gempukku.lotro.game.state.LotroGame;
|
||||||
|
|
||||||
public class CantDiscardCardsFromHandOrTopOfDeckModifier extends AbstractModifier {
|
public class CantDiscardCardsFromHandOrTopOfDeckModifier extends AbstractModifier {
|
||||||
private Filter _discardSourceAffected;
|
|
||||||
private String _playerId;
|
private String _playerId;
|
||||||
|
|
||||||
public CantDiscardCardsFromHandOrTopOfDeckModifier(PhysicalCard source, Condition condition, String playerId, Filterable... discardSourceAffected) {
|
public CantDiscardCardsFromHandOrTopOfDeckModifier(PhysicalCard source, Condition condition, String playerId, Filterable... discardSourceAffected) {
|
||||||
super(source, null, null, condition, ModifierEffect.DISCARD_NOT_FROM_PLAY);
|
super(source, null, Filters.and(discardSourceAffected), condition, ModifierEffect.DISCARD_NOT_FROM_PLAY);
|
||||||
_playerId = playerId;
|
_playerId = playerId;
|
||||||
_discardSourceAffected = Filters.and(discardSourceAffected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canDiscardCardsFromHand(LotroGame game, String playerId, PhysicalCard source) {
|
public boolean canDiscardCardsFromHand(LotroGame game, String playerId, PhysicalCard source) {
|
||||||
if (playerId.equals(_playerId))
|
if (playerId.equals(_playerId))
|
||||||
if (source == null || _discardSourceAffected.accepts(game, source))
|
return false;
|
||||||
return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canDiscardCardsFromTopOfDeck(LotroGame game, String playerId, PhysicalCard source) {
|
public boolean canDiscardCardsFromTopOfDeck(LotroGame game, String playerId, PhysicalCard source) {
|
||||||
if (playerId.equals(_playerId))
|
if (playerId.equals(_playerId))
|
||||||
if (source == null || _discardSourceAffected.accepts(game, source))
|
return false;
|
||||||
return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1246,4 +1246,43 @@ public class IndividualCardAtTest extends AbstractAtTest {
|
|||||||
|
|
||||||
assertTrue(_userFeedback.getAwaitingDecision(P1).getText().startsWith("Do you wish to mulligan"));
|
assertTrue(_userFeedback.getAwaitingDecision(P1).getText().startsWith("Do you wish to mulligan"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void courteousFrodoPreventsDiscard() throws DecisionResultInvalidException, CardNotFoundException {
|
||||||
|
Map<String, LotroDeck> decks = new HashMap<String, LotroDeck>();
|
||||||
|
final LotroDeck p1Deck = createSimplestDeck();
|
||||||
|
p1Deck.setRingBearer("4_301");
|
||||||
|
decks.put(P1, p1Deck);
|
||||||
|
|
||||||
|
decks.put(P2, createSimplestDeck());
|
||||||
|
|
||||||
|
initializeGameWithDecks(decks);
|
||||||
|
|
||||||
|
PhysicalCardImpl arwen = new PhysicalCardImpl(100, "7_16", P1, _library.getLotroCardBlueprint("7_16"));
|
||||||
|
PhysicalCardImpl legolas = new PhysicalCardImpl(100, "1_50", P1, _library.getLotroCardBlueprint("1_50"));
|
||||||
|
PhysicalCardImpl aragorn = new PhysicalCardImpl(100, "1_89", P1, _library.getLotroCardBlueprint("1_89"));
|
||||||
|
|
||||||
|
PhysicalCardImpl cardInHand = new PhysicalCardImpl(100, "1_268", P1, _library.getLotroCardBlueprint("1_268"));
|
||||||
|
PhysicalCardImpl inquisitor = new PhysicalCardImpl(100, "1_268", P2, _library.getLotroCardBlueprint("1_268"));
|
||||||
|
|
||||||
|
_game.getGameState().addCardToZone(_game, arwen, Zone.FREE_CHARACTERS);
|
||||||
|
_game.getGameState().addCardToZone(_game, legolas, Zone.FREE_CHARACTERS);
|
||||||
|
_game.getGameState().addCardToZone(_game, aragorn, Zone.FREE_CHARACTERS);
|
||||||
|
_game.getGameState().addCardToZone(_game, inquisitor, Zone.HAND);
|
||||||
|
_game.getGameState().addCardToZone(_game, cardInHand, Zone.HAND);
|
||||||
|
|
||||||
|
skipMulligans();
|
||||||
|
|
||||||
|
// Pass in fellowship
|
||||||
|
playerDecided(P1, "");
|
||||||
|
|
||||||
|
// Play inquisitor
|
||||||
|
playerDecided(P2, "0");
|
||||||
|
// Use inquisitor
|
||||||
|
playerDecided(P2, "0");
|
||||||
|
|
||||||
|
assertEquals(Zone.HAND, cardInHand.getZone());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user