Added Item filter and DiscardFromDeck trigger
Added item filter (which is just possession + artifact) Added trigger which keys off of cards being discarded from the deck. Added the bulk of Deepest Delvings as a result.
This commit is contained in:
@@ -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)"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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"); }
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -20,12 +20,15 @@ public class Card_V1_002Tests
|
||||
return new GenericCardTestHelper(
|
||||
new HashMap<String, String>()
|
||||
{{
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user