Merge pull request #564 from PlayersCouncil/bug/march-bugs

Yet even more card bug fixes
This commit is contained in:
Christian McCarty
2025-03-23 23:25:28 -05:00
committed by GitHub
19 changed files with 550 additions and 132 deletions

View File

@@ -114,10 +114,10 @@ class AutoZoom {
var targetShort = Math.min(maxShortSide, CardDisplay.TargetShort);
if(card.horizontal || card.effectivelyHorizontal()) {
this.cardDisplay.reloadFromCard(card, targetLong, targetShort);
this.cardDisplay.reloadFromCard(card, targetLong, targetShort, true);
}
else {
this.cardDisplay.reloadFromCard(card, targetShort, targetLong);
this.cardDisplay.reloadFromCard(card, targetShort, targetLong, true);
}
// get position and size of the reference image (or card hint):
@@ -206,7 +206,7 @@ class AutoZoom {
// However if shift IS held AND it's rotated, we act like it's not.
// This is basically XOR; when they are the same they cancel out,
// but when they are different they cause a rotation.
this.cardDisplay.setInvert(shiftHeld != invertShift);
//this.cardDisplay.setInvert(shiftHeld != invertShift);
}
setPreviewMessage(reversible) {

View File

@@ -55,6 +55,49 @@ class Card {
static GetAlternateImage(bpid) {
return bpid.includes("^", 2);
}
static GetImageFromCache(blueprintid, tengwar) {
if(tengwar)
return Card.GetTengwarImageFromCache(blueprintid);
return Card.GetBaseImageFromCache(blueprintid);
}
static GetBaseImageFromCache(blueprintid) {
let cached = Card.CardCache[blueprintid];
if(cached == null) {
cached = {
imageUrl:Card.getImageUrl(blueprintid),
backSideImageUrl:Card.getBackSideUrl(blueprintid),
incomplete:Card.isIncomplete(blueprintid),
errata:Card.isErrata(blueprintid)
};
Card.CardCache[blueprintid] = cached;
}
return cached;
}
static GetTengwarImageFromCache(blueprintid) {
let tengwarid = blueprintid + "T";
let cached = Card.CardCache[tengwarid];
if(cached == null) {
cached = {
imageUrl:Card.getImageUrl(tengwarid, true),
backSideImageUrl:Card.getBackSideUrl(tengwarid),
incomplete:Card.isIncomplete(tengwarid),
errata:Card.isErrata(tengwarid)
};
Card.CardCache[tengwarid] = cached;
}
return cached;
}
//blueprintId, zone, cardId, owner, siteNumber
constructor (blueprintId, testingText, backSideTestingText, zone, cardId, owner, siteNumber, upsideDown, onSide) {
@@ -106,32 +149,11 @@ class Card {
this.horizontal = Card.isHorizontal(this.bareBlueprint, this.zone);
if (this.bareBlueprint != "-1_1" && this.bareBlueprint != "-1_2" && Card.CardCache[this.bareBlueprint] != null) {
var cardFromCache = Card.CardCache[this.bareBlueprint];
this.imageUrl = cardFromCache.imageUrl;
this.backSideImageUrl = cardFromCache.backSideImageUrl;
this.incomplete = cardFromCache.incomplete;
this.errata = cardFromCache.errata;
} else {
this.imageUrl = Card.getImageUrl(this.bareBlueprint, this.tengwar);
this.backSideImageUrl = Card.getBackSideUrl(this.bareBlueprint);
this.incomplete = Card.isIncomplete(this.bareBlueprint);
var separator = this.bareBlueprint.indexOf("_");
var setNo = parseInt(this.bareBlueprint.substr(0, separator));
var cardNo = parseInt(this.bareBlueprint.substr(separator + 1));
this.errata = Card.getErrata(setNo, cardNo) != null;
if (this.bareBlueprint != "-1_1" && this.bareBlueprint != "-1_2") {
Card.CardCache[this.bareBlueprint] = {
imageUrl:this.imageUrl,
backSideImageUrl:this.backSideImageUrl,
incomplete:this.incomplete,
errata:this.errata
};
}
}
var cardFromCache = Card.GetImageFromCache(this.bareBlueprint, this.tengwar);
this.imageUrl = cardFromCache.imageUrl;
this.backSideImageUrl = cardFromCache.backSideImageUrl;
this.incomplete = cardFromCache.incomplete;
this.errata = cardFromCache.errata;
}
static getFixedImage (blueprintId) {
@@ -328,6 +350,14 @@ class Card {
return false;
}
static isErrata(blueprintId) {
var separator = blueprintId.indexOf("_");
var setNo = parseInt(blueprintId.substr(0, separator));
var cardNo = parseInt(blueprintId.substr(separator + 1));
return Card.getErrata(setNo, cardNo) != null;
}
static getImageUrl(blueprintId, tengwar, ignoreErrata) {
let image = Card.getFixedImage(blueprintId)
if (image != null)

View File

@@ -117,13 +117,21 @@ class CardDisplay {
this.backside = null;
}
reloadFromCard(card, maxWidth, maxHeight, noborder) {
reloadFromCard(card, maxWidth, maxHeight, ignoreTengwar) {
this.baseDiv.data("card", card);
this.currentBP = card.blueprintId;
this.frontside = card.imageUrl;
if(!this.frontside) {
this.frontside = Card.getImageUrl(this.currentBP);
if(ignoreTengwar && card.isTengwar()) {
this.currentBP = card.bareBlueprint;
this.frontside = Card.GetBaseImageFromCache(this.currentBP).imageUrl;
}
else {
this.currentBP = card.blueprintId;
this.frontside = card.imageUrl;
}
if(!this.frontside) {
this.frontside = Card.getImageUrl(this.currentBP);
}
let back = card.backSideImageUrl;
if(back && !back.includes("darkcardback") && !back.includes("lightcardback")) {
@@ -143,11 +151,9 @@ class CardDisplay {
this.backside = null;
}
}
this.reload(maxWidth, maxHeight, card.imageUrl,
card.horizontal || card.effectivelyHorizontal(), card.foil, noborder, card.testingText);
this.reload(maxWidth, maxHeight, this.frontside,
card.horizontal || card.effectivelyHorizontal(), card.foil, false, card.testingText);
}
reload(maxWidth, maxHeight, image, horizontal, foil, noborder, testingText) {

View File

@@ -140,10 +140,15 @@
}
{
type: If
check: {
type: HasMemory
memory: opponent
}
check: [
{
type: HasMemory
memory: opponent
}
{
type: SiteAvailableToControl
}
]
true: {
type: Optional
player: shadow

View File

@@ -109,9 +109,9 @@
"0_56", "0_57", "0_58", "0_59", "0_60"
]
blocks: [
Fellowship Block|The Fellowship of the Ring:1,Mines of Moria:2,Realms of the Elf-lords:3,V1 - Shadow of the Past:101
Towers Block|The Two Towers:4,Battle of Helm's Deep:5,Ents of Fangorn:6,V2 - King of the Golden Hall:102
king_block
pc_fotr_block
pc_ttt_block
pc_king_block
Additional Sets|Promotional:0,Reflections:9
Player's Council V-sets|V1 - Shadow of the Past:101,V2 - King of the Golden Hall:102
Player's Council Errata|The Fellowship of the Ring Errata:51,Mines of Moria Errata:52,Realms of the Elf-lords Errata:53,The Two Towers Errata:54,Battle of Helm's Deep Errata:55,Ents of Fangorn Errata:56,Return of the King Errata:57,Siege of Gondor Errata:58,Reflections Errata:59,Mount Doom Errata:60
@@ -121,6 +121,44 @@
51,52,53,54,55,56,57,58,59,60
]
}
{
name: Towers Block (PC)
code: pc_ttt_block
hall: false
order: 9
sites: TWO_TOWERS
cancelRingBearerSkirmish: true
sets: [
4, 5, 6
]
errataSets: [
54,55,66
]
blocks: [
ttt_block
]
}
{
name: King Block (PC)
code: pc_king_block
hall: false
order: 118
sites: KING
cancelRingBearerSkirmish: true
restricted: [
"7_49"
]
sets: [
7, 8, 10
]
errataSets: [
57,58,60
]
blocks: [
king_block
]
}
{
name: Latest PC Errata
code: pc_errata

View File

@@ -119,7 +119,7 @@
//Cave Troll of Moria, Scourge of the Black Pit FA
1x1_380
//Gimli, Vengeful Longbeard MW
1x101_67
1x101_103
#Easterling Captain FA
1x4_367
//The Tale of the Great Ring MW
@@ -393,7 +393,7 @@
//Treebeard, Enraged Shepherd MW
1x15_209
//Gimli, Vengeful Longbeard MW
1x101_67
1x101_103
//The Tale of the Great Ring MW
1x10_126
#Gandalf, The Grey Pilgrim MW
@@ -524,7 +524,7 @@
//Treebeard, Enraged Shepherd MW
1x15_209
//Gimli, Vengeful Longbeard MW
1x101_67
1x101_103
//The Tale of the Great Ring MW
1x10_126
#Gandalf, The Grey Pilgrim MW

View File

@@ -8,8 +8,7 @@ import com.gempukku.lotro.cards.build.field.FieldUtils;
import com.gempukku.lotro.cards.build.field.effect.EffectAppender;
import com.gempukku.lotro.cards.build.field.effect.EffectAppenderProducer;
import com.gempukku.lotro.cards.build.field.effect.appender.resolver.PlayerResolver;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.game.state.LotroGame;
import com.gempukku.lotro.logic.GameUtils;
import com.gempukku.lotro.logic.actions.CostToEffectAction;
import com.gempukku.lotro.logic.effects.TakeControlOfASiteEffect;
import com.gempukku.lotro.logic.timing.Effect;
@@ -26,18 +25,7 @@ public class TakeControlOfSite implements EffectAppenderProducer {
return new DelayedAppender() {
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
final LotroGame game = actionContext.getGame();
int maxUnoccupiedSite = Integer.MAX_VALUE;
for (String playerId : game.getGameState().getPlayerOrder().getAllPlayers())
maxUnoccupiedSite = Math.min(maxUnoccupiedSite, game.getGameState().getPlayerPosition(playerId) - 1);
for (int i = 1; i <= maxUnoccupiedSite; i++) {
final PhysicalCard site = game.getGameState().getSite(i);
if (site.getCardController() == null)
return true;
}
return false;
return GameUtils.anySiteAvailableToControl(actionContext.getGame());
}
@Override

View File

@@ -15,8 +15,15 @@ public class HasMemory implements RequirementProducer {
final String memory = FieldUtils.getString(object.get("memory"), "memory");
return actionContext ->
actionContext.getValueFromMemory(memory) != null && actionContext.getCardsFromMemory(memory) != null;
return actionContext -> {
try {
return actionContext.getValueFromMemory(memory) != null && actionContext.getCardsFromMemory(
memory) != null;
}
catch (IllegalArgumentException ex) {
return false;
}
};
}
}

View File

@@ -72,6 +72,7 @@ public class RequirementFactory {
requirementProducers.put("ringison", new RingIsOn());
requirementProducers.put("sarumanfirstsentenceactive", new SarumanFirstSentenceActive());
requirementProducers.put("shadowplayerreplacedcurrentsite", new ShadowPlayerReplacedCurrentSite());
requirementProducers.put("siteavailabletocontrol", new SiteAvailableToControl());
requirementProducers.put("twilightpoollessthan", new TwilightPoolLessThan());
requirementProducers.put("wasassignedtoskirmish", new WasAssignedToSkirmish());
requirementProducers.put("wasplayedfromzone", new WasPlayedFromZone());

View File

@@ -0,0 +1,19 @@
package com.gempukku.lotro.cards.build.field.effect.requirement;
import com.gempukku.lotro.cards.build.CardGenerationEnvironment;
import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
import com.gempukku.lotro.cards.build.Requirement;
import com.gempukku.lotro.cards.build.field.FieldUtils;
import com.gempukku.lotro.logic.GameUtils;
import org.json.simple.JSONObject;
public class SiteAvailableToControl implements RequirementProducer {
@Override
public Requirement getPlayRequirement(
JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(object);
return (actionContext) -> GameUtils.anySiteAvailableToControl(actionContext.getGame());
}
}

View File

@@ -348,4 +348,19 @@ public class GameUtils {
}
return total;
}
public static boolean anySiteAvailableToControl(LotroGame game) {
int maxUnoccupiedSite = Integer.MAX_VALUE;
for (String playerId : game.getGameState().getPlayerOrder().getAllPlayers()) {
maxUnoccupiedSite = Math.min(maxUnoccupiedSite, game.getGameState().getPlayerPosition(playerId) - 1);
}
for (int i = 1; i <= maxUnoccupiedSite; i++) {
final PhysicalCard site = game.getGameState().getSite(i);
if (site.getCardController() == null)
return true;
}
return false;
}
}

View File

@@ -37,7 +37,7 @@ public class ResolveSkirmishEffect extends AbstractEffect {
public Result getUpcomingResult(LotroGame game) {
final Skirmish skirmish = game.getGameState().getSkirmish();
if (skirmish.getShadowCharacters().size() == 0)
if (skirmish.getShadowCharacters().isEmpty())
return Result.SHADOW_LOSES;
if (skirmish.getFellowshipCharacter() == null)
return Result.FELLOWSHIP_LOSES;
@@ -76,7 +76,7 @@ public class ResolveSkirmishEffect extends AbstractEffect {
involving.addAll(skirmish.getShadowCharacters());
if (result == Result.FELLOWSHIP_LOSES) {
game.getGameState().sendMessage("Skirmish resolved with a normal win");
game.getGameState().sendMessage("Skirmish resolved with a normal win for Free Peoples");
game.getActionsEnvironment().emitEffectResult(new NormalSkirmishResult(skirmish.getShadowCharacters(), fpList(skirmish.getFellowshipCharacter()), skirmish.getRemovedFromSkirmish()));
for (PhysicalCard minion : skirmish.getShadowCharacters())
@@ -86,7 +86,7 @@ public class ResolveSkirmishEffect extends AbstractEffect {
for (PhysicalCard removedCharacter : skirmish.getRemovedFromSkirmish())
game.getActionsEnvironment().emitEffectResult(new CharacterLostSkirmishResult(CharacterLostSkirmishResult.SkirmishType.NORMAL, removedCharacter, involving));
} else if (result == Result.SHADOW_LOSES) {
game.getGameState().sendMessage("Skirmish resolved with a normal win");
game.getGameState().sendMessage("Skirmish resolved with a normal win for Shadow");
game.getActionsEnvironment().emitEffectResult(new NormalSkirmishResult(fpList(skirmish.getFellowshipCharacter()), skirmish.getShadowCharacters(), skirmish.getRemovedFromSkirmish()));
for (PhysicalCard minion : skirmish.getShadowCharacters())
@@ -96,7 +96,7 @@ public class ResolveSkirmishEffect extends AbstractEffect {
for (PhysicalCard removedCharacter : skirmish.getRemovedFromSkirmish())
game.getActionsEnvironment().emitEffectResult(new CharacterLostSkirmishResult(CharacterLostSkirmishResult.SkirmishType.NORMAL, removedCharacter, involving));
} else if (result == Result.FELLOWSHIP_OVERWHELMED) {
game.getGameState().sendMessage("Skirmish resolved with an overwhelm");
game.getGameState().sendMessage("Skirmish resolved with an overwhelm win for Shadow");
game.getActionsEnvironment().emitEffectResult(new OverwhelmSkirmishResult(skirmish.getShadowCharacters(), fpList(skirmish.getFellowshipCharacter()), skirmish.getRemovedFromSkirmish()));
for (PhysicalCard minion : skirmish.getShadowCharacters())
@@ -106,7 +106,7 @@ public class ResolveSkirmishEffect extends AbstractEffect {
for (PhysicalCard removedCharacter : skirmish.getRemovedFromSkirmish())
game.getActionsEnvironment().emitEffectResult(new CharacterLostSkirmishResult(CharacterLostSkirmishResult.SkirmishType.OVERWHELM, removedCharacter, involving));
} else {
game.getGameState().sendMessage("Skirmish resolved with an overwhelm");
game.getGameState().sendMessage("Skirmish resolved with an overwhelm win for Free Peoples");
game.getActionsEnvironment().emitEffectResult(new OverwhelmSkirmishResult(fpList(skirmish.getFellowshipCharacter()), skirmish.getShadowCharacters(), skirmish.getRemovedFromSkirmish()));
for (PhysicalCard minion : skirmish.getShadowCharacters())

View File

@@ -30,7 +30,7 @@ public class PlayoutSkirmishesGameProcess implements GameProcess {
final GameState gameState = game.getGameState();
final List<Assignment> assignments = gameState.getAssignments();
if (assignments.size() > 0) {
if (!assignments.isEmpty()) {
Set<PhysicalCard> nonLurkerSkirmishFps = new HashSet<>();
Set<PhysicalCard> lurkerSkirmishFps = new HashSet<>();
for (Assignment assignment : assignments) {
@@ -51,7 +51,7 @@ public class PlayoutSkirmishesGameProcess implements GameProcess {
SystemQueueAction chooseNextSkirmishAction = new SystemQueueAction();
Set<PhysicalCard> skirmishChoice;
if (nonLurkerSkirmishFps.size() > 0)
if (!nonLurkerSkirmishFps.isEmpty())
skirmishChoice = nonLurkerSkirmishFps;
else
skirmishChoice = lurkerSkirmishFps;

View File

@@ -3,7 +3,6 @@ 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.game.PhysicalCardImpl;
import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
import org.junit.Test;
@@ -18,8 +17,14 @@ public class Card_01_221_Tests
return new GenericCardTestHelper(
new HashMap<>()
{{
put("card", "1_221");
// put other cards in here as needed for the test case
put("paleblade", "1_221");
put("twk", "1_237");
put("gimli", "1_13");
put("condition1", "1_16");
put("condition2", "1_21");
put("condition3", "2_1");
put("condition4", "2_9");
}},
GenericCardTestHelper.FellowshipSites,
GenericCardTestHelper.FOTRFrodo,
@@ -45,7 +50,7 @@ public class Card_01_221_Tests
var scn = GetScenario();
var card = scn.GetFreepsCard("card");
var card = scn.GetFreepsCard("paleblade");
assertEquals("The Pale Blade", card.getBlueprint().getTitle());
assertNull(card.getBlueprint().getSubtitle());
@@ -58,18 +63,56 @@ public class Card_01_221_Tests
assertEquals(3, card.getBlueprint().getStrength());
}
// Uncomment any @Test markers below once this is ready to be used
//@Test
public void ThePaleBladeTest1() throws DecisionResultInvalidException, CardNotFoundException {
@Test
public void ThePaleBladeCanBeTriggeredMultipleTimesFromSameVictory() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var card = scn.GetFreepsCard("card");
scn.FreepsMoveCardToHand(card);
var twk = scn.GetShadowCard("twk");
var paleblade = scn.GetShadowCard("paleblade");
scn.ShadowMoveCharToTable(twk);
scn.AttachCardsTo(twk, paleblade);
var gimli = scn.GetFreepsCard("gimli");
var condition1 = scn.GetFreepsCard("condition1");
var condition2 = scn.GetFreepsCard("condition2");
var condition3 = scn.GetFreepsCard("condition3");
var condition4 = scn.GetFreepsCard("condition4");
scn.FreepsMoveCharToTable(gimli);
scn.FreepsMoveCardToSupportArea(condition1, condition2, condition3, condition4);
scn.StartGame();
scn.FreepsPlayCard(card);
scn.SkipToAssignments();
scn.FreepsAssignToMinions(gimli, twk);
scn.FreepsResolveSkirmish(gimli);
assertEquals(Zone.SUPPORT, condition1.getZone());
assertEquals(Zone.SUPPORT, condition2.getZone());
assertEquals(Zone.SUPPORT, condition3.getZone());
assertEquals(Zone.SUPPORT, condition4.getZone());
assertEquals(0, scn.GetWoundsOn(twk));
scn.PassCurrentPhaseActions();
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertEquals(1, scn.GetWoundsOn(twk));
scn.ShadowChooseCard(condition1);
assertEquals(Zone.DISCARD, condition1.getZone());
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertEquals(2, scn.GetWoundsOn(twk));
scn.ShadowChooseCard(condition2);
assertEquals(Zone.DISCARD, condition2.getZone());
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertEquals(3, scn.GetWoundsOn(twk));
scn.ShadowChooseCard(condition3);
assertEquals(Zone.DISCARD, condition3.getZone());
assertFalse(scn.ShadowHasOptionalTriggerAvailable());
assertEquals(Phase.ASSIGNMENT, scn.GetCurrentPhase());
assertEquals(2, scn.GetTwilight());
}
}

View File

@@ -3,7 +3,6 @@ package com.gempukku.lotro.cards.official.set04;
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;
@@ -18,8 +17,10 @@ public class Card_04_004_Tests
return new GenericCardTestHelper(
new HashMap<>()
{{
put("card", "4_4");
// put other cards in here as needed for the test case
put("band", "4_4");
put("sam", "1_311");
put("gimli", "1_13");
}},
GenericCardTestHelper.FellowshipSites,
GenericCardTestHelper.FOTRFrodo,
@@ -47,7 +48,7 @@ public class Card_04_004_Tests
var scn = GetScenario();
var card = scn.GetFreepsCard("card");
var card = scn.GetFreepsCard("band");
assertEquals("Band of Wild Men", card.getBlueprint().getTitle());
assertNull(card.getBlueprint().getSubtitle());
@@ -62,18 +63,75 @@ public class Card_04_004_Tests
assertEquals(3, card.getBlueprint().getSiteNumber());
}
// Uncomment any @Test markers below once this is ready to be used
//@Test
public void BandofWildMenTest1() throws DecisionResultInvalidException, CardNotFoundException {
@Test
public void BandofWildMenBecomesFierceIfWinningSkirmishNormally() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var card = scn.GetFreepsCard("card");
scn.FreepsMoveCardToHand(card);
var band = scn.GetShadowCard("band");
scn.ShadowMoveCharToTable(band);
var gimli = scn.GetFreepsCard("gimli");
scn.FreepsMoveCharToTable(gimli);
scn.StartGame();
scn.FreepsPlayCard(card);
scn.SkipToAssignments();
scn.FreepsAssignToMinions(gimli, band);
scn.FreepsResolveSkirmish(gimli);
scn.PassCurrentPhaseActions();
assertEquals(5, scn.GetTwilight());
assertFalse(scn.hasKeyword(band, Keyword.FIERCE));
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertTrue(scn.hasKeyword(band, Keyword.FIERCE));
}
@Test
public void BandofWildMenBecomesFierceIfWinningSkirmishWithOverwhelm() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var band = scn.GetShadowCard("band");
scn.ShadowMoveCharToTable(band);
var sam = scn.GetFreepsCard("sam");
scn.FreepsMoveCharToTable(sam);
scn.StartGame();
scn.SkipToAssignments();
scn.FreepsAssignToMinions(sam, band);
scn.FreepsResolveSkirmish(sam);
scn.PassCurrentPhaseActions();
assertFalse(scn.hasKeyword(band, Keyword.FIERCE));
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertTrue(scn.hasKeyword(band, Keyword.FIERCE));
}
@Test
public void BandofWildMenBecomesFierceIfWinningSkirmishKillsOpponentWithWound() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var band = scn.GetShadowCard("band");
scn.ShadowMoveCharToTable(band);
var gimli = scn.GetFreepsCard("gimli");
scn.FreepsMoveCharToTable(gimli);
scn.StartGame();
scn.AddWoundsToChar(gimli, 2);
scn.SkipToAssignments();
scn.FreepsAssignToMinions(gimli, band);
scn.FreepsResolveSkirmish(gimli);
scn.PassCurrentPhaseActions();
assertFalse(scn.hasKeyword(band, Keyword.FIERCE));
assertTrue(scn.ShadowHasOptionalTriggerAvailable());
scn.ShadowAcceptOptionalTrigger();
assertTrue(scn.hasKeyword(band, Keyword.FIERCE));
}
}

View File

@@ -1,9 +1,9 @@
package com.gempukku.lotro.cards.official.set08;
import com.gempukku.lotro.cards.GenericCardTestHelper;
import com.gempukku.lotro.common.*;
import com.gempukku.lotro.common.CardType;
import com.gempukku.lotro.common.Phase;
import com.gempukku.lotro.game.CardNotFoundException;
import com.gempukku.lotro.game.PhysicalCardImpl;
import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
import org.junit.Test;
@@ -18,10 +18,21 @@ public class Card_08_119_Tests
return new GenericCardTestHelper(
new HashMap<>()
{{
put("card", "8_119");
// put other cards in here as needed for the test case
put("merry", "4_310");
put("pippin", "4_314");
put("sam", "1_311");
}},
new HashMap<>() {{
put("site1", "7_330");
put("site2", "7_335");
put("site3", "8_117");
put("site4", "7_342");
put("site5", "8_119"); //
put("site6", "7_350");
put("site7", "8_120");
put("site8", "10_120");
put("site9", "7_360");
}},
GenericCardTestHelper.FellowshipSites,
GenericCardTestHelper.FOTRFrodo,
GenericCardTestHelper.RulingRing
);
@@ -44,10 +55,7 @@ public class Card_08_119_Tests
*/
var scn = GetScenario();
//Use this once you have set the deck up properly
//var card = scn.GetFreepsSite(5);
var card = scn.GetFreepsCard("card");
var card = scn.GetFreepsSite(5);
assertEquals("Crashed Gate", card.getBlueprint().getTitle());
assertNull(card.getBlueprint().getSubtitle());
@@ -57,18 +65,134 @@ public class Card_08_119_Tests
assertEquals(5, card.getBlueprint().getSiteNumber());
}
// Uncomment any @Test markers below once this is ready to be used
//@Test
public void CrashedGateTest1() throws DecisionResultInvalidException, CardNotFoundException {
@Test
public void CrashedGateOffers3ThreatsChoiceWhenBothAvailable() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var card = scn.GetFreepsCard("card");
scn.FreepsMoveCardToHand(card);
var site1 = scn.GetFreepsSite(1);
//Threat limit is now 4
scn.FreepsMoveCharToTable("sam", "merry", "pippin");
scn.StartGame();
scn.FreepsPlayCard(card);
scn.SkipToSite(4);
scn.SkipToPhase(Phase.REGROUP);
assertEquals(7, scn.GetTwilight());
assertEquals(0, scn.GetThreats());
assertFalse(scn.IsSiteControlled(site1));
assertEquals(2, scn.FreepsGetChoiceCount());
assertTrue(scn.FreepsDecisionAvailable("Choose action to perform"));
scn.FreepsChooseMultipleChoiceOption("threat");
assertEquals(3, scn.GetThreats());
assertFalse(scn.IsSiteControlled(site1));
}
@Test
public void CrashedGateOffersSiteControlChoiceWhenBothAvailable() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var site1 = scn.GetFreepsSite(1);
//Threat limit is now 4
scn.FreepsMoveCharToTable("sam", "merry", "pippin");
scn.StartGame();
scn.SkipToSite(4);
scn.SkipToPhase(Phase.REGROUP);
assertEquals(0, scn.GetThreats());
assertFalse(scn.IsSiteControlled(site1));
assertEquals(2, scn.FreepsGetChoiceCount());
assertTrue(scn.FreepsDecisionAvailable("Choose action to perform"));
scn.FreepsChooseMultipleChoiceOption("opponent");
assertTrue(scn.ShadowDecisionAvailable("Would you like to take control of a site?"));
scn.ShadowChooseYes();
assertEquals(0, scn.GetThreats());
assertTrue(scn.IsSiteControlled(site1));
}
@Test
public void CrashedGateOffersOpponentChoiceWhenSiteControlNotAvailable() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var site1 = scn.GetFreepsSite(1);
//Threat limit is now 4
scn.FreepsMoveCharToTable("sam", "merry", "pippin");
scn.StartGame();
scn.SkipToSite(4);
scn.FreepsPassCurrentPhaseAction();
scn.ShadowTakeControlOfSite();
scn.ShadowTakeControlOfSite();
scn.ShadowTakeControlOfSite();
scn.SkipToPhase(Phase.REGROUP);
assertEquals(0, scn.GetThreats());
assertEquals(2, scn.FreepsGetChoiceCount());
assertTrue(scn.FreepsDecisionAvailable("Choose action to perform"));
scn.FreepsChooseMultipleChoiceOption("opponent");
assertFalse(scn.ShadowDecisionAvailable("Would you like to take control of a site?"));
assertTrue(scn.FreepsAnyDecisionsAvailable());
}
@Test
public void CrashedGateChoosesOpponentChoiceAutomaticallyWhen3ThreatsCantBeAdded() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var site1 = scn.GetFreepsSite(1);
//Threat limit is now 4
scn.FreepsMoveCharToTable("sam", "merry", "pippin");
scn.StartGame();
scn.SkipToSite(4);
scn.FreepsPassCurrentPhaseAction();
//Only 2 threat slots left
scn.AddThreats(2);
scn.SkipToPhase(Phase.REGROUP);
assertEquals(2, scn.GetThreats());
assertFalse(scn.FreepsDecisionAvailable("Choose action to perform"));
assertTrue(scn.ShadowDecisionAvailable("Would you like to take control of a site?"));
}
@Test
public void CrashedGateChoosesOpponentChoiceAutomaticallyWhen3ThreatsCantBeAddedAndNoSiteAvailableToControl() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var site1 = scn.GetFreepsSite(1);
//Threat limit is now 4
scn.FreepsMoveCharToTable("sam", "merry", "pippin");
scn.StartGame();
scn.SkipToSite(4);
scn.FreepsPassCurrentPhaseAction();
//Only 2 threat slots left
scn.AddThreats(2);
scn.ShadowTakeControlOfSite();
scn.ShadowTakeControlOfSite();
scn.ShadowTakeControlOfSite();
scn.SkipToPhase(Phase.REGROUP);
assertEquals(2, scn.GetThreats());
assertFalse(scn.FreepsDecisionAvailable("Choose action to perform"));
assertFalse(scn.ShadowDecisionAvailable("Would you like to take control of a site?"));
assertTrue(scn.FreepsAnyDecisionsAvailable());
}
}

View File

@@ -20,7 +20,7 @@ public class Card_11_060_Tests
return new GenericCardTestHelper(
new HashMap<>()
{{
put("card", "11_60");
put("quality", "11_60");
// put other cards in here as needed for the test case
}},
GenericCardTestHelper.FellowshipSites,
@@ -41,12 +41,14 @@ public class Card_11_060_Tests
* Twilight Cost: 2
* Type: Event
* Subtype: Skirmish
* Game Text: Exert any number of [gondor] companions who have total resistance 12 or more to make a minion skirmishing a [gondor] companion strength -3 for each companion exerted this way.
* Game Text: Exert any number of [gondor] companions who have total resistance 12
* or more to make a minion skirmishing a [gondor] companion strength -3 for each
* companion exerted this way.
*/
var scn = GetScenario();
var card = scn.GetFreepsCard("card");
var card = scn.GetFreepsCard("quality");
assertEquals("The Highest Quality", card.getBlueprint().getTitle());
assertNull(card.getBlueprint().getSubtitle());
@@ -58,17 +60,16 @@ public class Card_11_060_Tests
assertEquals(2, card.getBlueprint().getTwilightCost());
}
// Uncomment any @Test markers below once this is ready to be used
//@Test
public void TheHighestQualityTest1() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var card = scn.GetFreepsCard("card");
scn.FreepsMoveCardToHand(card);
scn.StartGame();
scn.FreepsPlayCard(card);
var quality = scn.GetFreepsCard("quality");
// scn.FreepsMoveCardToHand(card);
//
// scn.StartGame();
// scn.FreepsPlayCard(card);
assertEquals(2, scn.GetTwilight());
}

View File

@@ -23,6 +23,7 @@ public class Card_12_184_Tests
put("fodder1", "1_302");
put("fodder2", "1_307");
put("fodder3", "1_310");
}},
GenericCardTestHelper.FellowshipSites,
GenericCardTestHelper.FOTRFrodo,
@@ -76,7 +77,8 @@ public class Card_12_184_Tests
var frodo = scn.GetRingBearer();
var fodder1 = scn.GetFreepsCard("fodder1");
var fodder2 = scn.GetFreepsCard("fodder2");
scn.FreepsMoveCharToTable(fodder1, fodder2);
var fodder3 = scn.GetFreepsCard("fodder3");
scn.FreepsMoveCharToTable(fodder1, fodder2, fodder3);
scn.StartGame();
scn.SkipToPhase(Phase.ASSIGNMENT);
@@ -103,8 +105,10 @@ public class Card_12_184_Tests
assertEquals(Phase.ASSIGNMENT, scn.GetCurrentPhase());
scn.PassCurrentPhaseActions();
scn.FreepsDeclineAssignments();
scn.ShadowDeclineAssignments();
scn.FreepsAssignToMinions(fodder3, twk);
scn.FreepsResolveSkirmish(fodder3);
assertEquals(Phase.SKIRMISH, scn.GetCurrentPhase());
scn.PassCurrentPhaseActions();
assertEquals(Phase.REGROUP, scn.GetCurrentPhase());
}

View File

@@ -3,7 +3,6 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set02;
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;
@@ -18,8 +17,10 @@ public class Card_02_076_ErrataTests
return new GenericCardTestHelper(
new HashMap<>()
{{
put("card", "52_76");
// put other cards in here as needed for the test case
put("sam", "1_311");
put("helpless", "52_76");
put("toto", "10_68");
put("nelya","1_233");
}},
GenericCardTestHelper.FellowshipSites,
GenericCardTestHelper.FOTRFrodo,
@@ -45,7 +46,7 @@ public class Card_02_076_ErrataTests
var scn = GetScenario();
var card = scn.GetFreepsCard("card");
var card = scn.GetFreepsCard("helpless");
assertEquals("Helpless", card.getBlueprint().getTitle());
assertNull(card.getBlueprint().getSubtitle());
@@ -57,18 +58,96 @@ public class Card_02_076_ErrataTests
assertEquals(1, card.getBlueprint().getTwilightCost());
}
// Uncomment any @Test markers below once this is ready to be used
//@Test
public void HelplessTest1() throws DecisionResultInvalidException, CardNotFoundException {
@Test
public void HelplessBlocksSpecialAbilities() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var card = scn.GetFreepsCard("card");
scn.FreepsMoveCardToHand(card);
var frodo = scn.GetRingBearer();
var sam = scn.GetFreepsCard("sam");
scn.FreepsMoveCharToTable(sam);
var helpless = scn.GetShadowCard("helpless");
var nelya = scn.GetShadowCard("nelya");
scn.ShadowAttachCardsTo(sam, helpless);
scn.ShadowMoveCharToTable(nelya);
scn.StartGame();
scn.FreepsPlayCard(card);
//The Fellowship burden-removing special ability should be blocked
assertFalse(scn.FreepsActionAvailable(sam));
assertEquals(1, scn.GetTwilight());
scn.SkipToAssignments();
scn.FreepsAssignToMinions(frodo, nelya);
scn.FreepsResolveSkirmish(frodo);
scn.PassCurrentPhaseActions();
//The Response ring-bearer special ability should also be blocked
assertFalse(scn.FreepsHasOptionalTriggerAvailable());
}
@Test
public void HelplessDoesNotBlockAbilitiesWhileInSupportArea() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var frodo = scn.GetRingBearer();
var sam = scn.GetFreepsCard("sam");
scn.FreepsMoveCharToTable(sam);
var helpless = scn.GetShadowCard("helpless");
var nelya = scn.GetShadowCard("nelya");
scn.ShadowMoveCardToSupportArea(helpless);
scn.ShadowMoveCharToTable(nelya);
scn.StartGame();
//The Fellowship burden-removing special ability should NOT be blocked
assertTrue(scn.FreepsActionAvailable(sam));
scn.SkipToAssignments();
scn.FreepsAssignToMinions(frodo, nelya);
scn.FreepsResolveSkirmish(frodo);
scn.PassCurrentPhaseActions();
//The Response ring-bearer special ability should also NOT be blocked
assertTrue(scn.FreepsHasOptionalTriggerAvailable());
}
@Test
public void HelplessManeuverActionTransfersToRingBoundCompanion() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var frodo = scn.GetRingBearer();
var sam = scn.GetFreepsCard("sam");
scn.FreepsMoveCharToTable(sam);
var helpless = scn.GetShadowCard("helpless");
var toto = scn.GetShadowCard("toto");
var nelya = scn.GetShadowCard("nelya");
scn.ShadowMoveCardToSupportArea(helpless);
scn.ShadowMoveCharToTable(toto, nelya);
scn.StartGame();
scn.SkipToPhase(Phase.MANEUVER);
scn.FreepsPassCurrentPhaseAction();
assertTrue(scn.ShadowActionAvailable(helpless));
assertEquals(0, scn.GetWoundsOn(toto));
assertEquals(0, scn.GetWoundsOn(nelya));
assertEquals(Zone.SUPPORT, helpless.getZone());
scn.ShadowUseCardAction(helpless);
assertEquals(2, scn.ShadowGetCardChoiceCount());
scn.ShadowChooseCard(toto);
assertEquals(1, scn.GetWoundsOn(toto));
assertEquals(0, scn.GetWoundsOn(nelya));
//Can go on either Sam or Frodo
assertEquals(2, scn.ShadowGetCardChoiceCount());
scn.ShadowChooseCard(frodo);
assertEquals(Zone.ATTACHED, helpless.getZone());
assertEquals(frodo, helpless.getAttachedTo());
}
}