Fixed Dwarven Axe not following official Decipher clarification. Wrote tests for it and the PC errata version. Altered Ancient Emnity to be flat discard instead of random discard
This commit is contained in:
@@ -136,11 +136,24 @@
|
||||
against: bearer
|
||||
memorize: losingMinion
|
||||
}
|
||||
effect: {
|
||||
type: discardTopCardsFromDeck
|
||||
deck: ownerFromMemory(losingMinion)
|
||||
forced: true
|
||||
}
|
||||
effect: [
|
||||
{
|
||||
type: conditional
|
||||
requires: {
|
||||
type: perPhaseLimit
|
||||
limit: 1
|
||||
}
|
||||
effect: {
|
||||
type: discardTopCardsFromDeck
|
||||
deck: ownerFromMemory(losingMinion)
|
||||
forced: true
|
||||
}
|
||||
}
|
||||
{
|
||||
type: incrementPerPhaseLimit
|
||||
limit: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
1_10: {
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
}
|
||||
effect: {
|
||||
type: choice
|
||||
player: fp
|
||||
player: OwnerFromMemory(losingMinion)
|
||||
texts: [
|
||||
Exert a minion
|
||||
Discard the bottom card of your draw deck
|
||||
@@ -102,7 +102,7 @@
|
||||
}
|
||||
{
|
||||
type: discardBottomCardsFromDeck
|
||||
deck: ownerFromMemory(losingMinion)
|
||||
deck: OwnerFromMemory(losingMinion)
|
||||
forced: false
|
||||
}
|
||||
]
|
||||
|
||||
@@ -64,12 +64,13 @@
|
||||
type: preventable
|
||||
player: ownerFromMemory(losingMinion)
|
||||
cost: {
|
||||
type: discardCardAtRandomFromHand
|
||||
type: DiscardFromHand
|
||||
player: ownerFromMemory(losingMinion)
|
||||
hand: ownerFromMemory(losingMinion)
|
||||
count: 1
|
||||
count: 2
|
||||
forced: false
|
||||
}
|
||||
text: Discard 1 card at random from hand to prevent healing {chosenElves}
|
||||
text: Discard 2 cards from hand to prevent healing {chosenElves}
|
||||
effect: {
|
||||
type: heal
|
||||
filter: memory(chosenElves)
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
package com.gempukku.lotro.cards.official.set01;
|
||||
|
||||
import com.gempukku.lotro.cards.GenericCardTestHelper;
|
||||
import com.gempukku.lotro.common.*;
|
||||
import com.gempukku.lotro.game.CardNotFoundException;
|
||||
import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class Card_01_009_Tests
|
||||
{
|
||||
|
||||
protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
|
||||
return new GenericCardTestHelper(
|
||||
new HashMap<String, String>()
|
||||
{{
|
||||
put("axe", "1_9");
|
||||
put("gimli", "1_13");
|
||||
|
||||
put("runner", "1_178");
|
||||
put("runner2", "1_178");
|
||||
}},
|
||||
GenericCardTestHelper.FellowshipSites,
|
||||
GenericCardTestHelper.FOTRFrodo,
|
||||
GenericCardTestHelper.FOTRRing
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void DwarvenAxeStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
|
||||
/**
|
||||
* Set: 1
|
||||
* Title: Dwarven Axe
|
||||
* Unique: False
|
||||
* Side: FREE_PEOPLE
|
||||
* Culture: Dwarven
|
||||
* Twilight Cost: 0
|
||||
* Type: possession
|
||||
* Subtype: Hand Weapon
|
||||
* Strength: 2
|
||||
* Game Text: Bearer must be a Dwarf. <br>Each time a minion loses a skirmish to bearer, that minion's owner must exert a minion or discard the bottom card of their draw deck.
|
||||
*/
|
||||
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var card = scn.GetFreepsCard("axe");
|
||||
|
||||
assertFalse(card.getBlueprint().isUnique());
|
||||
assertEquals(Side.FREE_PEOPLE, card.getBlueprint().getSide());
|
||||
assertEquals(Culture.DWARVEN, card.getBlueprint().getCulture());
|
||||
assertEquals(CardType.POSSESSION, card.getBlueprint().getCardType());
|
||||
assertTrue(card.getBlueprint().getPossessionClasses().contains(PossessionClass.HAND_WEAPON));
|
||||
assertEquals(0, card.getBlueprint().getTwilightCost());
|
||||
assertEquals(2, card.getBlueprint().getStrength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void AxeMustBeBorneByDwarf() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var axe = scn.GetFreepsCard("axe");
|
||||
var gimli = scn.GetFreepsCard("gimli");
|
||||
scn.FreepsMoveCardToHand(axe, gimli);
|
||||
|
||||
scn.StartGame();
|
||||
assertFalse(scn.FreepsPlayAvailable(axe));
|
||||
scn.FreepsPlayCard(gimli);
|
||||
assertTrue(scn.FreepsPlayAvailable(axe));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void AxeCausesDeckDiscardOnSkirmishVictory() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var axe = scn.GetFreepsCard("axe");
|
||||
var gimli = scn.GetFreepsCard("gimli");
|
||||
scn.FreepsMoveCharToTable(gimli);
|
||||
scn.AttachCardsTo(gimli, axe);
|
||||
|
||||
var runner = scn.GetShadowCard("runner");
|
||||
scn.ShadowMoveCharToTable(runner);
|
||||
|
||||
scn.StartGame();
|
||||
|
||||
scn.SkipToPhase(Phase.ASSIGNMENT);
|
||||
|
||||
scn.PassCurrentPhaseActions();
|
||||
scn.FreepsAssignToMinions(gimli, runner);
|
||||
|
||||
scn.FreepsResolveSkirmish(gimli);
|
||||
scn.PassCurrentPhaseActions();
|
||||
|
||||
var topcard = scn.GetShadowTopOfDeck();
|
||||
assertEquals(Zone.DECK, topcard.getZone());
|
||||
assertEquals(3, scn.GetShadowDeckCount());
|
||||
assertEquals(0, scn.GetShadowDiscardCount());
|
||||
|
||||
scn.FreepsResolveActionOrder("Axe");
|
||||
assertEquals(Zone.DISCARD, topcard.getZone());
|
||||
assertEquals(2, scn.GetShadowDeckCount());
|
||||
assertEquals(2, scn.GetShadowDiscardCount());//runner, and a card discarded from the deck
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void AxeAffectsMaxOneMinionDuringSkirmish() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var axe = scn.GetFreepsCard("axe");
|
||||
var gimli = scn.GetFreepsCard("gimli");
|
||||
scn.FreepsMoveCharToTable(gimli);
|
||||
scn.AttachCardsTo(gimli, axe);
|
||||
|
||||
var runner = scn.GetShadowCard("runner");
|
||||
var runner2 = scn.GetShadowCard("runner2");
|
||||
scn.ShadowMoveCharToTable(runner, runner2);
|
||||
|
||||
scn.StartGame();
|
||||
|
||||
scn.SkipToPhase(Phase.ASSIGNMENT);
|
||||
|
||||
scn.PassCurrentPhaseActions();
|
||||
scn.FreepsDeclineAssignments();
|
||||
scn.ShadowAssignToMinions(gimli, runner, runner2);
|
||||
|
||||
scn.FreepsResolveSkirmish(gimli);
|
||||
scn.FreepsUseCardAction(gimli);
|
||||
scn.ShadowPassCurrentPhaseAction();
|
||||
scn.FreepsUseCardAction(gimli);
|
||||
scn.ShadowPassCurrentPhaseAction();
|
||||
scn.FreepsPassCurrentPhaseAction();
|
||||
|
||||
//Should only have "resolve skirmish wounds" and one instance of "dwarven axe required trigger".
|
||||
// If there are two axe-triggers, then the card is violating the latest Decipher "clarification":
|
||||
//
|
||||
//"This card can trigger only once for each Shadow player with a minion in that skirmish,
|
||||
// regardless of how many minions that player had."
|
||||
assertEquals(3, scn.FreepsGetAvailableActions().size());
|
||||
|
||||
var topcard = scn.GetShadowTopOfDeck();
|
||||
assertEquals(Zone.DECK, topcard.getZone());
|
||||
assertEquals(2, scn.GetShadowDeckCount());
|
||||
assertEquals(0, scn.GetShadowDiscardCount());
|
||||
|
||||
//Ideally we shouldn't have both triggers, but at least we can squelch the results of the second
|
||||
scn.FreepsResolveActionOrder("Axe");
|
||||
scn.FreepsResolveActionOrder("Axe");
|
||||
assertEquals(Zone.DISCARD, topcard.getZone());
|
||||
assertEquals(1, scn.GetShadowDeckCount());
|
||||
assertEquals(3, scn.GetShadowDiscardCount());//2 dead runners, and a card discarded from the deck
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package com.gempukku.lotro.cards.unofficial.pc.errata.set01;
|
||||
|
||||
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 com.gempukku.lotro.logic.modifiers.KeywordModifier;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class Card_01_009_ErrataTests
|
||||
{
|
||||
|
||||
protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
|
||||
return new GenericCardTestHelper(
|
||||
new HashMap<String, String>()
|
||||
{{
|
||||
put("axe", "71_9");
|
||||
put("gimli", "1_13");
|
||||
|
||||
put("scout", "1_191");
|
||||
put("runner", "1_178");
|
||||
}},
|
||||
GenericCardTestHelper.FellowshipSites,
|
||||
GenericCardTestHelper.FOTRFrodo,
|
||||
GenericCardTestHelper.FOTRRing
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void DwarvenAxeStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
|
||||
/**
|
||||
* Set: 1
|
||||
* Title: Dwarven Axe
|
||||
* Unique: False
|
||||
* Side: FREE_PEOPLE
|
||||
* Culture: Dwarven
|
||||
* Twilight Cost: 0
|
||||
* Type: possession
|
||||
* Subtype: Hand Weapon
|
||||
* Strength: 2
|
||||
* Game Text: Bearer must be a Dwarf. <br>Each time a minion loses a skirmish to bearer, that minion's owner must exert a minion or discard the bottom card of their draw deck.
|
||||
*/
|
||||
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var card = scn.GetFreepsCard("axe");
|
||||
|
||||
assertFalse(card.getBlueprint().isUnique());
|
||||
assertEquals(Side.FREE_PEOPLE, card.getBlueprint().getSide());
|
||||
assertEquals(Culture.DWARVEN, card.getBlueprint().getCulture());
|
||||
assertEquals(CardType.POSSESSION, card.getBlueprint().getCardType());
|
||||
assertTrue(card.getBlueprint().getPossessionClasses().contains(PossessionClass.HAND_WEAPON));
|
||||
assertEquals(0, card.getBlueprint().getTwilightCost());
|
||||
assertEquals(2, card.getBlueprint().getStrength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void AxeMustBeBorneByDwarf() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var axe = scn.GetFreepsCard("axe");
|
||||
var gimli = scn.GetFreepsCard("gimli");
|
||||
scn.FreepsMoveCardToHand(axe, gimli);
|
||||
|
||||
scn.StartGame();
|
||||
assertFalse(scn.FreepsPlayAvailable(axe));
|
||||
scn.FreepsPlayCard(gimli);
|
||||
assertTrue(scn.FreepsPlayAvailable(axe));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void AxeCausesExertOrDeckDiscardChoice() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var axe = scn.GetFreepsCard("axe");
|
||||
var gimli = scn.GetFreepsCard("gimli");
|
||||
var frodo = scn.GetRingBearer();
|
||||
scn.FreepsMoveCharToTable(gimli);
|
||||
scn.AttachCardsTo(gimli, axe);
|
||||
|
||||
var scout = scn.GetShadowCard("scout");
|
||||
var runner = scn.GetShadowCard("runner");
|
||||
scn.ShadowMoveCharToTable(runner,scout);
|
||||
|
||||
scn.ApplyAdHocModifier(new KeywordModifier(null, Race.ORC, Keyword.FIERCE));
|
||||
|
||||
scn.StartGame();
|
||||
|
||||
scn.SkipToPhase(Phase.ASSIGNMENT);
|
||||
|
||||
scn.PassCurrentPhaseActions();
|
||||
scn.FreepsDeclineAssignments();
|
||||
scn.ShadowAssignToMinions(new PhysicalCardImpl[]{gimli, runner}, new PhysicalCardImpl[]{frodo,scout});
|
||||
|
||||
scn.FreepsResolveSkirmish(gimli);
|
||||
scn.PassCurrentPhaseActions();
|
||||
scn.FreepsResolveActionOrder("Axe");
|
||||
assertTrue(scn.ShadowDecisionAvailable("choose"));
|
||||
|
||||
assertEquals(0, scn.GetWoundsOn(scout));
|
||||
scn.ShadowChooseMultipleChoiceOption("exert");
|
||||
assertEquals(1, scn.GetWoundsOn(scout));
|
||||
|
||||
scn.FreepsResolveSkirmish(frodo);
|
||||
scn.PassCurrentPhaseActions();
|
||||
scn.FreepsDeclineOptionalTrigger(); // ring
|
||||
|
||||
//Fierce assignment
|
||||
scn.PassCurrentPhaseActions();
|
||||
scn.FreepsAssignToMinions(gimli, scout);
|
||||
scn.FreepsResolveSkirmish(gimli);
|
||||
scn.PassCurrentPhaseActions();
|
||||
|
||||
var botcard = scn.GetShadowBottomOfDeck();
|
||||
assertEquals(Zone.DECK, botcard.getZone());
|
||||
assertEquals(2, scn.GetShadowDeckCount());
|
||||
assertEquals(1, scn.GetShadowDiscardCount());
|
||||
scn.FreepsResolveActionOrder("Axe");
|
||||
assertEquals(Zone.DISCARD, botcard.getZone());
|
||||
assertEquals(1, scn.GetShadowDeckCount());
|
||||
assertEquals(3, scn.GetShadowDiscardCount());//runner, scout, and a card discarded from the deck
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void AxeAffectsMultipleMinionsSeparately() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var axe = scn.GetFreepsCard("axe");
|
||||
var gimli = scn.GetFreepsCard("gimli");
|
||||
scn.FreepsMoveCharToTable(gimli);
|
||||
scn.AttachCardsTo(gimli, axe);
|
||||
|
||||
var scout = scn.GetShadowCard("scout");
|
||||
var runner = scn.GetShadowCard("runner");
|
||||
scn.ShadowMoveCharToTable(scout, runner);
|
||||
|
||||
scn.StartGame();
|
||||
|
||||
scn.SkipToPhase(Phase.ASSIGNMENT);
|
||||
|
||||
scn.PassCurrentPhaseActions();
|
||||
scn.FreepsDeclineAssignments();
|
||||
scn.ShadowAssignToMinions(gimli, scout, runner);
|
||||
|
||||
scn.FreepsResolveSkirmish(gimli);
|
||||
scn.FreepsUseCardAction(gimli);
|
||||
scn.ShadowPassCurrentPhaseAction();
|
||||
scn.FreepsUseCardAction(gimli);
|
||||
scn.ShadowPassCurrentPhaseAction();
|
||||
scn.FreepsPassCurrentPhaseAction();
|
||||
scn.FreepsResolveActionOrder("Axe");
|
||||
assertTrue(scn.ShadowDecisionAvailable("choose"));
|
||||
scn.ShadowChooseMultipleChoiceOption("exert");
|
||||
|
||||
assertEquals(2, scn.GetShadowDeckCount());
|
||||
assertEquals(0, scn.GetShadowDiscardCount());
|
||||
scn.FreepsResolveActionOrder("Axe");
|
||||
assertEquals(1, scn.GetShadowDeckCount());
|
||||
assertEquals(3, scn.GetShadowDiscardCount());//runner, scout, and a card discarded from the deck
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user