Overhauled assignment definitions

- Assignments now require 3 flags: whether an assignment is to ignore existing assignments (false for actions, false for freeps assignments, true for shadow assignments, true for mordor assassin), whether an assignment is to ignore defender bonuses (true for actions, false for freeps assignments, true for shadow assignments, true for mordor assassin), and whether allies are to be considered valid targets (false for everything except for certain abilities)
This commit is contained in:
Christian 'ketura' McCarty
2024-12-17 09:30:45 -06:00
parent 13ff6be1d0
commit 284e44976c
12 changed files with 130 additions and 43 deletions

View File

@@ -213,6 +213,7 @@
type: AssignFpCharacterToSkirmish type: AssignFpCharacterToSkirmish
fpCharacter: choose(or(ally,and(unbound,companion))) fpCharacter: choose(or(ally,and(unbound,companion)))
minion: choose(uruk-hai, MaxTwilight(memory(removed))) minion: choose(uruk-hai, MaxTwilight(memory(removed)))
ignoreAllyLocation: true
} }
} }
] ]

View File

@@ -21,7 +21,8 @@ import java.util.Collection;
public class AssignFpCharacterToSkirmish implements EffectAppenderProducer { public class AssignFpCharacterToSkirmish implements EffectAppenderProducer {
@Override @Override
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(effectObject, "player", "fpCharacter", "minion", "memorizeMinion", "memorizeFPCharacter", "ignoreExistingAssignments", "preventCost", "preventText", "insteadEffect"); FieldUtils.validateAllowedFields(effectObject, "player", "fpCharacter", "minion", "memorizeMinion",
"memorizeFPCharacter", "ignoreExistingAssignments", "ignoreDefender", "ignoreAllyLocation", "preventCost", "preventText", "insteadEffect");
final String player = FieldUtils.getString(effectObject.get("player"), "player", "you"); final String player = FieldUtils.getString(effectObject.get("player"), "player", "you");
final String fpCharacter = FieldUtils.getString(effectObject.get("fpCharacter"), "fpCharacter", "choose(any)"); final String fpCharacter = FieldUtils.getString(effectObject.get("fpCharacter"), "fpCharacter", "choose(any)");
@@ -40,6 +41,8 @@ public class AssignFpCharacterToSkirmish implements EffectAppenderProducer {
final String minionMemory = FieldUtils.getString(effectObject.get("memorizeMinion"), "memorizeMinion", "_tempMinion"); final String minionMemory = FieldUtils.getString(effectObject.get("memorizeMinion"), "memorizeMinion", "_tempMinion");
final String fpCharacterMemory = FieldUtils.getString(effectObject.get("memorizeFPCharacter"), "memorizeFPCharacter", "_tempFpCharacter"); final String fpCharacterMemory = FieldUtils.getString(effectObject.get("memorizeFPCharacter"), "memorizeFPCharacter", "_tempFpCharacter");
final boolean ignoreExistingAssignments = FieldUtils.getBoolean(effectObject.get("ignoreExistingAssignments"), "ignoreExistingAssignments", false); final boolean ignoreExistingAssignments = FieldUtils.getBoolean(effectObject.get("ignoreExistingAssignments"), "ignoreExistingAssignments", false);
final boolean ignoreDefender = FieldUtils.getBoolean(effectObject.get("ignoreDefender"), "ignoreDefender", true);
final boolean ignoreAllyLocation = FieldUtils.getBoolean(effectObject.get("ignoreAllyLocation"), "ignoreAllyLocation", false);
final PlayerSource playerSource = PlayerResolver.resolvePlayer(player); final PlayerSource playerSource = PlayerResolver.resolvePlayer(player);
@@ -52,7 +55,7 @@ public class AssignFpCharacterToSkirmish implements EffectAppenderProducer {
final String assigningPlayer = playerSource.getPlayer(actionContext); final String assigningPlayer = playerSource.getPlayer(actionContext);
Side assigningSide = GameUtils.getSide(actionContext.getGame(), assigningPlayer); Side assigningSide = GameUtils.getSide(actionContext.getGame(), assigningPlayer);
final Filterable filter = minionFilter.getFilterable(actionContext); final Filterable filter = minionFilter.getFilterable(actionContext);
return Filters.assignableToSkirmishAgainst(assigningSide, filter, ignoreExistingAssignments, false); return Filters.assignableToSkirmishAgainst(assigningSide, filter, ignoreExistingAssignments, ignoreDefender, ignoreAllyLocation);
}, fpCharacterMemory, player, "Choose character to assign to skirmish", environment)); }, fpCharacterMemory, player, "Choose character to assign to skirmish", environment));
result.addEffectAppender( result.addEffectAppender(
CardResolver.resolveCard(minion, CardResolver.resolveCard(minion,
@@ -60,7 +63,7 @@ public class AssignFpCharacterToSkirmish implements EffectAppenderProducer {
final String assigningPlayer = playerSource.getPlayer(actionContext); final String assigningPlayer = playerSource.getPlayer(actionContext);
Side assigningSide = GameUtils.getSide(actionContext.getGame(), assigningPlayer); Side assigningSide = GameUtils.getSide(actionContext.getGame(), assigningPlayer);
final Collection<? extends PhysicalCard> fpChar = actionContext.getCardsFromMemory(fpCharacterMemory); final Collection<? extends PhysicalCard> fpChar = actionContext.getCardsFromMemory(fpCharacterMemory);
return Filters.assignableToSkirmishAgainst(assigningSide, Filters.in(fpChar), ignoreExistingAssignments, false); return Filters.assignableToSkirmishAgainst(assigningSide, Filters.in(fpChar), ignoreExistingAssignments, ignoreDefender, ignoreAllyLocation);
}, minionMemory, player, "Choose minion to assign to character", environment)); }, minionMemory, player, "Choose minion to assign to character", environment));
DelayedAppender assignAppender = new DelayedAppender() { DelayedAppender assignAppender = new DelayedAppender() {
@@ -70,8 +73,7 @@ public class AssignFpCharacterToSkirmish implements EffectAppenderProducer {
final Collection<? extends PhysicalCard> fpChar = actionContext.getCardsFromMemory(fpCharacterMemory); final Collection<? extends PhysicalCard> fpChar = actionContext.getCardsFromMemory(fpCharacterMemory);
final Collection<? extends PhysicalCard> minion = actionContext.getCardsFromMemory(minionMemory); final Collection<? extends PhysicalCard> minion = actionContext.getCardsFromMemory(minionMemory);
if (fpChar.size() == 1 && minion.size() == 1) { if (fpChar.size() == 1 && minion.size() == 1) {
AssignmentEffect effect = new AssignmentEffect(assigningPlayer, fpChar.iterator().next(), minion.iterator().next()); AssignmentEffect effect = new AssignmentEffect(assigningPlayer, fpChar.iterator().next(), minion.iterator().next(), ignoreExistingAssignments, ignoreDefender, ignoreAllyLocation);
effect.setIgnoreSingleMinionRestriction(ignoreExistingAssignments);
return effect; return effect;
} else { } else {
return null; return null;

View File

@@ -39,7 +39,7 @@ public class StartSkirmish implements EffectAppenderProducer {
final String assigningPlayer = playerSource.getPlayer(actionContext); final String assigningPlayer = playerSource.getPlayer(actionContext);
Side assigningSide = GameUtils.getSide(actionContext.getGame(), assigningPlayer); Side assigningSide = GameUtils.getSide(actionContext.getGame(), assigningPlayer);
final Filterable filter = minionFilter.getFilterable(actionContext); final Filterable filter = minionFilter.getFilterable(actionContext);
return Filters.assignableToSkirmishAgainst(assigningSide, filter, true, false); return Filters.assignableToSkirmishAgainst(assigningSide, filter, true, true, false);
}, "_fpCharacterTemp", "you", "Choose character to assign to skirmish", environment)); }, "_fpCharacterTemp", "you", "Choose character to assign to skirmish", environment));
result.addEffectAppender( result.addEffectAppender(
CardResolver.resolveCard(against, CardResolver.resolveCard(against,
@@ -47,7 +47,7 @@ public class StartSkirmish implements EffectAppenderProducer {
final String assigningPlayer = playerSource.getPlayer(actionContext); final String assigningPlayer = playerSource.getPlayer(actionContext);
Side assigningSide = GameUtils.getSide(actionContext.getGame(), assigningPlayer); Side assigningSide = GameUtils.getSide(actionContext.getGame(), assigningPlayer);
final Collection<? extends PhysicalCard> fpChar = actionContext.getCardsFromMemory("_tempFpCharacter"); final Collection<? extends PhysicalCard> fpChar = actionContext.getCardsFromMemory("_tempFpCharacter");
return Filters.assignableToSkirmishAgainst(assigningSide, Filters.in(fpChar), true, false); return Filters.assignableToSkirmishAgainst(assigningSide, Filters.in(fpChar), true, true, false);
}, "_minionTemp", "you", "Choose minion to assign to character", environment)); }, "_minionTemp", "you", "Choose minion to assign to character", environment));
result.addEffectAppender( result.addEffectAppender(
new DelayedAppender() { new DelayedAppender() {
@@ -55,7 +55,7 @@ public class StartSkirmish implements EffectAppenderProducer {
protected List<? extends Effect> createEffects(boolean cost, CostToEffectAction action, ActionContext actionContext) { protected List<? extends Effect> createEffects(boolean cost, CostToEffectAction action, ActionContext actionContext) {
final Collection<? extends PhysicalCard> fpChar = actionContext.getCardsFromMemory("_fpCharacterTemp"); final Collection<? extends PhysicalCard> fpChar = actionContext.getCardsFromMemory("_fpCharacterTemp");
final Collection<? extends PhysicalCard> minions = actionContext.getCardsFromMemory("_minionTemp"); final Collection<? extends PhysicalCard> minions = actionContext.getCardsFromMemory("_minionTemp");
if (fpChar.size() == 1 && minions.size() > 0) { if (fpChar.size() == 1 && !minions.isEmpty()) {
new AdditionalSkirmishPhaseEffect(fpChar.iterator().next(), minions); new AdditionalSkirmishPhaseEffect(fpChar.iterator().next(), minions);
} }
return null; return null;

View File

@@ -14,6 +14,7 @@ import com.gempukku.lotro.logic.modifiers.evaluator.Evaluator;
import com.gempukku.lotro.logic.timing.RuleUtils; import com.gempukku.lotro.logic.timing.RuleUtils;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
public class Filters { public class Filters {
private static final Map<CardType, Filter> _typeFilterMap = new HashMap<>(); private static final Map<CardType, Filter> _typeFilterMap = new HashMap<>();
@@ -192,16 +193,17 @@ public class Filters {
} }
public static Filter assignableToSkirmishAgainst(final Side assignedBySide, final Filterable againstFilter) { public static Filter assignableToSkirmishAgainst(final Side assignedBySide, final Filterable againstFilter) {
return assignableToSkirmishAgainst(assignedBySide, againstFilter, false, false); return assignableToSkirmishAgainst(assignedBySide, againstFilter, false, false, false);
} }
public static Filter assignableToSkirmishAgainst(final Side assignedBySide, final Filterable againstFilter, final boolean ignoreExistingAssignments, final boolean allowAllyToSkirmish) { public static Filter assignableToSkirmishAgainst(final Side assignedBySide, final Filterable againstFilter,
final boolean ignoreExistingAssignments, final boolean ignoreDefender, final boolean allowAllyToSkirmish) {
return Filters.and( return Filters.and(
assignableToSkirmish(assignedBySide, ignoreExistingAssignments, allowAllyToSkirmish), assignableToSkirmish(assignedBySide, ignoreExistingAssignments, ignoreDefender, allowAllyToSkirmish),
(Filter) (game, physicalCard) -> { (Filter) (game, physicalCard) -> {
for (PhysicalCard card : Filters.filterActive(game, againstFilter)) { for (PhysicalCard card : Filters.filterActive(game, againstFilter)) {
if (card.getBlueprint().getSide() != physicalCard.getBlueprint().getSide() if (card.getBlueprint().getSide() != physicalCard.getBlueprint().getSide()
&& Filters.assignableToSkirmish(assignedBySide, ignoreExistingAssignments, allowAllyToSkirmish).accepts(game, card)) { && Filters.assignableToSkirmish(assignedBySide, ignoreExistingAssignments, ignoreDefender, allowAllyToSkirmish).accepts(game, card)) {
Map<PhysicalCard, Set<PhysicalCard>> thisAssignment = new HashMap<>(); Map<PhysicalCard, Set<PhysicalCard>> thisAssignment = new HashMap<>();
if (card.getBlueprint().getSide() == Side.FREE_PEOPLE) { if (card.getBlueprint().getSide() == Side.FREE_PEOPLE) {
if (thisAssignment.containsKey(card)) if (thisAssignment.containsKey(card))
@@ -223,7 +225,8 @@ public class Filters {
}); });
} }
public static Filter assignableToSkirmish(final Side assignedBySide, final boolean ignoreExistingAssignments, final boolean allowAllyToSkirmish) { public static Filter assignableToSkirmish(final Side assignedBySide, final boolean ignoreExistingAssignments,
final boolean ignoreDefender, final boolean allowAllyToSkirmish) {
Filter assignableFilter = Filters.or( Filter assignableFilter = Filters.or(
Filters.and( Filters.and(
CardType.ALLY, CardType.ALLY,
@@ -256,9 +259,20 @@ public class Filters {
(Filter) (game, physicalCard) -> { (Filter) (game, physicalCard) -> {
if (!ignoreExistingAssignments) { if (!ignoreExistingAssignments) {
boolean assignedToSkirmish = Filters.assignedToSkirmish.accepts(game, physicalCard); boolean assignedToSkirmish = Filters.assignedToSkirmish.accepts(game, physicalCard);
int defender = game.getModifiersQuerying().getKeywordCount(game, physicalCard, Keyword.DEFENDER);
if (assignedToSkirmish && defender == 0) if (assignedToSkirmish) {
return false; if(!ignoreDefender) {
int defender = game.getModifiersQuerying().getKeywordCount(game, physicalCard, Keyword.DEFENDER);
var assignments = game.getGameState().getAssignments()
.stream().filter(x -> x.getFellowshipCharacter() == physicalCard || x.getShadowCharacters().contains(physicalCard)).collect(
Collectors.toSet());
if(1 + defender <= assignments.size())
return false;
}
else {
return false;
}
}
} }
return game.getModifiersQuerying().canBeAssignedToSkirmish(game, assignedBySide, physicalCard); return game.getModifiersQuerying().canBeAssignedToSkirmish(game, assignedBySide, physicalCard);
}); });

View File

@@ -14,24 +14,24 @@ import java.util.Collections;
public class AssignmentEffect extends AbstractEffect { public class AssignmentEffect extends AbstractEffect {
private final String _playerId; private final String _playerId;
private boolean _ignoreSingleMinionRestriction; private boolean _ignoreExistingAssignments;
private boolean _ignoreDefender;
private final boolean _skipAllyLocationCheck; private final boolean _skipAllyLocationCheck;
private final PhysicalCard _fpChar; private final PhysicalCard _fpChar;
private final PhysicalCard _minion; private final PhysicalCard _minion;
public AssignmentEffect(String playerId, PhysicalCard fpChar, PhysicalCard minion) { public AssignmentEffect(String playerId, PhysicalCard fpChar, PhysicalCard minion) {
this(playerId, fpChar, minion, false); this(playerId, fpChar, minion, false, false, false);
} }
public AssignmentEffect(String playerId, PhysicalCard fpChar, PhysicalCard minion, boolean skipAllyLocationCheck) { public AssignmentEffect(String playerId, PhysicalCard fpChar, PhysicalCard minion, boolean ignoreExistingAssignments,
boolean ignoreDefender, boolean skipAllyLocationCheck) {
_playerId = playerId; _playerId = playerId;
_fpChar = fpChar; _fpChar = fpChar;
_minion = minion; _minion = minion;
_skipAllyLocationCheck = skipAllyLocationCheck; _skipAllyLocationCheck = skipAllyLocationCheck;
} _ignoreExistingAssignments = ignoreExistingAssignments;
_ignoreDefender = ignoreDefender;
public void setIgnoreSingleMinionRestriction(boolean ignoreSingleMinionRestriction) {
_ignoreSingleMinionRestriction = ignoreSingleMinionRestriction;
} }
@Override @Override
@@ -47,7 +47,7 @@ public class AssignmentEffect extends AbstractEffect {
@Override @Override
public boolean isPlayableInFull(LotroGame game) { public boolean isPlayableInFull(LotroGame game) {
Side side = _playerId.equals(game.getGameState().getCurrentPlayerId()) ? Side.FREE_PEOPLE : Side.SHADOW; Side side = _playerId.equals(game.getGameState().getCurrentPlayerId()) ? Side.FREE_PEOPLE : Side.SHADOW;
return Filters.assignableToSkirmishAgainst(side, _fpChar, _ignoreSingleMinionRestriction, _skipAllyLocationCheck).accepts(game, _minion); return Filters.assignableToSkirmishAgainst(side, _fpChar, _ignoreExistingAssignments, _ignoreDefender, _skipAllyLocationCheck).accepts(game, _minion);
} }
@Override @Override

View File

@@ -45,14 +45,14 @@ public class FreePeoplePlayerAssignsMinionsGameProcess implements GameProcess {
protected void doPlayEffect(final LotroGame game) { protected void doPlayEffect(final LotroGame game) {
final GameState gameState = game.getGameState(); final GameState gameState = game.getGameState();
final Collection<PhysicalCard> minions = Filters.filterActive(game, CardType.MINION, Filters.assignableToSkirmish(Side.FREE_PEOPLE, false, false)); final Collection<PhysicalCard> minions = Filters.filterActive(game, CardType.MINION, Filters.assignableToSkirmish(Side.FREE_PEOPLE, false, false, false));
if (!minions.isEmpty()) { if (!minions.isEmpty()) {
final Collection<PhysicalCard> freePeopleTargets = final Collection<PhysicalCard> freePeopleTargets =
Filters.filterActive(game, Filters.filterActive(game,
Filters.and( Filters.and(
Filters.or( Filters.or(
CardType.COMPANION, CardType.ALLY), CardType.COMPANION, CardType.ALLY),
Filters.assignableToSkirmish(Side.FREE_PEOPLE, false, false))); Filters.assignableToSkirmish(Side.FREE_PEOPLE, false, false, false)));
game.getUserFeedback().sendAwaitingDecision(gameState.getCurrentPlayerId(), game.getUserFeedback().sendAwaitingDecision(gameState.getCurrentPlayerId(),

View File

@@ -36,14 +36,14 @@ public class ShadowPlayerAssignsHisMinionsGameProcess implements GameProcess {
GameState gameState = game.getGameState(); GameState gameState = game.getGameState();
Filter minionFilter = Filters.and(CardType.MINION, Filters.owner(_playerId), Filters.in(_leftoverMinions)); Filter minionFilter = Filters.and(CardType.MINION, Filters.owner(_playerId), Filters.in(_leftoverMinions));
final Collection<PhysicalCard> minions = Filters.filterActive(game, minionFilter, Filters.assignableToSkirmish(Side.SHADOW, false, false)); final Collection<PhysicalCard> minions = Filters.filterActive(game, minionFilter, Filters.assignableToSkirmish(Side.SHADOW, false, false, false));
if (!minions.isEmpty()) { if (!minions.isEmpty()) {
final Collection<PhysicalCard> freePeopleTargets = final Collection<PhysicalCard> freePeopleTargets =
Filters.filterActive(game, Filters.filterActive(game,
Filters.and( Filters.and(
Filters.or( Filters.or(
CardType.COMPANION, CardType.ALLY), CardType.COMPANION, CardType.ALLY),
Filters.assignableToSkirmish(Side.SHADOW, true, false))); Filters.assignableToSkirmish(Side.SHADOW, true, true, false)));
game.getUserFeedback().sendAwaitingDecision(_playerId, game.getUserFeedback().sendAwaitingDecision(_playerId,
new PlayerAssignMinionsDecision(1, "Assign minions to companions or allies at home", freePeopleTargets, minions) { new PlayerAssignMinionsDecision(1, "Assign minions to companions or allies at home", freePeopleTargets, minions) {

View File

@@ -373,9 +373,9 @@ public class ModifiersAtTest extends AbstractAtTest {
DefaultActionContext actionContext = new DefaultActionContext(P1, _game, null, null, null); DefaultActionContext actionContext = new DefaultActionContext(P1, _game, null, null, null);
passUntil(Phase.FELLOWSHIP); passUntil(Phase.FELLOWSHIP);
assertFalse(Filters.assignableToSkirmish(Side.FREE_PEOPLE, false, false).accepts(_game, birchseed)); assertFalse(Filters.assignableToSkirmish(Side.FREE_PEOPLE, false, false, false).accepts(_game, birchseed));
addModifier(modifierSource.getModifier(actionContext)); addModifier(modifierSource.getModifier(actionContext));
assertTrue(Filters.assignableToSkirmish(Side.FREE_PEOPLE, false, false).accepts(_game, birchseed)); assertTrue(Filters.assignableToSkirmish(Side.FREE_PEOPLE, false, false, false).accepts(_game, birchseed));
} }
@Test @Test

View File

@@ -4,6 +4,7 @@ import com.gempukku.lotro.at.AbstractAtTest;
import com.gempukku.lotro.cards.build.*; import com.gempukku.lotro.cards.build.*;
import com.gempukku.lotro.cards.build.field.effect.filter.FilterFactory; import com.gempukku.lotro.cards.build.field.effect.filter.FilterFactory;
import com.gempukku.lotro.common.*; import com.gempukku.lotro.common.*;
import com.gempukku.lotro.filters.Filters;
import com.gempukku.lotro.game.*; import com.gempukku.lotro.game.*;
import com.gempukku.lotro.game.state.Assignment; import com.gempukku.lotro.game.state.Assignment;
import com.gempukku.lotro.game.state.LotroGame; import com.gempukku.lotro.game.state.LotroGame;
@@ -1029,14 +1030,29 @@ public class GenericCardTestHelper extends AbstractAtTest {
return _game.getModifiersQuerying().isRace(_game, card, race); return _game.getModifiersQuerying().isRace(_game, card, race);
} }
public Boolean CanBeAssigned(PhysicalCardImpl card) public Boolean CanBeAssignedViaAction(PhysicalCardImpl card)
{ {
return CanBeAssigned(card, Side.SHADOW) || CanBeAssigned(card, Side.FREE_PEOPLE); return CanBeAssignedViaAction(card, Side.SHADOW) || CanBeAssignedViaAction(card, Side.FREE_PEOPLE);
} }
public Boolean CanBeAssigned(PhysicalCardImpl card, Side side) public Boolean FreepsCanAssign(PhysicalCardImpl card)
{ {
return _game.getModifiersQuerying().canBeAssignedToSkirmish(_game, side, card); return CanBeAssignedNormally(card, Side.FREE_PEOPLE);
}
public Boolean ShadowCanAssign(PhysicalCardImpl card)
{
return CanBeAssignedViaAction(card, Side.FREE_PEOPLE);
}
public Boolean CanBeAssignedViaAction(PhysicalCardImpl card, Side side)
{
return Filters.assignableToSkirmish(side, false, true, false).accepts(_game, card);
}
public Boolean CanBeAssignedNormally(PhysicalCardImpl card, Side side)
{
return Filters.assignableToSkirmish(side, side == Side.SHADOW, side == Side.SHADOW, false).accepts(_game, card);
} }

View File

@@ -85,12 +85,16 @@ public class Card_01_262_Tests
scn.ShadowUseCardAction(assassin); scn.ShadowUseCardAction(assassin);
assertEquals(2, scn.GetFreepsCardChoiceCount()); assertEquals(2, scn.GetFreepsCardChoiceCount());
assertTrue(scn.CanBeAssigned(sam)); assertTrue(scn.CanBeAssignedViaAction(sam));
scn.FreepsChooseCard(sam); scn.FreepsChooseCard(sam);
assertTrue(scn.IsCharAssigned(sam)); assertTrue(scn.IsCharAssigned(sam));
assertTrue(scn.IsCharAssigned(assassin)); assertTrue(scn.IsCharAssigned(assassin));
scn.PassCurrentPhaseActions(); scn.PassCurrentPhaseActions();
assertFalse(scn.FreepsCanAssign(sam));
assertFalse(scn.FreepsCanAssign(assassin));
assertTrue(scn.FreepsCanAssign(runner));
assertTrue(scn.FreepsCanAssign(frodo));
scn.FreepsAssignToMinions(frodo, runner); scn.FreepsAssignToMinions(frodo, runner);
// If beginning skirmishes now fails, then there is some dangling minion that Gemp thinks // If beginning skirmishes now fails, then there is some dangling minion that Gemp thinks
// is unassigned, which isn't right. // is unassigned, which isn't right.
@@ -122,7 +126,7 @@ public class Card_01_262_Tests
scn.ShadowUseCardAction(assassin); scn.ShadowUseCardAction(assassin);
assertEquals(2, scn.GetFreepsCardChoiceCount()); assertEquals(2, scn.GetFreepsCardChoiceCount());
assertTrue(scn.CanBeAssigned(sam)); assertTrue(scn.CanBeAssignedViaAction(sam));
scn.FreepsChooseCard(sam); scn.FreepsChooseCard(sam);
assertTrue(scn.IsCharAssigned(sam)); assertTrue(scn.IsCharAssigned(sam));
assertTrue(scn.IsCharAssigned(assassin)); assertTrue(scn.IsCharAssigned(assassin));
@@ -131,7 +135,7 @@ public class Card_01_262_Tests
assertTrue(scn.hasKeyword(sam, Keyword.DEFENDER)); assertTrue(scn.hasKeyword(sam, Keyword.DEFENDER));
assertEquals(1, scn.GetKeywordCount(sam, Keyword.DEFENDER)); assertEquals(1, scn.GetKeywordCount(sam, Keyword.DEFENDER));
scn.CanBeAssigned(sam); assertTrue(scn.FreepsCanAssign(sam));
scn.FreepsAssignToMinions(sam, runner); scn.FreepsAssignToMinions(sam, runner);
assertTrue(scn.IsCharAssigned(sam)); assertTrue(scn.IsCharAssigned(sam));
assertTrue(scn.IsCharAssigned(assassin)); assertTrue(scn.IsCharAssigned(assassin));

View File

@@ -19,6 +19,7 @@ public class Card_03_069_Tests
{{ {{
put("saruman", "3_69"); put("saruman", "3_69");
put("savage", "1_151"); put("savage", "1_151");
put("shaman", "1_152");
put("sam", "2_114"); put("sam", "2_114");
@@ -82,12 +83,61 @@ public class Card_03_069_Tests
scn.FreepsPassCurrentPhaseAction(); scn.FreepsPassCurrentPhaseAction();
assertTrue(scn.ShadowActionAvailable(saruman)); assertTrue(scn.ShadowActionAvailable(saruman));
assertTrue(scn.CanBeAssigned(sam)); assertTrue(scn.CanBeAssignedViaAction(sam));
assertTrue(scn.CanBeAssigned(savage)); assertTrue(scn.CanBeAssignedViaAction(savage));
scn.ShadowUseCardAction(saruman); scn.ShadowUseCardAction(saruman);
scn.FreepsChooseNo(); scn.FreepsChooseNo();
scn.PassCurrentPhaseActions(); scn.PassCurrentPhaseActions();
assertTrue(scn.IsCharAssigned(sam));
assertTrue(scn.IsCharAssigned(savage));
scn.FreepsResolveSkirmish(sam);
}
@Test
public void SarumanCannotAssignMultipleMinionsToSameCompanionEvenWithDefender() throws DecisionResultInvalidException, CardNotFoundException {
//Pre-game setup
var scn = GetScenario();
var saruman = scn.GetShadowCard("saruman");
var savage = scn.GetShadowCard("savage");
var shaman = scn.GetShadowCard("shaman");
scn.ShadowMoveCharToTable(saruman, savage, shaman);
var frodo = scn.GetRingBearer();
var sam = scn.GetFreepsCard("sam");
scn.FreepsMoveCharToTable(sam);
scn.StartGame();
scn.SkipToPhase(Phase.MANEUVER);
scn.FreepsUseCardAction(sam);
scn.ShadowPassCurrentPhaseAction();
scn.FreepsPassCurrentPhaseAction();
scn.SkipToPhase(Phase.ASSIGNMENT);
scn.FreepsPassCurrentPhaseAction();
assertTrue(scn.ShadowActionAvailable(saruman));
assertTrue(scn.CanBeAssignedViaAction(sam));
assertTrue(scn.CanBeAssignedViaAction(savage));
assertTrue(scn.CanBeAssignedViaAction(shaman));
scn.ShadowUseCardAction(saruman);
scn.ShadowChooseCard(savage);
scn.FreepsChooseNo();
scn.FreepsPassCurrentPhaseAction();
assertTrue(scn.IsCharAssigned(sam));
assertTrue(scn.IsCharAssigned(savage));
assertFalse(scn.IsCharAssigned(shaman));
assertFalse(scn.CanBeAssignedViaAction(sam));
assertFalse(scn.CanBeAssignedViaAction(savage));
assertTrue(scn.CanBeAssignedViaAction(shaman));
scn.ShadowUseCardAction(saruman);
scn.PassCurrentPhaseActions();
scn.FreepsAssignToMinions(frodo, shaman);
scn.FreepsResolveSkirmish(sam); scn.FreepsResolveSkirmish(sam);
} }

View File

@@ -88,13 +88,13 @@ public class Card_V1_018_Tests
scn.StartGame(); scn.StartGame();
assertFalse(scn.CanBeAssigned(saruman)); assertFalse(scn.CanBeAssignedViaAction(saruman));
scn.FreepsPlayCard(elrond); scn.FreepsPlayCard(elrond);
assertFalse(scn.CanBeAssigned(saruman)); assertFalse(scn.CanBeAssignedViaAction(saruman));
scn.FreepsPlayCard(galadriel); scn.FreepsPlayCard(galadriel);
assertFalse(scn.CanBeAssigned(saruman)); assertFalse(scn.CanBeAssignedViaAction(saruman));
scn.FreepsPlayCard(gandalf); scn.FreepsPlayCard(gandalf);
assertTrue(scn.CanBeAssigned(saruman)); assertTrue(scn.CanBeAssignedViaAction(saruman));
scn.SkipToPhase(Phase.ASSIGNMENT); scn.SkipToPhase(Phase.ASSIGNMENT);
scn.PassCurrentPhaseActions(); scn.PassCurrentPhaseActions();