diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/official/set15/set15-orc.hjson b/gemp-lotr/gemp-lotr-async/src/main/web/cards/official/set15/set15-orc.hjson
new file mode 100644
index 000000000..0b11b6010
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/official/set15/set15-orc.hjson
@@ -0,0 +1,93 @@
+{
+ 15_112: {
+ cardInfo: {
+ //Either a full URL, or a subpath for the PC image server
+ imagePath: decipher/LOTR15112.jpg
+ //If this is true, then all gameplay-related info outside this cardInfo definition
+ // will be ignored and the java class loaded instead.
+ javaClass: false
+ //Versioning differentiates releases within a particular alt path, such as PC errata
+ // version 1 vs version 2. PC version 2 will not conflict with, say, Decipher version 2.
+ //Top-level cards should always be version 0.
+ version: 0
+ collInfo: 15R112
+ rarity: R
+ setNum: "15"
+ cardNum: 112
+ // Standard, Masterwork, Tengwar, FullArt, etc. Top-level cards are always Standard.
+ style: Standard
+ }
+ title: Mountain-troll
+ unique: false
+ side: Shadow
+ culture: Orc
+ twilight: 10
+ type: Minion
+ race: Troll
+ strength: 22
+ vitality: 6
+ site: 5
+ effects: [
+ {
+ type: discount
+ memorize: DiscountPaid
+ max: {
+ type: requires
+ requires: {
+ type: CanSpot
+ filter: culture(orc),minion
+ count: 5
+ }
+ true: 10
+ false: 0
+ }
+ discount: {
+ type: ifDiscardFromPlay
+ filter: culture(orc),minion
+ count: 5
+ }
+ }
+ {
+ type: modifier
+ modifier: {
+ type: addkeyword
+ keyword: fierce
+ filter: self
+ requires: {
+ #This is only set if the discount was paid for.
+ type: HasInZoneData
+ filter: self
+ }
+ }
+ }
+ {
+ type: activated
+ phase: shadow
+ cost: {
+ type: removeTwilight
+ amount: 3
+ }
+ effect: [
+ {
+ type: playCardFromDiscard
+ removedTwilight: 2
+ filter: choose(culture(orc), orc)
+ memorize: PlayedOrc
+ cost: -2
+ }
+ ]
+ }
+ ]
+ gametext: When you play this minion, you may discard 5 [orc] minions from play to make it strength +10 and fierce until the regroup phase.
Shadow: Remove (2) to play an [orc] Orc from your discard pile. It comes into play exhausted.
+ lore: “Suddenly on the last stroke the Gate of Gondor broke.”
+ promotext: ""
+ alts: {
+ //These are just CardInfo objects
+ promos: {
+ }
+ //These are full card definitions, with redundant info that is the same as the original card ommitted
+ errata: {
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/errata/set15/set15-Orc-errata-playtest.hjson b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/errata/set15/set15-Orc-errata-playtest.hjson
index 1eda4ba32..954e7c3a3 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/errata/set15/set15-Orc-errata-playtest.hjson
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/errata/set15/set15-Orc-errata-playtest.hjson
@@ -26,33 +26,61 @@
}
title: Mountain-troll
unique: false
+ side: Shadow
culture: Orc
twilight: 8
type: Minion
- requires: {
- type: canSpot
- filter: orc
- }
+ race: Troll
+ strength: 13
+ vitality: 4
+ site: 5
effects: [
- {
- type: modifier,
- modifier: {
- type: addKeyword
- filter: dwarf
- keyword: damage+1
- }
- },
{
type: trigger
optional: true,
trigger: {
- type: winsSkirmish
- filter: dwarf
+ type: played
+ filter: self
},
- effect: {
- type: wound
- filter: choose(orc)
+ cost: {
+ type: discard
+ count: 5
+ filter: choose(culture(orc), minion, another)
}
+ effect: [
+ {
+ type: addKeyword
+ keyword: fierce
+ filter: self
+ until: endofturn
+ }
+ {
+ type: modifystrength
+ amount: 10
+ filter: self
+ until: endofturn
+ }
+ ]
+ }
+ {
+ type: activated
+ phase: shadow
+ cost: {
+ type: removeTwilight
+ amount: 2
+ }
+ effect: [
+ {
+ type: playCardFromDiscard
+ removedTwilight: 2
+ filter: choose(culture(orc), orc)
+ memorize: PlayedOrc
+ }
+ {
+ type: exhaust
+ filter: memory(PlayedOrc)
+ }
+ ]
}
]
gametext: When you play this minion, you may discard 5 [orc] minions from play to make it strength +10 and fierce until the regroup phase.
Shadow: Remove (2) to play an [orc] Orc from your discard pile. It comes into play exhausted.
diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/second-edition/set40/set40-moria.hjson b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/second-edition/set40/set40-moria.hjson
index f34a11405..1a674609c 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/second-edition/set40/set40-moria.hjson
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/second-edition/set40/set40-moria.hjson
@@ -135,12 +135,12 @@
]
effects: {
type: discount
- amount: {
+ max: {
type: forEachInHand
filter: culture(moria),goblin
}
discount: {
- type: discardFromHand
+ type: perDiscardFromHand
filter: culture(moria),goblin
}
}
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set15/orc/Card15_112.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set15/orc/Card15_112.java
deleted file mode 100644
index 4366b27fc..000000000
--- a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set15/orc/Card15_112.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.gempukku.lotro.cards.set15.orc;
-
-import com.gempukku.lotro.common.*;
-import com.gempukku.lotro.game.PhysicalCard;
-import com.gempukku.lotro.game.state.LotroGame;
-import com.gempukku.lotro.logic.actions.ActivateCardAction;
-import com.gempukku.lotro.logic.actions.CostToEffectAction;
-import com.gempukku.lotro.logic.cardtype.AbstractMinion;
-import com.gempukku.lotro.logic.effects.AddUntilEndOfTurnModifierEffect;
-import com.gempukku.lotro.logic.effects.RemoveTwilightEffect;
-import com.gempukku.lotro.logic.effects.choose.ChooseAndPlayCardFromDiscardEffect;
-import com.gempukku.lotro.logic.effects.discount.OptionalDiscardDiscountEffect;
-import com.gempukku.lotro.logic.modifiers.KeywordModifier;
-import com.gempukku.lotro.logic.timing.PlayConditions;
-import com.gempukku.lotro.logic.timing.UnrespondableEffect;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Set: The Hunters
- * Side: Shadow
- * Culture: Orc
- * Twilight Cost: 10
- * Type: Minion • Troll
- * Strength: 22
- * Vitality: 6
- * Site: 5
- * Game Text: When you play this minion, you may discard 5 [ORC] minions from play to make it twilight cost -10
- * and fierce. Shadow: Remove (3) to play an [ORC] Orc from your discard pile. Its twilight cost is -2.
- */
-public class Card15_112 extends AbstractMinion {
- public Card15_112() {
- super(10, 22, 6, 5, Race.TROLL, Culture.ORC, "Mountain-troll");
- }
-
- @Override
- public int getPotentialDiscount(LotroGame game, String playerId, PhysicalCard self) {
- if (PlayConditions.canDiscardFromPlay(self, game, 5, Culture.ORC, CardType.MINION))
- return 10;
- return 0;
- }
-
- @Override
- public void appendPotentialDiscountEffects(LotroGame game, final CostToEffectAction action, String playerId, final PhysicalCard self) {
- action.appendPotentialDiscount(new OptionalDiscardDiscountEffect(action, 10, playerId, 5, Culture.ORC, CardType.MINION) {
- @Override
- protected void discountPaidCallback() {
- action.appendEffect(
- new UnrespondableEffect() {
- @Override
- protected void doPlayEffect(LotroGame game) {
- action.appendEffect(
- new AddUntilEndOfTurnModifierEffect(
- new KeywordModifier(self, self, Keyword.FIERCE)));
- }
- });
- }
- });
- }
-
- @Override
- public List extends ActivateCardAction> getPhaseActionsInPlay(String playerId, LotroGame game, PhysicalCard self) {
- if (PlayConditions.canUseShadowCardDuringPhase(game, Phase.SHADOW, self, 3)
- && PlayConditions.canPlayFromDiscard(playerId, game, 3, -2, Culture.ORC, Race.ORC)) {
- ActivateCardAction action = new ActivateCardAction(self);
- action.appendCost(
- new RemoveTwilightEffect(3));
- action.appendEffect(
- new ChooseAndPlayCardFromDiscardEffect(playerId, game, -2, Culture.ORC, Race.ORC));
- return Collections.singletonList(action);
- }
- return null;
- }
-}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/PotentialDiscount.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/PotentialDiscount.java
index c8b023afb..7c33d3638 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/PotentialDiscount.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/PotentialDiscount.java
@@ -7,38 +7,160 @@ import com.gempukku.lotro.cards.build.field.effect.appender.resolver.ValueResolv
import com.gempukku.lotro.common.Filterable;
import com.gempukku.lotro.logic.actions.CostToEffectAction;
import com.gempukku.lotro.logic.effects.DiscountEffect;
-import com.gempukku.lotro.logic.effects.discount.DiscardCardFromHandDiscountEffect;
+import com.gempukku.lotro.logic.effects.discount.*;
import org.json.simple.JSONObject;
public class PotentialDiscount implements EffectProcessor {
@Override
public void processEffect(JSONObject value, BuiltLotroCardBlueprint blueprint, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
- FieldUtils.validateAllowedFields(value, "amount", "discount");
+ FieldUtils.validateAllowedFields(value, "max", "discount", "memorize");
- final ValueSource amountSource = ValueResolver.resolveEvaluator(value.get("amount"), environment);
+ final ValueSource maxSource = ValueResolver.resolveEvaluator(value.get("max"), 1000, environment);
final JSONObject discount = (JSONObject) value.get("discount");
+ final String memory = FieldUtils.getString(value.get("memorize"), "memorize", "_temp");
final String discountType = FieldUtils.getString(discount.get("type"), "type");
- if (discountType.equals("discardFromHand")) {
+ if (discountType.equalsIgnoreCase("perDiscardFromHand")) {
FieldUtils.validateAllowedFields(discount, "filter");
final String filter = FieldUtils.getString(discount.get("filter"), "filter", "any");
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
blueprint.appendDiscountSource(
- new DiscountSource() {
- @Override
- public int getPotentialDiscount(ActionContext actionContext) {
- return amountSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), actionContext.getSource());
- }
+ new DiscountSource() {
+ @Override
+ public int getPotentialDiscount(ActionContext actionContext) {
+ return maxSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), actionContext.getSource());
+ }
- @Override
- public DiscountEffect getDiscountEffect(CostToEffectAction action, ActionContext actionContext) {
- final Filterable filterable = filterableSource.getFilterable(actionContext);
- return new DiscardCardFromHandDiscountEffect(action, actionContext.getPerformingPlayer(), filterable);
- }
- });
- } else {
+ @Override
+ public DiscountEffect getDiscountEffect(CostToEffectAction action, ActionContext actionContext) {
+ final Filterable filterable = filterableSource.getFilterable(actionContext);
+ return new DiscardCardFromHandDiscountEffect(action, actionContext.getPerformingPlayer(), filterable) {
+ @Override
+ protected void discountPaidCallback(int paid) {
+ actionContext.setValueToMemory(memory, String.valueOf(paid));
+ actionContext.getSource().setWhileInZoneData(paid);
+ }
+ };
+ }
+ });
+ }
+ else if (discountType.equalsIgnoreCase("perExert")) {
+ FieldUtils.validateAllowedFields(discount, "multiplier", "filter");
+
+ final ValueSource multiplierSource = ValueResolver.resolveEvaluator(discount.get("multiplier"), environment);
+ final String filter = FieldUtils.getString(discount.get("filter"), "filter", "any");
+ final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
+
+ blueprint.appendDiscountSource(
+ new DiscountSource() {
+ @Override
+ public int getPotentialDiscount(ActionContext actionContext) {
+ return maxSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), actionContext.getSource());
+ }
+
+ @Override
+ public DiscountEffect getDiscountEffect(CostToEffectAction action, ActionContext actionContext) {
+ final Filterable filterable = filterableSource.getFilterable(actionContext);
+ final int multiplier = multiplierSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
+ return new ExertCharactersDiscountEffect(action, actionContext.getSource(),
+ actionContext.getPerformingPlayer(), multiplier, filterable) {
+
+ @Override
+ protected void discountPaidCallback(int paid) {
+ actionContext.setValueToMemory(memory, String.valueOf(paid));
+ actionContext.getSource().setWhileInZoneData(paid);
+ }
+ };
+ }
+ });
+ }
+ else if (discountType.equalsIgnoreCase("perThreatRemoved")) {
+ //FieldUtils.validateAllowedFields(discount, "multiplier");
+
+ blueprint.appendDiscountSource(
+ new DiscountSource() {
+ @Override
+ public int getPotentialDiscount(ActionContext actionContext) {
+ return maxSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), actionContext.getSource());
+ }
+
+ @Override
+ public DiscountEffect getDiscountEffect(CostToEffectAction action, ActionContext actionContext) {
+ //final int multiplier = multiplierSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
+ return new RemoveThreatsToDiscountEffect(action) {
+
+ @Override
+ protected void discountPaidCallback(int paid) {
+ actionContext.setValueToMemory(memory, String.valueOf(paid));
+ actionContext.getSource().setWhileInZoneData(paid);
+ }
+ };
+ }
+ });
+ }
+ else if (discountType.equalsIgnoreCase("ifDiscardFromPlay")) {
+ FieldUtils.validateAllowedFields(discount, "count", "filter");
+
+ final ValueSource discardCountSource = ValueResolver.resolveEvaluator(discount.get("count"), environment);
+ final String filter = FieldUtils.getString(discount.get("filter"), "filter", "any");
+ final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
+
+ blueprint.appendDiscountSource(
+ new DiscountSource() {
+ @Override
+ public int getPotentialDiscount(ActionContext actionContext) {
+ return maxSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), actionContext.getSource());
+ }
+
+ @Override
+ public DiscountEffect getDiscountEffect(CostToEffectAction action, ActionContext actionContext) {
+ final Filterable filterable = filterableSource.getFilterable(actionContext);
+ final int max = maxSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), actionContext.getSource());
+ final int discardCount = discardCountSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), actionContext.getSource());
+ actionContext.setValueToMemory(memory, "No");
+ return new OptionalDiscardDiscountEffect(action, max, actionContext.getPerformingPlayer(), discardCount, filterable) {
+ @Override
+ protected void discountPaidCallback(int paid) {
+ actionContext.setValueToMemory(memory, "Yes");
+ actionContext.getSource().setWhileInZoneData(memory);
+ }
+ };
+ }
+ });
+ }
+ else if (discountType.equalsIgnoreCase("ifRemoveFromDiscard")) {
+ FieldUtils.validateAllowedFields(discount, "count", "filter");
+
+ final ValueSource removeCountSource = ValueResolver.resolveEvaluator(value.get("count"), environment);
+ final String filter = FieldUtils.getString(discount.get("filter"), "filter", "any");
+ final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
+
+ blueprint.appendDiscountSource(
+ new DiscountSource() {
+ @Override
+ public int getPotentialDiscount(ActionContext actionContext) {
+ return maxSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), actionContext.getSource());
+ }
+
+ @Override
+ public DiscountEffect getDiscountEffect(CostToEffectAction action, ActionContext actionContext) {
+ final Filterable filterable = filterableSource.getFilterable(actionContext);
+ final int max = maxSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), actionContext.getSource());
+ final int removeCount = removeCountSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), actionContext.getSource());
+ actionContext.setValueToMemory(memory, "No");
+ return new RemoveCardsFromDiscardDiscountEffect(actionContext.getSource(), actionContext.getPerformingPlayer(), removeCount, max, filterable) {
+ @Override
+ protected void discountPaidCallback(int paid) {
+ actionContext.setValueToMemory(memory, "Yes");
+ actionContext.getSource().setWhileInZoneData(memory);
+ }
+ };
+ }
+ });
+ }
+ else {
throw new InvalidCardDefinitionException("Unknown type of discount: " + discountType);
}
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/MemoryIs.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/MemoryIs.java
index 588aceb05..917d3e3f2 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/MemoryIs.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/MemoryIs.java
@@ -16,7 +16,7 @@ public class MemoryIs implements RequirementProducer {
return (actionContext) -> {
String valueFromMemory = actionContext.getValueFromMemory(memory);
- return valueFromMemory != null && valueFromMemory.equals(value);
+ return valueFromMemory != null && valueFromMemory.equalsIgnoreCase(value);
};
}
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java
index ac2a4737f..791defaca 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java
@@ -455,7 +455,10 @@ public class GameState {
removeFromSkirmish(card, false);
removeAllTokens(card);
- card.setWhileInZoneData(null);
+ //If this is reset, then there is no way for self-discounting effects (which are evaluated while in the void)
+ // to have any sort of permanent effect once the card is in play.
+ if(zone != Zone.VOID_FROM_HAND && zone != Zone.VOID)
+ card.setWhileInZoneData(null);
}
for (GameStateListener listener : getAllGameStateListeners())
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/ChooseActiveCardsEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/ChooseActiveCardsEffect.java
index ef22a449a..cf2ddc1c1 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/ChooseActiveCardsEffect.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/ChooseActiveCardsEffect.java
@@ -61,7 +61,7 @@ public abstract class ChooseActiveCardsEffect extends AbstractEffect {
@Override
public String getText(LotroGame game) {
- return null;
+ return _choiceText;
}
@Override
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/DiscountEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/DiscountEffect.java
index 767c5a232..ac909a04b 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/DiscountEffect.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/DiscountEffect.java
@@ -6,7 +6,7 @@ import com.gempukku.lotro.logic.timing.Effect;
public interface DiscountEffect extends Effect {
int getMaximumPossibleDiscount(LotroGame game);
- public void setMinimalRequiredDiscount(int minimalDiscount);
+ void setMinimalRequiredDiscount(int minimalDiscount);
- public int getDiscountPaidFor();
+ int getDiscountPaidFor();
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/OptionalEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/OptionalEffect.java
index e862c6aa4..95e87db26 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/OptionalEffect.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/OptionalEffect.java
@@ -35,9 +35,12 @@ public class OptionalEffect extends AbstractSubActionEffect {
@Override
public void playEffect(final LotroGame game) {
- if (_optionalEffect.isPlayableInFull(game))
+ if (_optionalEffect.isPlayableInFull(game)) {
+ String text = _optionalEffect.getText(game);
+ if(text != null)
+ text = text.toLowerCase();
game.getUserFeedback().sendAwaitingDecision(_playerId,
- new MultipleChoiceAwaitingDecision(1, "Do you wish to " + _optionalEffect.getText(game) + "?", new String[]{"Yes", "No"}) {
+ new MultipleChoiceAwaitingDecision(1, "Do you wish to " + text + "?", new String[]{"Yes", "No"}) {
@Override
protected void validDecisionMade(int index, String result) {
if (index == 0) {
@@ -47,5 +50,6 @@ public class OptionalEffect extends AbstractSubActionEffect {
}
}
});
+ }
}
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/DiscardCardFromHandDiscountEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/DiscardCardFromHandDiscountEffect.java
index 07bcd760b..287f35ade 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/DiscardCardFromHandDiscountEffect.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/DiscardCardFromHandDiscountEffect.java
@@ -64,9 +64,12 @@ public class DiscardCardFromHandDiscountEffect extends AbstractSubActionEffect i
@Override
protected void cardsBeingDiscardedCallback(Collection cardsBeingDiscarded) {
_discardedCount = cardsBeingDiscarded.size();
+ discountPaidCallback(_discardedCount);
}
});
processSubAction(game, subAction);
}
}
+
+ protected void discountPaidCallback(int paid) { }
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/ExertCharactersDiscountEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/ExertCharactersDiscountEffect.java
index 9bd167617..2be065956 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/ExertCharactersDiscountEffect.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/ExertCharactersDiscountEffect.java
@@ -10,6 +10,8 @@ import com.gempukku.lotro.logic.effects.choose.ChooseAndExertCharactersEffect;
import com.gempukku.lotro.logic.timing.AbstractSubActionEffect;
import com.gempukku.lotro.logic.timing.Action;
+import java.util.Collection;
+
public class ExertCharactersDiscountEffect extends AbstractSubActionEffect implements DiscountEffect {
private final Action _action;
private final PhysicalCard _payingFor;
@@ -30,7 +32,7 @@ public class ExertCharactersDiscountEffect extends AbstractSubActionEffect imple
@Override
public String getText(LotroGame game) {
- return null;
+ return "Exert characters to reduce twilight cost";
}
@Override
@@ -70,6 +72,11 @@ public class ExertCharactersDiscountEffect extends AbstractSubActionEffect imple
protected void forEachCardExertedCallback(PhysicalCard character) {
_exertedCount++;
}
+
+ @Override
+ protected void cardsToBeExertedCallback(Collection characters) {
+ discountPaidCallback(_exertedCount);
+ }
});
processSubAction(game, subAction);
}
@@ -79,4 +86,6 @@ public class ExertCharactersDiscountEffect extends AbstractSubActionEffect imple
public int getDiscountPaidFor() {
return _exertedCount * _multiplier;
}
+
+ protected void discountPaidCallback(int paid) { }
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/OptionalDiscardDiscountEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/OptionalDiscardDiscountEffect.java
index 607737bca..0ab42ad36 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/OptionalDiscardDiscountEffect.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/OptionalDiscardDiscountEffect.java
@@ -42,7 +42,7 @@ public class OptionalDiscardDiscountEffect extends AbstractSubActionEffect imple
@Override
public String getText(LotroGame game) {
- return null;
+ return "Discard cards to get a twilight discount";
}
@Override
@@ -74,7 +74,7 @@ public class OptionalDiscardDiscountEffect extends AbstractSubActionEffect imple
protected void cardsToBeDiscardedCallback(Collection cards) {
if (cards.size() == _discardCount) {
_paid = true;
- discountPaidCallback();
+ discountPaidCallback(_discardCount);
}
}
}));
@@ -82,6 +82,5 @@ public class OptionalDiscardDiscountEffect extends AbstractSubActionEffect imple
}
}
- protected void discountPaidCallback() {
- }
+ protected void discountPaidCallback(int paid) { }
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/RemoveCardsFromDiscardDiscountEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/RemoveCardsFromDiscardDiscountEffect.java
index 57f78d9c6..d38ae61e7 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/RemoveCardsFromDiscardDiscountEffect.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/RemoveCardsFromDiscardDiscountEffect.java
@@ -104,10 +104,13 @@ public class RemoveCardsFromDiscardDiscountEffect implements DiscountEffect {
game.getGameState().addCardToZone(game, removedCard, Zone.REMOVED);
game.getGameState().sendMessage(_playerId + " removed " + GameUtils.getAppendedNames(removedCards) + " from discard using " + GameUtils.getCardLink(_source));
+ discountPaidCallback(removedCards.size());
}
@Override
public boolean wasCarriedOut() {
return !_required || _paid;
}
+
+ protected void discountPaidCallback(int paid) { }
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/RemoveThreatsToDiscountEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/RemoveThreatsToDiscountEffect.java
index 4ab66d4de..64fdaf490 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/RemoveThreatsToDiscountEffect.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/discount/RemoveThreatsToDiscountEffect.java
@@ -60,6 +60,7 @@ public class RemoveThreatsToDiscountEffect extends AbstractSubActionEffect imple
new RemoveThreatsEffect(_action.getActionSource(), threats));
processSubAction(game, subAction);
_threatsRemoved = threats;
+ discountPaidCallback(threats);
}
}
}
@@ -78,4 +79,6 @@ public class RemoveThreatsToDiscountEffect extends AbstractSubActionEffect imple
public int getDiscountPaidFor() {
return _threatsRemoved;
}
+
+ protected void discountPaidCallback(int paid) { }
}
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 499deb9e5..d3b578adf 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
@@ -804,7 +804,7 @@ public class GenericCardTestHelper extends AbstractAtTest {
public void ShadowAcceptOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, "0"); }
public void ShadowDeclineOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, ""); }
- public void ShadowDeclineReconciliation() throws DecisionResultInvalidException { playerDecided(P2, ""); }
+ public void ShadowDeclineReconciliation() throws DecisionResultInvalidException { ShadowPassCurrentPhaseAction(); }
public void FreepsChooseYes() throws DecisionResultInvalidException { ChooseMultipleChoiceOption(P1, "Yes"); }
public void ShadowChooseYes() throws DecisionResultInvalidException { ChooseMultipleChoiceOption(P2, "Yes"); }
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set15/Card_15_112_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set15/Card_15_112_Tests.java
new file mode 100644
index 000000000..0686a58b7
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set15/Card_15_112_Tests.java
@@ -0,0 +1,175 @@
+package com.gempukku.lotro.cards.official.set15;
+
+import com.gempukku.lotro.cards.GenericCardTestHelper;
+import com.gempukku.lotro.common.*;
+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 org.junit.Assert.*;
+
+public class Card_15_112_Tests
+{
+
+ protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
+ return new GenericCardTestHelper(
+ new HashMap()
+ {{
+ put("troll", "15_112");
+ put("orc1", "13_118");
+ put("orc2", "13_118");
+ put("orc3", "13_118");
+ put("orc4", "13_118");
+ put("orc5", "13_118");
+ }},
+ GenericCardTestHelper.FellowshipSites,
+ GenericCardTestHelper.FOTRFrodo,
+ GenericCardTestHelper.FOTRRing
+ );
+ }
+
+ @Test
+ public void MountaintrollStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
+
+ /**
+ * Set: 15
+ * Title: Mountain-troll
+ * Side: Free Peoples
+ * Culture: Orc
+ * Twilight Cost: 10
+ * Type: minion
+ * Subtype: Troll
+ * Strength: 13
+ * Vitality: 4
+ * Site Number: 5
+ * Game Text: When you play this minion, you may discard 5 [orc] minions from play to make it twilight cost -10 and
+ * fierce.
+ * Shadow: Remove (2) to play an [orc] Orc from your discard pile. It comes into play exhausted.
+ */
+
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl troll = scn.GetFreepsCard("troll");
+
+ assertFalse(troll.getBlueprint().isUnique());
+ assertEquals(Side.SHADOW, troll.getBlueprint().getSide());
+ assertEquals(Culture.ORC, troll.getBlueprint().getCulture());
+ assertEquals(CardType.MINION, troll.getBlueprint().getCardType());
+ assertEquals(Race.TROLL, troll.getBlueprint().getRace());
+ assertEquals(10, troll.getBlueprint().getTwilightCost());
+ assertEquals(22, troll.getBlueprint().getStrength());
+ assertEquals(6, troll.getBlueprint().getVitality());
+ //assertEquals(, troll.getBlueprint().getResistance());
+ //assertEquals(Signet., troll.getBlueprint().getSignet());
+ assertEquals(5, troll.getBlueprint().getSiteNumber()); // Change this to getAllyHomeSiteNumbers for allies
+
+ }
+
+ @Test
+ public void OnPlayTrollDoesNothingIfLessThan5OrcMinionsInPlay() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ var troll = scn.GetShadowCard("troll");
+ var orc1 = scn.GetShadowCard("orc1");
+ var orc2 = scn.GetShadowCard("orc2");
+ var orc3 = scn.GetShadowCard("orc3");
+ var orc4 = scn.GetShadowCard("orc4");
+ var orc5 = scn.GetShadowCard("orc5");
+ scn.ShadowMoveCardToHand(troll);
+ scn.ShadowMoveCharToTable(orc1, orc2, orc3, orc4);
+
+ scn.StartGame();
+
+ scn.SetTwilight(20);
+
+ scn.FreepsPassCurrentPhaseAction();
+ scn.ShadowPlayCard(troll);
+
+ assertFalse(scn.ShadowHasOptionalTriggerAvailable());
+ }
+
+ @Test
+ public void OnPlayTrollOptionallDiscards5OrcMinionsForMinus10TwilightAndFierceUntilEndOfTurn() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ var troll = scn.GetShadowCard("troll");
+ var orc1 = scn.GetShadowCard("orc1");
+ var orc2 = scn.GetShadowCard("orc2");
+ var orc3 = scn.GetShadowCard("orc3");
+ var orc4 = scn.GetShadowCard("orc4");
+ var orc5 = scn.GetShadowCard("orc5");
+ scn.ShadowMoveCardToHand(troll);
+ scn.ShadowMoveCharToTable(orc1, orc2, orc3, orc4, orc5);
+
+ scn.StartGame();
+
+ scn.SetTwilight(17);
+
+ scn.FreepsPassCurrentPhaseAction();
+ assertEquals(20, scn.GetTwilight());
+ scn.ShadowPlayCard(troll);
+
+ assertTrue(scn.ShadowDecisionAvailable("choose cards to discard"));
+ assertFalse(scn.HasKeyword(troll, Keyword.FIERCE));
+
+ scn.ShadowChooseYes();
+ assertTrue(scn.HasKeyword(troll, Keyword.FIERCE));
+ assertEquals(Zone.DISCARD, orc1.getZone());
+ assertEquals(Zone.DISCARD, orc2.getZone());
+ assertEquals(Zone.DISCARD, orc3.getZone());
+ assertEquals(Zone.DISCARD, orc4.getZone());
+ assertEquals(Zone.DISCARD, orc5.getZone());
+ assertEquals(18, scn.GetTwilight()); //20 initial -2 for roaming, troll was otherwise free
+
+ scn.SkipToPhase(Phase.ASSIGNMENT);
+ assertTrue(scn.HasKeyword(troll, Keyword.FIERCE));
+
+ scn.SkipToPhase(Phase.REGROUP);
+ assertTrue(scn.HasKeyword(troll, Keyword.FIERCE));
+
+ scn.PassCurrentPhaseActions();
+ scn.ShadowDeclineReconciliation();
+ scn.FreepsChooseToMove();
+ assertTrue(scn.HasKeyword(troll, Keyword.FIERCE));
+ }
+
+ @Test
+ public void ShadowAbilityRemoves3AndPlaysDiscountedOrcFromDiscard() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ var troll = scn.GetShadowCard("troll");
+ var orc1 = scn.GetShadowCard("orc1");
+ var orc2 = scn.GetShadowCard("orc2");
+ var orc3 = scn.GetShadowCard("orc3");
+ var orc4 = scn.GetShadowCard("orc4");
+ var orc5 = scn.GetShadowCard("orc5");
+ scn.ShadowMoveCharToTable(troll);
+ scn.ShadowMoveCardToDiscard(orc1, orc2, orc3, orc4, orc5);
+
+ scn.StartGame();
+
+ scn.SetTwilight(17);
+
+ scn.FreepsPassCurrentPhaseAction();
+
+ assertEquals(20, scn.GetTwilight());
+ assertTrue(scn.ShadowActionAvailable(troll));
+ assertEquals(Zone.DISCARD, orc1.getZone());
+
+ scn.ShadowUseCardAction(troll);
+ assertEquals(5, scn.GetShadowCardChoiceCount());
+ scn.ShadowChooseCardBPFromSelection(orc1);
+
+ // -3 for ability, -3 for orc, +2 for discount, -2 for roaming
+ assertEquals(14, scn.GetTwilight());
+ assertEquals(Zone.SHADOW_CHARACTERS, orc1.getZone());
+ assertEquals(0, scn.GetWoundsOn(orc1));
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set15/Card_15_112_ErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set15/Card_15_112_ErrataTests.java
index dd8777ae4..2dce36793 100644
--- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set15/Card_15_112_ErrataTests.java
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set15/Card_15_112_ErrataTests.java
@@ -6,6 +6,7 @@ import com.gempukku.lotro.game.CardNotFoundException;
import com.gempukku.lotro.game.PhysicalCardImpl;
import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
import com.gempukku.lotro.logic.modifiers.MoveLimitModifier;
+import org.junit.Assert;
import org.junit.Test;
import java.util.HashMap;
@@ -21,8 +22,12 @@ public class Card_15_112_ErrataTests
return new GenericCardTestHelper(
new HashMap()
{{
- put("card", "85_112");
- // put other cards in here as needed for the test case
+ put("troll", "85_112");
+ put("orc1", "13_118");
+ put("orc2", "13_118");
+ put("orc3", "13_118");
+ put("orc4", "13_118");
+ put("orc5", "13_118");
}},
GenericCardTestHelper.FellowshipSites,
GenericCardTestHelper.FOTRFrodo,
@@ -30,9 +35,7 @@ public class Card_15_112_ErrataTests
);
}
- // Uncomment both @Test markers below once this is ready to be used
-
- //@Test
+ @Test
public void MountaintrollStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
/**
@@ -46,40 +49,135 @@ public class Card_15_112_ErrataTests
* Strength: 13
* Vitality: 4
* Site Number: 5
- * Game Text: When you play this minion, you may discard 5 [orc] minions from play to make it strength +10 and fierce until the regroup phase.
Shadow: Remove (2) to play an [orc] Orc from your discard pile. It comes into play exhausted.
+ * Game Text: When you play this minion, you may discard 5 [orc] minions from play to make it strength +10 and
+ * fierce until the end of the turn.
+ * Shadow: Remove (2) to play an [orc] Orc from your discard pile. It comes into play exhausted.
*/
//Pre-game setup
GenericCardTestHelper scn = GetScenario();
- PhysicalCardImpl card = scn.GetFreepsCard("card");
+ PhysicalCardImpl troll = scn.GetFreepsCard("troll");
- assertFalse(card.getBlueprint().isUnique());
- assertEquals(Side.SHADOW, card.getBlueprint().getSide());
- assertEquals(Culture.ORC, card.getBlueprint().getCulture());
- assertEquals(CardType.MINION, card.getBlueprint().getCardType());
- assertEquals(Race.CREATURE, card.getBlueprint().getRace());
- assertTrue(scn.HasKeyword(card, Keyword.SUPPORT_AREA));
- assertEquals(8, card.getBlueprint().getTwilightCost());
- assertEquals(13, card.getBlueprint().getStrength());
- assertEquals(4, card.getBlueprint().getVitality());
- //assertEquals(, card.getBlueprint().getResistance());
- //assertEquals(Signet., card.getBlueprint().getSignet());
- assertEquals(5, card.getBlueprint().getSiteNumber()); // Change this to getAllyHomeSiteNumbers for allies
+ assertFalse(troll.getBlueprint().isUnique());
+ assertEquals(Side.SHADOW, troll.getBlueprint().getSide());
+ assertEquals(Culture.ORC, troll.getBlueprint().getCulture());
+ assertEquals(CardType.MINION, troll.getBlueprint().getCardType());
+ assertEquals(Race.TROLL, troll.getBlueprint().getRace());
+ assertEquals(8, troll.getBlueprint().getTwilightCost());
+ assertEquals(13, troll.getBlueprint().getStrength());
+ assertEquals(4, troll.getBlueprint().getVitality());
+ //assertEquals(, troll.getBlueprint().getResistance());
+ //assertEquals(Signet., troll.getBlueprint().getSignet());
+ assertEquals(5, troll.getBlueprint().getSiteNumber()); // Change this to getAllyHomeSiteNumbers for allies
}
- //@Test
- public void MountaintrollTest1() throws DecisionResultInvalidException, CardNotFoundException {
+ @Test
+ public void OnPlayTrollDoesNothingIfLessThan5OrcMinionsInPlay() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
GenericCardTestHelper scn = GetScenario();
- PhysicalCardImpl card = scn.GetFreepsCard("card");
- scn.FreepsMoveCardToHand(card);
+ var troll = scn.GetShadowCard("troll");
+ var orc1 = scn.GetShadowCard("orc1");
+ var orc2 = scn.GetShadowCard("orc2");
+ var orc3 = scn.GetShadowCard("orc3");
+ var orc4 = scn.GetShadowCard("orc4");
+ var orc5 = scn.GetShadowCard("orc5");
+ scn.ShadowMoveCardToHand(troll);
+ scn.ShadowMoveCharToTable(orc1, orc2, orc3, orc4);
scn.StartGame();
- scn.FreepsPlayCard(card);
- assertEquals(8, scn.GetTwilight());
+ scn.SetTwilight(20);
+
+ scn.FreepsPassCurrentPhaseAction();
+ scn.ShadowPlayCard(troll);
+
+ assertFalse(scn.ShadowHasOptionalTriggerAvailable());
+ }
+
+ @Test
+ public void OnPlayTrollOptionallDiscards5OrcMinionsForFierceAndStrengthPluse10UntilEndOfTurn() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ var troll = scn.GetShadowCard("troll");
+ var orc1 = scn.GetShadowCard("orc1");
+ var orc2 = scn.GetShadowCard("orc2");
+ var orc3 = scn.GetShadowCard("orc3");
+ var orc4 = scn.GetShadowCard("orc4");
+ var orc5 = scn.GetShadowCard("orc5");
+ scn.ShadowMoveCardToHand(troll);
+ scn.ShadowMoveCharToTable(orc1, orc2, orc3, orc4, orc5);
+
+ scn.StartGame();
+
+ scn.SetTwilight(17);
+
+ scn.FreepsPassCurrentPhaseAction();
+ assertEquals(20, scn.GetTwilight());
+ scn.ShadowPlayCard(troll);
+
+ assertTrue(scn.ShadowHasOptionalTriggerAvailable());
+ assertEquals(13, scn.GetStrength(troll));
+ assertFalse(scn.HasKeyword(troll, Keyword.FIERCE));
+
+ scn.ShadowAcceptOptionalTrigger();
+ assertEquals(23, scn.GetStrength(troll));
+ assertTrue(scn.HasKeyword(troll, Keyword.FIERCE));
+ assertEquals(Zone.DISCARD, orc1.getZone());
+ assertEquals(Zone.DISCARD, orc2.getZone());
+ assertEquals(Zone.DISCARD, orc3.getZone());
+ assertEquals(Zone.DISCARD, orc4.getZone());
+ assertEquals(Zone.DISCARD, orc5.getZone());
+ assertEquals(10, scn.GetTwilight()); //20 initial -8 for troll -2 for roaming
+
+ scn.SkipToPhase(Phase.ASSIGNMENT);
+ assertEquals(23, scn.GetStrength(troll));
+ assertTrue(scn.HasKeyword(troll, Keyword.FIERCE));
+
+ scn.SkipToPhase(Phase.REGROUP);
+ assertEquals(23, scn.GetStrength(troll));
+ assertTrue(scn.HasKeyword(troll, Keyword.FIERCE));
+
+ scn.PassCurrentPhaseActions();
+ scn.ShadowDeclineReconciliation();
+ scn.FreepsChooseToMove();
+ assertEquals(23, scn.GetStrength(troll));
+ assertTrue(scn.HasKeyword(troll, Keyword.FIERCE));
+ }
+
+ @Test
+ public void ShadowAbilityRemoves2AndPlaysExhaustedOrcFromDiscard() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ var troll = scn.GetShadowCard("troll");
+ var orc1 = scn.GetShadowCard("orc1");
+ var orc2 = scn.GetShadowCard("orc2");
+ var orc3 = scn.GetShadowCard("orc3");
+ var orc4 = scn.GetShadowCard("orc4");
+ var orc5 = scn.GetShadowCard("orc5");
+ scn.ShadowMoveCharToTable(troll);
+ scn.ShadowMoveCardToDiscard(orc1, orc2, orc3, orc4, orc5);
+
+ scn.StartGame();
+
+ scn.SetTwilight(17);
+
+ scn.FreepsPassCurrentPhaseAction();
+
+ assertEquals(20, scn.GetTwilight());
+ assertTrue(scn.ShadowActionAvailable(troll));
+ assertEquals(Zone.DISCARD, orc1.getZone());
+
+ scn.ShadowUseCardAction(troll);
+ assertEquals(5, scn.GetShadowCardChoiceCount());
+ scn.ShadowChooseCardBPFromSelection(orc1);
+
+ assertEquals(13, scn.GetTwilight()); // -2 for ability, -3 for orc, -2 for roaming
+ assertEquals(Zone.SHADOW_CHARACTERS, orc1.getZone());
+ assertEquals(1, scn.GetWoundsOn(orc1));
}
}