Orc Butchery errata tests
This commit is contained in:
@@ -379,44 +379,87 @@
|
||||
twilight: 0
|
||||
type: event
|
||||
keyword: response
|
||||
requires: {
|
||||
type: canSpot
|
||||
filter: culture(sauron),orc,inSkirmish
|
||||
}
|
||||
effects: {
|
||||
type: responseEvent
|
||||
trigger: {
|
||||
type: killed
|
||||
filter: companion
|
||||
}
|
||||
effect: {
|
||||
type: repeat
|
||||
amount: {
|
||||
type: ForEachInDeadPile
|
||||
filter: any
|
||||
effects: [
|
||||
{
|
||||
type: responseEvent
|
||||
trigger: {
|
||||
type: killed
|
||||
filter: companion
|
||||
}
|
||||
requires: {
|
||||
type: canSpot
|
||||
filter: culture(sauron),orc,inSkirmish
|
||||
}
|
||||
effect: {
|
||||
type: choice
|
||||
player: freeps
|
||||
texts: [
|
||||
Add a burden
|
||||
Discard the top 4 cards of your draw deck
|
||||
]
|
||||
effects: [
|
||||
{
|
||||
type: addBurdens
|
||||
amount: 1
|
||||
}
|
||||
{
|
||||
type: discardTopCardsFromDeck
|
||||
deck: freeps
|
||||
count: 4
|
||||
forced: false
|
||||
}
|
||||
]
|
||||
type: repeat
|
||||
amount: {
|
||||
type: ForEachInDeadPile
|
||||
filter: any
|
||||
}
|
||||
effect: {
|
||||
type: choice
|
||||
player: freeps
|
||||
texts: [
|
||||
Add a burden
|
||||
Discard the top 4 cards of your draw deck
|
||||
]
|
||||
effects: [
|
||||
{
|
||||
type: addBurdens
|
||||
amount: 1
|
||||
}
|
||||
{
|
||||
type: discardTopCardsFromDeck
|
||||
deck: freeps
|
||||
count: 4
|
||||
forced: false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
type: responseEvent
|
||||
requires: {
|
||||
type: cantSpot
|
||||
filter: culture(sauron),orc,inSkirmish
|
||||
}
|
||||
trigger: {
|
||||
type: TakesWound
|
||||
filter: companion,zone(dead)
|
||||
source: culture(sauron),orc
|
||||
}
|
||||
effect: {
|
||||
type: repeat
|
||||
amount: {
|
||||
type: ForEachInDeadPile
|
||||
filter: any
|
||||
}
|
||||
effect: {
|
||||
type: choice
|
||||
player: freeps
|
||||
texts: [
|
||||
Add a burden
|
||||
Discard the top 4 cards of your draw deck
|
||||
]
|
||||
effects: [
|
||||
{
|
||||
type: addBurdens
|
||||
amount: 1
|
||||
}
|
||||
{
|
||||
type: discardTopCardsFromDeck
|
||||
deck: freeps
|
||||
count: 4
|
||||
forced: false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
gametext: If a companion is killed by a [sauron] Orc, for each card in the dead pile the Free Peoples player must choose to add a burden or discard 4 cards from the top of their draw deck.
|
||||
lore: For sport, Orcs hew cruelly at the bodies of those they slay.
|
||||
promotext: ""
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.json.simple.JSONObject;
|
||||
public class ResponseEventEffectProcessor implements EffectProcessor {
|
||||
@Override
|
||||
public void processEffect(JSONObject value, BuiltLotroCardBlueprint blueprint, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
|
||||
FieldUtils.validateAllowedFields(value, "trigger", "cost", "effect");
|
||||
FieldUtils.validateAllowedFields(value, "trigger", "requires", "cost", "effect");
|
||||
|
||||
final JSONObject[] triggerArray = FieldUtils.getObjectArray(value.get("trigger"), "trigger");
|
||||
|
||||
@@ -21,7 +21,7 @@ public class ResponseEventEffectProcessor implements EffectProcessor {
|
||||
|
||||
DefaultActionSource triggerActionSource = new DefaultActionSource();
|
||||
triggerActionSource.addPlayRequirement(triggerChecker);
|
||||
EffectUtils.processCostsAndEffects(value, environment, triggerActionSource);
|
||||
EffectUtils.processRequirementsCostsAndEffects(value, environment, triggerActionSource);
|
||||
|
||||
if (before) {
|
||||
blueprint.appendOptionalInHandBeforeAction(triggerActionSource);
|
||||
|
||||
@@ -16,7 +16,7 @@ public class AboutToTakeWound implements TriggerCheckerProducer {
|
||||
FieldUtils.validateAllowedFields(value, "source", "filter");
|
||||
|
||||
String source = FieldUtils.getString(value.get("source"), "source", "any");
|
||||
String filter = FieldUtils.getString(value.get("filter"), "source");
|
||||
String filter = FieldUtils.getString(value.get("filter"), "filter");
|
||||
|
||||
final FilterableSource sourceFilter = environment.getFilterFactory().generateFilter(source, environment);
|
||||
final FilterableSource affectedFilter = environment.getFilterFactory().generateFilter(filter, environment);
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.gempukku.lotro.cards.build.FilterableSource;
|
||||
import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
|
||||
import com.gempukku.lotro.cards.build.field.FieldUtils;
|
||||
import com.gempukku.lotro.common.Filterable;
|
||||
import com.gempukku.lotro.filters.Filters;
|
||||
import com.gempukku.lotro.game.PhysicalCard;
|
||||
import com.gempukku.lotro.logic.timing.TriggerConditions;
|
||||
import com.gempukku.lotro.logic.timing.results.WoundResult;
|
||||
@@ -14,12 +15,15 @@ import org.json.simple.JSONObject;
|
||||
public class TakesWound implements TriggerCheckerProducer {
|
||||
@Override
|
||||
public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
|
||||
FieldUtils.validateAllowedFields(value, "filter", "memorize");
|
||||
FieldUtils.validateAllowedFields(value, "filter", "source", "memorize");
|
||||
|
||||
String source = FieldUtils.getString(value.get("source"), "source", "any");
|
||||
String filter = FieldUtils.getString(value.get("filter"), "filter", "any");
|
||||
|
||||
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);
|
||||
final FilterableSource sourceFilter = environment.getFilterFactory().generateFilter(source, environment);
|
||||
final FilterableSource targetFilterable = environment.getFilterFactory().generateFilter(filter, environment);
|
||||
|
||||
return new TriggerChecker() {
|
||||
@Override
|
||||
@@ -29,8 +33,15 @@ public class TakesWound implements TriggerCheckerProducer {
|
||||
|
||||
@Override
|
||||
public boolean accepts(ActionContext actionContext) {
|
||||
final Filterable filterable = filterableSource.getFilterable(actionContext);
|
||||
final Filterable filterable = targetFilterable.getFilterable(actionContext);
|
||||
final Filterable sourceFilterable = sourceFilter.getFilterable(actionContext);
|
||||
final boolean result = TriggerConditions.forEachWounded(actionContext.getGame(), actionContext.getEffectResult(), filterable);
|
||||
if(result && !source.equals("any")) {
|
||||
var sources = ((WoundResult) actionContext.getEffectResult()).getSources();
|
||||
if(sources.stream().noneMatch(x -> Filters.and(sourceFilterable).accepts(actionContext.getGame(), x))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (result && memorize != null) {
|
||||
final PhysicalCard woundedCard = ((WoundResult) actionContext.getEffectResult()).getWoundedCard();
|
||||
actionContext.setCardMemory(memorize, woundedCard);
|
||||
|
||||
@@ -233,6 +233,16 @@ public class GenericCardTestHelper extends AbstractAtTest {
|
||||
return actions.stream().anyMatch(x -> x.toLowerCase().contains(lowerAction));
|
||||
}
|
||||
|
||||
public Boolean FreepsChoiceAvailable(String choice) { return ChoiceAvailable(P1, choice); }
|
||||
public Boolean ShadowChoiceAvailable(String choice) { return ChoiceAvailable(P2, choice); }
|
||||
public Boolean ChoiceAvailable(String player, String choice) {
|
||||
List<String> actions = GetADParamAsList(player, "results");
|
||||
if(actions == null)
|
||||
return false;
|
||||
String lowerChoice = choice.toLowerCase();
|
||||
return actions.stream().anyMatch(x -> x.toLowerCase().contains(lowerChoice));
|
||||
}
|
||||
|
||||
public Boolean FreepsAnyActionsAvailable() { return AnyActionsAvailable(P1); }
|
||||
public Boolean ShadowAnyActionsAvailable() { return AnyActionsAvailable(P2); }
|
||||
public Boolean AnyActionsAvailable(String player) {
|
||||
@@ -498,7 +508,7 @@ public class GenericCardTestHelper extends AbstractAtTest {
|
||||
Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.SUPPORT));
|
||||
}
|
||||
public void ShadowMoveCardToSupportArea(String...names) {
|
||||
Arrays.stream(names).forEach(name -> ShadowMoveCardToSupportArea(GetFreepsCard(name)));
|
||||
Arrays.stream(names).forEach(name -> ShadowMoveCardToSupportArea(GetShadowCard(name)));
|
||||
}
|
||||
public void ShadowMoveCardToSupportArea(PhysicalCardImpl...cards) {
|
||||
Arrays.stream(cards).forEach(card -> MoveCardToZone(P2, card, Zone.SUPPORT));
|
||||
@@ -790,6 +800,7 @@ public class GenericCardTestHelper extends AbstractAtTest {
|
||||
return _game.getModifiersQuerying().getStrength(_game, card);
|
||||
}
|
||||
public int GetVitality(PhysicalCardImpl card) { return _game.getModifiersQuerying().getVitality(_game, card); }
|
||||
public int GetResistance(PhysicalCardImpl card) { return _game.getModifiersQuerying().getResistance(_game, card); }
|
||||
public int GetMinionSiteNumber(PhysicalCardImpl card) { return _game.getModifiersQuerying().getMinionSiteNumber(_game, card); }
|
||||
public int GetGeneralSiteNumber(PhysicalCardImpl card)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
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.logic.decisions.DecisionResultInvalidException;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class Card_01_265_ErrataTests
|
||||
{
|
||||
|
||||
protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
|
||||
return new GenericCardTestHelper(
|
||||
new HashMap<>()
|
||||
{{
|
||||
put("butchery", "51_265");
|
||||
put("slayer", "3_93");
|
||||
put("scavengers", "1_179");
|
||||
|
||||
put("sam", "2_114");
|
||||
put("sword", "1_299");
|
||||
put("guard1", "1_7");
|
||||
put("guard2", "1_7");
|
||||
}},
|
||||
GenericCardTestHelper.FellowshipSites,
|
||||
GenericCardTestHelper.FOTRFrodo,
|
||||
GenericCardTestHelper.FOTRRing
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void OrcButcheryStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
|
||||
/**
|
||||
* Set: 1
|
||||
* Title: Orc Butchery
|
||||
* Unique: False
|
||||
* Side: SHADOW
|
||||
* Culture: Sauron
|
||||
* Twilight Cost: 0
|
||||
* Type: event
|
||||
* Subtype: Response
|
||||
* Game Text: If a companion is killed by a [sauron] Orc, then for each card in the dead pile the Free Peoples
|
||||
* player must choose to add a burden or discard 4 cards from the top of their draw deck.
|
||||
*/
|
||||
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var butchery = scn.GetFreepsCard("butchery");
|
||||
|
||||
assertFalse(butchery.getBlueprint().isUnique());
|
||||
assertEquals(Side.SHADOW, butchery.getBlueprint().getSide());
|
||||
assertEquals(Culture.SAURON, butchery.getBlueprint().getCulture());
|
||||
assertEquals(CardType.EVENT, butchery.getBlueprint().getCardType());
|
||||
assertTrue(scn.HasKeyword(butchery, Keyword.RESPONSE));
|
||||
assertEquals(0, butchery.getBlueprint().getTwilightCost());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ButcheryIsTriggeredBySkirmishOverwhelmKill() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var butchery = scn.GetShadowCard("butchery");
|
||||
var slayer = scn.GetShadowCard("slayer");
|
||||
scn.ShadowMoveCardToHand(butchery);
|
||||
scn.ShadowMoveCharToTable(slayer);
|
||||
|
||||
var sam = scn.GetFreepsCard("sam");
|
||||
scn.FreepsMoveCharToTable(sam);
|
||||
|
||||
scn.StartGame();
|
||||
scn.SkipToAssignments();
|
||||
|
||||
scn.FreepsAssignToMinions(sam, slayer);
|
||||
scn.FreepsResolveSkirmish(sam);
|
||||
scn.PassCurrentPhaseActions();
|
||||
|
||||
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ButcheryIsTriggeredBySkirmishWoundKill() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var butchery = scn.GetShadowCard("butchery");
|
||||
var slayer = scn.GetShadowCard("slayer");
|
||||
scn.ShadowMoveCardToHand(butchery);
|
||||
scn.ShadowMoveCharToTable(slayer);
|
||||
|
||||
var sam = scn.GetFreepsCard("sam");
|
||||
scn.FreepsMoveCharToTable(sam);
|
||||
scn.FreepsAttachCardsTo(sam, "sword");
|
||||
|
||||
scn.StartGame();
|
||||
scn.AddWoundsToChar(sam, 3);
|
||||
scn.SkipToAssignments();
|
||||
|
||||
scn.FreepsAssignToMinions(sam, slayer);
|
||||
scn.FreepsResolveSkirmish(sam);
|
||||
scn.PassCurrentPhaseActions();
|
||||
|
||||
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ButcheryIsTriggeredByDirectWoundAbility() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var butchery = scn.GetShadowCard("butchery");
|
||||
var slayer = scn.GetShadowCard("slayer");
|
||||
scn.ShadowMoveCardToHand(butchery);
|
||||
scn.ShadowMoveCharToTable(slayer);
|
||||
|
||||
var sam = scn.GetFreepsCard("sam");
|
||||
scn.FreepsMoveCharToTable(sam);
|
||||
|
||||
scn.StartGame();
|
||||
scn.AddWoundsToChar(sam, 3);
|
||||
scn.SkipToAssignments();
|
||||
scn.FreepsDeclineAssignments();
|
||||
scn.ShadowDeclineAssignments();
|
||||
|
||||
assertEquals(Phase.REGROUP, scn.GetCurrentPhase());
|
||||
scn.FreepsPassCurrentPhaseAction();
|
||||
scn.ShadowUseCardAction(slayer);
|
||||
|
||||
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ButcheryForcesBurdenIfLessThan4TopDeckCards() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var butchery = scn.GetShadowCard("butchery");
|
||||
var slayer = scn.GetShadowCard("slayer");
|
||||
scn.ShadowMoveCardToHand(butchery);
|
||||
scn.ShadowMoveCharToTable(slayer);
|
||||
|
||||
var sam = scn.GetFreepsCard("sam");
|
||||
scn.FreepsMoveCharToTable(sam);
|
||||
scn.FreepsMoveCardToDiscard("sword", "guard1", "guard2");
|
||||
|
||||
scn.StartGame();
|
||||
scn.SkipToAssignments();
|
||||
|
||||
scn.FreepsAssignToMinions(sam, slayer);
|
||||
scn.FreepsResolveSkirmish(sam);
|
||||
scn.PassCurrentPhaseActions();
|
||||
|
||||
assertEquals(3, scn.GetFreepsDeckCount());
|
||||
assertEquals(1, scn.GetBurdens());
|
||||
assertEquals(Zone.HAND, butchery.getZone());
|
||||
scn.ShadowAcceptOptionalTrigger();
|
||||
assertEquals(2, scn.GetBurdens());
|
||||
assertEquals(Zone.DISCARD, butchery.getZone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ButcheryOffersChoiceOfBurdenOr4TopDeck() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var butchery = scn.GetShadowCard("butchery");
|
||||
var slayer = scn.GetShadowCard("slayer");
|
||||
scn.ShadowMoveCardToHand(butchery);
|
||||
scn.ShadowMoveCharToTable(slayer);
|
||||
|
||||
var sam = scn.GetFreepsCard("sam");
|
||||
scn.FreepsMoveCharToTable(sam);
|
||||
|
||||
scn.StartGame();
|
||||
scn.SkipToAssignments();
|
||||
|
||||
scn.FreepsAssignToMinions(sam, slayer);
|
||||
scn.FreepsResolveSkirmish(sam);
|
||||
scn.PassCurrentPhaseActions();
|
||||
|
||||
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
|
||||
scn.ShadowAcceptOptionalTrigger();
|
||||
assertTrue(scn.FreepsDecisionAvailable("Choose action to perform"));
|
||||
assertTrue(scn.FreepsChoiceAvailable("Add a burden"));
|
||||
assertTrue(scn.FreepsChoiceAvailable("Discard the top 4 cards of your draw deck"));
|
||||
|
||||
assertEquals(6, scn.GetFreepsDeckCount());
|
||||
scn.FreepsChooseMultipleChoiceOption("Discard");
|
||||
assertEquals(2, scn.GetFreepsDeckCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ButcheryForcesChoicePerDeadPileDenizen() throws DecisionResultInvalidException, CardNotFoundException {
|
||||
//Pre-game setup
|
||||
var scn = GetScenario();
|
||||
|
||||
var butchery = scn.GetShadowCard("butchery");
|
||||
var slayer = scn.GetShadowCard("slayer");
|
||||
scn.ShadowMoveCardToHand(butchery);
|
||||
scn.ShadowMoveCharToTable(slayer);
|
||||
|
||||
var sam = scn.GetFreepsCard("sam");
|
||||
scn.FreepsMoveCharToTable(sam);
|
||||
scn.FreepsMoveCardToDeadPile("guard1", "guard2");
|
||||
|
||||
scn.StartGame();
|
||||
scn.SkipToAssignments();
|
||||
|
||||
scn.FreepsAssignToMinions(sam, slayer);
|
||||
scn.FreepsResolveSkirmish(sam);
|
||||
scn.PassCurrentPhaseActions();
|
||||
|
||||
assertEquals(1, scn.GetBurdens());
|
||||
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
|
||||
scn.ShadowAcceptOptionalTrigger();
|
||||
assertTrue(scn.FreepsChoiceAvailable("Add a burden"));
|
||||
scn.FreepsChooseMultipleChoiceOption("Burden");
|
||||
|
||||
assertEquals(2, scn.GetBurdens());
|
||||
assertTrue(scn.FreepsChoiceAvailable("Add a burden"));
|
||||
scn.FreepsChooseMultipleChoiceOption("Burden");
|
||||
|
||||
assertEquals(3, scn.GetBurdens());
|
||||
assertTrue(scn.FreepsChoiceAvailable("Add a burden"));
|
||||
scn.FreepsChooseMultipleChoiceOption("Burden");
|
||||
assertEquals(4, scn.GetBurdens());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user