Fixed Ulaire Nertea causing Ford of Bruinen to apply its discount to all Nazgul played by Nertea's ability

This commit is contained in:
Christian 'ketura' McCarty
2024-10-17 22:19:22 -05:00
parent 7d065bd550
commit 5505bd346e
6 changed files with 281 additions and 167 deletions

View File

@@ -978,10 +978,22 @@
site: 3 site: 3
effects: { effects: {
type: trigger type: trigger
optional: true
trigger: { trigger: {
type: played type: played
filter: self filter: self
} }
requires: [
{
type: CanSpot
filter: companion
count: 5
}
{
type: PlayableFromDiscard
filter: minion
}
]
effect: [ effect: [
{ {
type: MemorizeValue type: MemorizeValue
@@ -989,61 +1001,47 @@
value: yes value: yes
} }
{ {
type: conditional type: Repeat
requires: [ amount: {
{ type: forEachYouCanSpot
type: CanSpot filter: companion
filter: companion over: 4
count: 5 }
}
{
type: PlayableFromDiscard
filter: minion
}
]
effect: { effect: {
type: Repeat type: conditional
amount: { requires: [
type: forEachYouCanSpot {
filter: companion type: MemoryIs
over: 4 memory: choice
} value: yes
effect: { }
type: conditional {
requires: [ type: HasCardInDiscard
{ filter: playable,minion
type: MemoryIs }
memory: choice ]
value: yes effect: [
} {
{ type: chooseYesOrNo
type: HasCardInDiscard player: you
filter: playable,minion text: Would you like to play a minion from your discard?
} memorize: choice
] }
effect: [ {
{ type: conditional
type: chooseYesOrNo requires: [
player: you {
text: Would you like to play a minion from your discard? type: MemoryIs
memorize: choice memory: choice
} value: yes
{
type: conditional
requires: [
{
type: MemoryIs
memory: choice
value: yes
}
]
effect: {
type: playCardFromDiscard
filter: choose(minion)
} }
]
effect: {
type: playCardFromDiscard
filter: choose(minion)
} }
] }
} ]
} }
} }
] ]

View File

@@ -526,7 +526,10 @@
type: site type: site
site: 3 site: 3
block: fellowship block: fellowship
keyword: river keywords: [
river
Sanctuary
]
direction: right direction: right
effects: [ effects: [
{ {
@@ -534,11 +537,8 @@
modifier: { modifier: {
type: modifyCost type: modifyCost
requires: { requires: {
type: not type: perTurnLimit
requires: { limit: 1
type: hasInZoneData
filter: self
}
} }
filter: nazgul filter: nazgul
amount: -5 amount: -5
@@ -549,41 +549,10 @@
trigger: { trigger: {
type: played type: played
filter: nazgul filter: nazgul
memorize: playedNazgul
}
requires: {
type: not
requires: {
type: hasInZoneData
filter: self
}
} }
effect: { effect: {
type: appendCardIdsToWhileInZone type: incrementPerTurnLimit
memory: playedNazgul limit: 1
}
}
{
type: trigger
trigger: {
type: endOfTurn
}
effect: {
type: resetWhileInZoneData
}
}
{
type: trigger
trigger: {
type: movesFrom
filter: self
}
requires: {
type: phase
phase: regroup
}
effect: {
type: resetWhileInZoneData
} }
} }
] ]
@@ -900,17 +869,15 @@
site: 6 site: 6
block: fellowship block: fellowship
direction: left direction: left
keywords: Sanctuary
effects: [ effects: [
{ {
type: modifier type: modifier
modifier: { modifier: {
type: modifyCost type: modifyCost
requires: { requires: {
type: not type: perPhaseLimit
requires: { limit: 1
type: hasInZoneData
filter: self
}
} }
filter: culture(moria),orc filter: culture(moria),orc
amount: -2 amount: -2
@@ -923,26 +890,9 @@
filter: culture(moria),orc filter: culture(moria),orc
memorize: playedOrc memorize: playedOrc
} }
requires: {
type: not
requires: {
type: hasInZoneData
filter: self
}
}
effect: { effect: {
type: appendCardIdsToWhileInZone type: incrementPerPhaseLimit
memory: playedOrc limit: 1
}
}
{
type: trigger
trigger: {
type: endOfPhase
phase: shadow
}
effect: {
type: resetWhileInZoneData
} }
} }
] ]

View File

@@ -26,10 +26,22 @@
site: 3 site: 3
effects: { effects: {
type: trigger type: trigger
optional: true
trigger: { trigger: {
type: played type: played
filter: self filter: self
} }
requires: [
{
type: CanSpot
filter: companion
count: 5
}
{
type: PlayableFromDiscard
filter: minion
}
]
effect: [ effect: [
{ {
type: MemorizeValue type: MemorizeValue
@@ -37,61 +49,47 @@
value: yes value: yes
} }
{ {
type: conditional type: Repeat
requires: [ amount: {
{ type: forEachYouCanSpot
type: CanSpot filter: companion
filter: companion over: 4
count: 5 }
}
{
type: PlayableFromDiscard
filter: unique,culture(wraith),minion
}
]
effect: { effect: {
type: Repeat type: conditional
amount: { requires: [
type: forEachYouCanSpot {
filter: companion type: MemoryIs
over: 4 memory: choice
} value: yes
effect: { }
type: conditional {
requires: [ type: HasCardInDiscard
{ filter: playable,unique,culture(wraith),minion
type: MemoryIs }
memory: choice ]
value: yes effect: [
} {
{ type: chooseYesOrNo
type: HasCardInDiscard player: you
filter: playable,unique,culture(wraith),minion text: Would you like to play a unique WRAITH minion from your discard?
} memorize: choice
] }
effect: [ {
{ type: conditional
type: chooseYesOrNo requires: [
player: you {
text: Would you like to play a unique WRAITH minion from your discard? type: MemoryIs
memorize: choice memory: choice
} value: yes
{
type: conditional
requires: [
{
type: MemoryIs
memory: choice
value: yes
}
]
effect: {
type: playCardFromDiscard
filter: choose(unique,culture(wraith),minion)
} }
]
effect: {
type: playCardFromDiscard
filter: choose(unique,culture(wraith),minion)
} }
] }
} ]
} }
} }
] ]

View File

@@ -108,6 +108,8 @@ public class Card_01_234_Tests
scn.FreepsPassCurrentPhaseAction(); scn.FreepsPassCurrentPhaseAction();
scn.ShadowPlayCard(nertea); scn.ShadowPlayCard(nertea);
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertTrue(scn.ShadowDecisionAvailable("play a minion")); assertTrue(scn.ShadowDecisionAvailable("play a minion"));
scn.ShadowChooseYes(); scn.ShadowChooseYes();
//twk, attea, rit, and runner //twk, attea, rit, and runner
@@ -139,6 +141,8 @@ public class Card_01_234_Tests
scn.FreepsPassCurrentPhaseAction(); scn.FreepsPassCurrentPhaseAction();
scn.ShadowPlayCard(nertea); scn.ShadowPlayCard(nertea);
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertTrue(scn.ShadowDecisionAvailable("play a minion")); assertTrue(scn.ShadowDecisionAvailable("play a minion"));
scn.ShadowChooseYes(); scn.ShadowChooseYes();
//twk, attea, rit, and runner //twk, attea, rit, and runner
@@ -176,6 +180,8 @@ public class Card_01_234_Tests
scn.FreepsPassCurrentPhaseAction(); scn.FreepsPassCurrentPhaseAction();
scn.ShadowPlayCard(nertea); scn.ShadowPlayCard(nertea);
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertTrue(scn.ShadowDecisionAvailable("play a minion")); assertTrue(scn.ShadowDecisionAvailable("play a minion"));
scn.ShadowChooseNo(); scn.ShadowChooseNo();
@@ -201,6 +207,8 @@ public class Card_01_234_Tests
scn.FreepsPassCurrentPhaseAction(); scn.FreepsPassCurrentPhaseAction();
scn.ShadowPlayCard(nertea); scn.ShadowPlayCard(nertea);
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertTrue(scn.ShadowDecisionAvailable("play a minion")); assertTrue(scn.ShadowDecisionAvailable("play a minion"));
scn.ShadowChooseYes(); scn.ShadowChooseYes();
assertEquals(4, scn.GetShadowCardChoiceCount()); assertEquals(4, scn.GetShadowCardChoiceCount());

View File

@@ -0,0 +1,152 @@
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_338_Tests
{
protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException {
return new GenericCardTestHelper(
new HashMap<>()
{{
put("twk", "1_237");
put("lemenya", "1_232");
put("nertea", "1_234");
put("guard1", "1_7");
put("guard2", "1_7");
put("guard3", "1_7");
put("guard4", "1_7");
}},
new HashMap<>() {{
put("site1", "1_319");
put("site2", "1_327");
put("site3", "1_338");
put("site4", "1_343");
put("site5", "1_349");
put("site6", "1_351");
put("site7", "1_353");
put("site8", "1_356");
put("site9", "1_360");
}},
GenericCardTestHelper.FOTRFrodo,
GenericCardTestHelper.RulingRing
);
}
@Test
public void FordofBruinenStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException {
/**
* Set: 1
* Name: Ford of Bruinen
* Unique: False
* Side:
* Culture:
* Shadow Number: 0
* Type: Sanctuary
* Subtype:
* Site Number: 3
* Game Text: <b>River</b>. <b>Sanctuary</b>. The twilight cost of the first Nazgûl played to Ford of Bruinen each turn is -5.
*/
var scn = GetScenario();
var card = scn.GetFreepsSite(3);
assertEquals("Ford of Bruinen", card.getBlueprint().getTitle());
assertNull(card.getBlueprint().getSubtitle());
assertFalse(card.getBlueprint().isUnique());
assertEquals(CardType.SITE, card.getBlueprint().getCardType());
assertTrue(scn.HasKeyword(card, Keyword.RIVER));
assertTrue(scn.HasKeyword(card, Keyword.SANCTUARY));
assertEquals(0, card.getBlueprint().getTwilightCost());
assertEquals(3, card.getBlueprint().getSiteNumber());
}
@Test
public void FordofBruinenOnlyDiscountsTheFirstNazgul() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var ford = scn.GetShadowSite(3);
var twk = scn.GetShadowCard("twk");
var lemenya = scn.GetShadowCard("lemenya");
scn.ShadowMoveCardToHand(twk, lemenya);
scn.StartGame();
//Start our test on 2 so that moving to 3 is the first thing we do
scn.SkipToSite(2);
scn.SetTwilight(9);
scn.FreepsPassCurrentPhaseAction();
assertEquals(ford, scn.GetCurrentSite());
//9 manual + 1 from the fellowship moving
assertEquals(10, scn.GetTwilight());
scn.ShadowPlayCard(twk);
//TWK costs 8 (no roaming), discounted by 5 to 3 total
//10 - 3
assertEquals(7, scn.GetTwilight());
scn.ShadowPlayCard(lemenya);
//Lemenya costs 4, should have no discount
//7 - 4
assertEquals(3, scn.GetTwilight());
}
@Test
public void FordDiscountsNerteaButNotNerteasTrigger() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var ford = scn.GetShadowSite(3);
var twk = scn.GetShadowCard("twk");
var nertea = scn.GetShadowCard("nertea");
scn.ShadowMoveCardToHand(nertea);
scn.ShadowMoveCardToDiscard(twk);
scn.FreepsMoveCharToTable("guard1", "guard2", "guard3", "guard4");
scn.StartGame();
//Start our test on 2 so that moving to 3 is the first thing we do
scn.SkipToSite(2);
scn.SetTwilight(5);
scn.FreepsPassCurrentPhaseAction();
assertEquals(ford, scn.GetCurrentSite());
//5 manual + 5 from the fellowship moving
assertEquals(10, scn.GetTwilight());
scn.ShadowPlayCard(nertea);
//Nertea costs 4 (no roaming), discounted by 5 to 0 total
//10 - 0
assertEquals(10, scn.GetTwilight());
//Nertea pulls a minion from discard, which should not get discounted
// as Nertea should have consumed the only discount
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertTrue(scn.ShadowDecisionAvailable("play a minion"));
scn.ShadowChooseYes();
scn.ShadowChooseCardBPFromSelection(twk);
//TWK costs 8, should not be discounted
//10 - 8
assertEquals(2, scn.GetTwilight());
}
}

View File

@@ -108,6 +108,8 @@ public class Card_01_234_ErrataTests
scn.FreepsPassCurrentPhaseAction(); scn.FreepsPassCurrentPhaseAction();
scn.ShadowPlayCard(nertea); scn.ShadowPlayCard(nertea);
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion")); assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion"));
scn.ShadowChooseYes(); scn.ShadowChooseYes();
//twk and attea, but not rit or runner //twk and attea, but not rit or runner
@@ -138,6 +140,8 @@ public class Card_01_234_ErrataTests
scn.FreepsPassCurrentPhaseAction(); scn.FreepsPassCurrentPhaseAction();
scn.ShadowPlayCard(nertea); scn.ShadowPlayCard(nertea);
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion")); assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion"));
scn.ShadowChooseYes(); scn.ShadowChooseYes();
//twk and attea, but not rit or runner //twk and attea, but not rit or runner
@@ -174,6 +178,8 @@ public class Card_01_234_ErrataTests
scn.FreepsPassCurrentPhaseAction(); scn.FreepsPassCurrentPhaseAction();
scn.ShadowPlayCard(nertea); scn.ShadowPlayCard(nertea);
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion")); assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion"));
scn.ShadowChooseNo(); scn.ShadowChooseNo();
@@ -199,6 +205,8 @@ public class Card_01_234_ErrataTests
scn.FreepsPassCurrentPhaseAction(); scn.FreepsPassCurrentPhaseAction();
scn.ShadowPlayCard(nertea); scn.ShadowPlayCard(nertea);
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion")); assertTrue(scn.ShadowDecisionAvailable("play a unique WRAITH minion"));
scn.ShadowChooseYes(); scn.ShadowChooseYes();
//twk and attea, but not rit or runner //twk and attea, but not rit or runner