Added absolute value coercer. Fixed Treebeard, Enraged Shephard causing a game crash when winning against Enquea TOTO.

This commit is contained in:
Christian 'ketura' McCarty
2025-03-21 22:18:06 -05:00
parent 3cb492657f
commit 87c490256d
3 changed files with 105 additions and 21 deletions

View File

@@ -718,14 +718,17 @@
player: shadow
select: choose(minion)
count: {
type: subtract
firstNumber: {
type: forEachStrength
filter: self
}
secondNumber: {
type: forEachStrength
filter: memory(losers)
type: abs
value: {
type: subtract
firstNumber: {
type: forEachStrength
filter: self
}
secondNumber: {
type: forEachStrength
filter: memory(losers)
}
}
}
}

View File

@@ -183,6 +183,22 @@ public class ValueResolver {
return true;
}
};
} else if (type.equalsIgnoreCase("abs")) {
FieldUtils.validateAllowedFields(object, "value");
ValueSource source = resolveEvaluator(object.get("value"), 0, environment);
return new ValueSource() {
@Override
public Evaluator getEvaluator(ActionContext actionContext) {
var evaluator = source.getEvaluator(actionContext);
return (game, cardAffected) -> Math.abs(evaluator.evaluateExpression(game, cardAffected));
}
@Override
public boolean canPreEvaluate() {
return source.canPreEvaluate();
}
};
}
/**

View File

@@ -1,9 +1,11 @@
package com.gempukku.lotro.cards.official.set15;
import com.gempukku.lotro.cards.GenericCardTestHelper;
import com.gempukku.lotro.common.*;
import com.gempukku.lotro.common.CardType;
import com.gempukku.lotro.common.Culture;
import com.gempukku.lotro.common.Race;
import com.gempukku.lotro.common.Side;
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 +20,13 @@ public class Card_15_038_Tests
return new GenericCardTestHelper(
new HashMap<>()
{{
put("card", "15_38");
// put other cards in here as needed for the test case
put("treebeard", "15_38");
put("orc1", "1_272"); //strength 10
put("orc2", "1_262");
put("orc3", "1_266");
put("orc4", "1_267");
put("enduring", "10_68");
}},
GenericCardTestHelper.FellowshipSites,
GenericCardTestHelper.FOTRFrodo,
@@ -42,12 +49,14 @@ public class Card_15_038_Tests
* Strength: 12
* Vitality: 4
* Resistance: 6
* Game Text: To play, spot 3 [gandalf] companions.<br>Each time Treebeard wins a skirmish, the first Shadow player must exert X minions, where X is the difference between Treebeard's strength and the losing character's strength.
* Game Text: To play, spot 3 [gandalf] companions.<br>Each time Treebeard wins a skirmish, the first Shadow
* player must exert X minions, where X is the difference between Treebeard's strength and the losing
* character's strength.
*/
var scn = GetScenario();
var card = scn.GetFreepsCard("card");
var card = scn.GetFreepsCard("treebeard");
assertEquals("Treebeard", card.getBlueprint().getTitle());
assertEquals("Enraged Shepherd", card.getBlueprint().getSubtitle());
@@ -62,18 +71,74 @@ public class Card_15_038_Tests
assertEquals(6, card.getBlueprint().getResistance());
}
// Uncomment any @Test markers below once this is ready to be used
//@Test
public void TreebeardTest1() throws DecisionResultInvalidException, CardNotFoundException {
@Test
public void TreebeardExerts2MinionsAgainstStrength10Minion() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var card = scn.GetFreepsCard("card");
scn.FreepsMoveCardToHand(card);
var treebeard = scn.GetFreepsCard("treebeard");
scn.FreepsMoveCharToTable(treebeard);
var orc1 = scn.GetShadowCard("orc1");
var orc2 = scn.GetShadowCard("orc2");
var orc3 = scn.GetShadowCard("orc3");
var orc4 = scn.GetShadowCard("orc4");
scn.ShadowMoveCharToTable(orc1, orc2, orc3, orc4);
scn.StartGame();
scn.FreepsPlayCard(card);
assertEquals(5, scn.GetTwilight());
scn.SkipToAssignments();
scn.FreepsAssignToMinions(treebeard, orc1); //10 strength orc
scn.ShadowDeclineAssignments();
scn.FreepsResolveSkirmish(treebeard);
scn.PassCurrentPhaseActions();
scn.FreepsResolveRuleFirst();
//Treebeard is strength 12, the orc is 10, so 2 minions must be exerted
assertEquals(2, scn.ShadowGetChoiceMin());
assertEquals(3, scn.GetShadowCardChoiceCount());
assertEquals(0, scn.GetWoundsOn(orc2));
assertEquals(0, scn.GetWoundsOn(orc3));
scn.ShadowChooseCards(orc2, orc3);
assertEquals(1, scn.GetWoundsOn(orc2));
assertEquals(1, scn.GetWoundsOn(orc3));
}
@Test
public void TreebeardDoesNotCrashIfAgainstEnduringMinionOf11Strength() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var treebeard = scn.GetFreepsCard("treebeard");
scn.FreepsMoveCharToTable(treebeard);
var enduring = scn.GetShadowCard("enduring");
var orc1 = scn.GetShadowCard("orc1"); //only here to slow down choices
scn.ShadowMoveCharToTable(enduring, orc1);
scn.StartGame();
scn.SkipToAssignments();
scn.FreepsAssignToMinions(treebeard, enduring); //11 strength enduring nazgul
scn.ShadowDeclineAssignments();
scn.FreepsResolveSkirmish(treebeard);
scn.PassCurrentPhaseActions();
assertEquals(11, scn.GetStrength(enduring));
assertEquals(0, scn.GetWoundsOn((enduring)));
scn.FreepsResolveRuleFirst();
assertEquals(13, scn.GetStrength(enduring));
assertEquals(1, scn.GetWoundsOn((enduring))); // Skirmish loss
//Treebeard is strength 12, the nazgul is 11. However, 1 wound makes it 13
// at the time this is evaluated, so it should be an absolute calculation.
//With only 1 minion in play, it gets the exertion
assertNotEquals(-1, scn.ShadowGetChoiceMin());
assertEquals(1, scn.ShadowGetChoiceMin());
assertEquals(2, scn.GetShadowCardChoiceCount());
scn.ShadowChooseCard(enduring);
assertEquals(2, scn.GetWoundsOn((enduring)));
}
}