Fixed issues with discard from top of deck or hand
This commit is contained in:
@@ -32,7 +32,8 @@
|
||||
},
|
||||
"effect": {
|
||||
"type": "discardTopCardFromDeck",
|
||||
"deck": "owner(skirmishLoser)"
|
||||
"deck": "owner(skirmishLoser)",
|
||||
"forced": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -50,7 +50,8 @@
|
||||
"filter": "choose(hasAttached(self))"
|
||||
},
|
||||
{
|
||||
"type": "discardCardAtRandomFromHand"
|
||||
"type": "discardCardAtRandomFromHand",
|
||||
"forced": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -44,6 +44,14 @@ public class FieldUtils {
|
||||
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 {
|
||||
if (value == null)
|
||||
return defaultValue;
|
||||
|
||||
@@ -17,24 +17,31 @@ import org.json.simple.JSONObject;
|
||||
public class DiscardCardAtRandomFromHand implements EffectAppenderProducer {
|
||||
@Override
|
||||
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() {
|
||||
@Override
|
||||
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
|
||||
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
|
||||
public Requirement createCostRequirement(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
|
||||
FieldUtils.validateAllowedFields(effectObject);
|
||||
return (playerId, game, self, effectResult, effect) -> game.getGameState().getHand(self.getOwner()).size() >= 1;
|
||||
FieldUtils.validateAllowedFields(effectObject, "forced");
|
||||
|
||||
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 {
|
||||
@Override
|
||||
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 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);
|
||||
|
||||
@@ -34,15 +35,16 @@ public class DiscardTopCardFromDeck implements EffectAppenderProducer {
|
||||
public boolean isPlayableInFull(String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect 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
|
||||
&& game.getModifiersQuerying().canDiscardCardsFromTopOfDeck(game, deckId, self);
|
||||
&& (!forced || game.getModifiersQuerying().canDiscardCardsFromTopOfDeck(game, playerId, self));
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
|
||||
return new DiscardTopCardFromDeckEffect(self, deckId, count, true);
|
||||
return new DiscardTopCardFromDeckEffect(self, deckId, count, forced);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -51,17 +53,19 @@ public class DiscardTopCardFromDeck implements EffectAppenderProducer {
|
||||
|
||||
@Override
|
||||
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 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);
|
||||
|
||||
// Don't check if can discard top cards, since it's a cost
|
||||
return (playerId, game, self, effectResult, effect) -> {
|
||||
final String deckId = playerSource.getPlayer(playerId, game, self, effectResult, effect);
|
||||
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;
|
||||
|
||||
import com.gempukku.lotro.common.Filterable;
|
||||
import com.gempukku.lotro.filters.Filter;
|
||||
import com.gempukku.lotro.filters.Filters;
|
||||
import com.gempukku.lotro.game.PhysicalCard;
|
||||
import com.gempukku.lotro.game.state.LotroGame;
|
||||
|
||||
public class CantDiscardCardsFromHandOrTopOfDeckModifier extends AbstractModifier {
|
||||
private Filter _discardSourceAffected;
|
||||
private String _playerId;
|
||||
|
||||
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;
|
||||
_discardSourceAffected = Filters.and(discardSourceAffected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDiscardCardsFromHand(LotroGame game, String playerId, PhysicalCard source) {
|
||||
if (playerId.equals(_playerId))
|
||||
if (source == null || _discardSourceAffected.accepts(game, source))
|
||||
return false;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDiscardCardsFromTopOfDeck(LotroGame game, String playerId, PhysicalCard source) {
|
||||
if (playerId.equals(_playerId))
|
||||
if (source == null || _discardSourceAffected.accepts(game, source))
|
||||
return false;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1246,4 +1246,43 @@ public class IndividualCardAtTest extends AbstractAtTest {
|
||||
|
||||
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