From 8276a5e718172c6f322fdbd8b02db319ade1c7b4 Mon Sep 17 00:00:00 2001 From: "marcins78@gmail.com" Date: Tue, 27 Dec 2011 12:14:53 +0000 Subject: [PATCH] - "Orc Assassin" and other similar cards should be working correctly now, allowing to assign allies only when allies are "on the site" (at home or allowed to participate otherwise). --- ...hooseAndAssignCharacterToMinionEffect.java | 8 +- .../lotro/cards/set4/dunland/Card4_015.java | 4 +- .../lotro/cards/set4/dunland/Card4_018.java | 4 +- .../com/gempukku/lotro/filters/Filters.java | 20 +++-- .../lotro/logic/timing/RuleUtils.java | 79 +++++++++++++++++++ ...PeoplePlayerAssignsMinionsGameProcess.java | 39 +-------- .../lotro/at/IndividualCardAtTest.java | 44 ++++++++++- .../src/main/webapp/includes/changeLog.html | 2 + 8 files changed, 149 insertions(+), 51 deletions(-) diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/effects/choose/ChooseAndAssignCharacterToMinionEffect.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/effects/choose/ChooseAndAssignCharacterToMinionEffect.java index 9a0ab88d0..700542b9d 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/effects/choose/ChooseAndAssignCharacterToMinionEffect.java +++ b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/effects/choose/ChooseAndAssignCharacterToMinionEffect.java @@ -16,18 +16,24 @@ public class ChooseAndAssignCharacterToMinionEffect extends ChooseActiveCardEffe private Action _action; private String _playerId; private PhysicalCard _minion; + private boolean _skipAllyLocationCheck; public ChooseAndAssignCharacterToMinionEffect(Action action, String playerId, PhysicalCard minion, Filterable... filters) { + this(action, playerId, minion, false, filters); + } + + public ChooseAndAssignCharacterToMinionEffect(Action action, String playerId, PhysicalCard minion, boolean skipAllyLocationCheck, Filterable... filters) { super(action.getActionSource(), playerId, "Choose character to assign " + GameUtils.getCardLink(minion) + " to", filters); _action = action; _playerId = playerId; _minion = minion; + _skipAllyLocationCheck = skipAllyLocationCheck; } @Override protected Filter getExtraFilterForPlaying(final LotroGame game) { final Side side = game.getGameState().getCurrentPlayerId().equals(_playerId) ? Side.FREE_PEOPLE : Side.SHADOW; - return Filters.canBeAssignedToSkirmishByEffectAgainst(side, _minion); + return Filters.canBeAssignedToSkirmishByEffectAgainst(side, _minion, _skipAllyLocationCheck); } @Override diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set4/dunland/Card4_015.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set4/dunland/Card4_015.java index 00e5cd283..585380a22 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set4/dunland/Card4_015.java +++ b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set4/dunland/Card4_015.java @@ -47,10 +47,10 @@ public class Card4_015 extends AbstractMinion { @Override protected List getExtraPhaseActions(final String playerId, LotroGame game, final PhysicalCard self) { if (PlayConditions.canUseShadowCardDuringPhase(game, Phase.ASSIGNMENT, self, 0) - && Filters.canSpot(game.getGameState(), game.getModifiersQuerying(), CardType.ALLY, Filters.canBeAssignedToSkirmishByEffect(Side.SHADOW))) { + && Filters.canSpot(game.getGameState(), game.getModifiersQuerying(), CardType.ALLY, Filters.canBeAssignedToSkirmishByEffect(Side.SHADOW, true))) { final ActivateCardAction action = new ActivateCardAction(self); action.appendEffect( - new ChooseAndAssignCharacterToMinionEffect(action, playerId, self, CardType.ALLY)); + new ChooseAndAssignCharacterToMinionEffect(action, playerId, self, true, CardType.ALLY)); return Collections.singletonList(action); } return null; diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set4/dunland/Card4_018.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set4/dunland/Card4_018.java index 8fac4dd75..72607d941 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set4/dunland/Card4_018.java +++ b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/set4/dunland/Card4_018.java @@ -33,10 +33,10 @@ public class Card4_018 extends AbstractMinion { @Override protected List getExtraPhaseActions(final String playerId, LotroGame game, final PhysicalCard self) { if (PlayConditions.canUseShadowCardDuringPhase(game, Phase.ASSIGNMENT, self, 0) - && Filters.canSpot(game.getGameState(), game.getModifiersQuerying(), CardType.ALLY, Filters.canBeAssignedToSkirmishByEffect(Side.SHADOW))) { + && Filters.canSpot(game.getGameState(), game.getModifiersQuerying(), CardType.ALLY, Filters.canBeAssignedToSkirmishByEffect(Side.SHADOW, true))) { final ActivateCardAction action = new ActivateCardAction(self); action.appendEffect( - new ChooseAndAssignCharacterToMinionEffect(action, playerId, self, CardType.ALLY)); + new ChooseAndAssignCharacterToMinionEffect(action, playerId, self, true, CardType.ALLY)); return Collections.singletonList(action); } return null; diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java index 89439162b..3948e4251 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java @@ -10,6 +10,7 @@ import com.gempukku.lotro.game.state.GameState; import com.gempukku.lotro.game.state.LotroGame; import com.gempukku.lotro.game.state.Skirmish; import com.gempukku.lotro.logic.modifiers.ModifiersQuerying; +import com.gempukku.lotro.logic.timing.RuleUtils; import java.util.*; @@ -208,6 +209,10 @@ public class Filters { } public static Filter canBeAssignedToSkirmishByEffect(final Side sidePlayer) { + return canBeAssignedToSkirmishByEffect(sidePlayer, false); + } + + public static Filter canBeAssignedToSkirmishByEffect(final Side sidePlayer, boolean skipAllyLocationCheck) { return Filters.and( notAssignedToSkirmish, Filters.or( @@ -219,12 +224,9 @@ public class Filters { return !gameState.isFierceSkirmishes(); } }, Keyword.FIERCE)), - new Filter() { - @Override - public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { - return modifiersQuerying.canBeAssignedToSkirmish(gameState, sidePlayer, physicalCard); - } - }); + Filters.or( + CardType.MINION, + RuleUtils.getSkirmishAssignableFPCharacterFilter(sidePlayer, skipAllyLocationCheck))); } public static Filter canBeAssignedToSkirmishByEffectIgnoreNotAssigned(final Side sidePlayer) { @@ -263,8 +265,12 @@ public class Filters { } public static Filter canBeAssignedToSkirmishByEffectAgainst(final Side sidePlayer, final PhysicalCard against) { + return canBeAssignedToSkirmishByEffectAgainst(sidePlayer, against, false); + } + + public static Filter canBeAssignedToSkirmishByEffectAgainst(final Side sidePlayer, final PhysicalCard against, boolean skipAllyLocationCheck) { return Filters.and( - canBeAssignedToSkirmishByEffect(sidePlayer), + canBeAssignedToSkirmishByEffect(sidePlayer, skipAllyLocationCheck), new Filter() { @Override public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleUtils.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleUtils.java index fcab553b1..b42eb6665 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleUtils.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleUtils.java @@ -59,6 +59,85 @@ public class RuleUtils { return game.getModifiersQuerying().getArcheryTotal(game.getGameState(), Side.SHADOW, normalArcheryTotal); } + public static Filter getSkirmishAssignableFPCharacterFilter(final Side side, final boolean skipAllyLocationCheck) { + if (side == Side.FREE_PEOPLE) { + return Filters.and( + Filters.or( + Filters.and( + CardType.COMPANION, + Filters.or( + Filters.not(Keyword.UNHASTY), + new Filter() { + @Override + public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { + return modifiersQuerying.isAllowedToParticipateInSkirmishes(gameState, Side.FREE_PEOPLE, physicalCard); + } + } + ) + ), + Filters.and( + CardType.ALLY, + Filters.or( + new Filter() { + @Override + public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { + return skipAllyLocationCheck; + } + }, + Filters.and( + Filters.allyAtHome, + new Filter() { + @Override + public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { + return !modifiersQuerying.isAllyPreventedFromParticipatingInSkirmishes(gameState, Side.FREE_PEOPLE, physicalCard); + } + }), + new Filter() { + @Override + public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { + return modifiersQuerying.isAllowedToParticipateInSkirmishes(gameState, Side.FREE_PEOPLE, physicalCard); + } + } + ) + ) + ), + Filters.canBeAssignedToSkirmish(Side.FREE_PEOPLE)); + } else { + return Filters.and( + Filters.or( + Filters.and( + CardType.COMPANION, + new Filter() { + @Override + public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { + return modifiersQuerying.isAllowedToParticipateInSkirmishes(gameState, Side.SHADOW, physicalCard); + } + } + ), + Filters.and( + CardType.ALLY, + Filters.or( + Filters.and( + Filters.allyAtHome, + new Filter() { + @Override + public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { + return !modifiersQuerying.isAllyPreventedFromParticipatingInSkirmishes(gameState, Side.SHADOW, physicalCard); + } + }), + new Filter() { + @Override + public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { + return modifiersQuerying.isAllowedToParticipateInSkirmishes(gameState, Side.SHADOW, physicalCard); + } + } + ) + ) + ), + Filters.canBeAssignedToSkirmish(Side.SHADOW)); + } + } + public static int calculateMoveLimit(LotroGame game) { return game.getModifiersQuerying().getMoveLimit(game.getGameState(), 2); } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/assign/FreePeoplePlayerAssignsMinionsGameProcess.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/assign/FreePeoplePlayerAssignsMinionsGameProcess.java index 6a8ac26bd..081937316 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/assign/FreePeoplePlayerAssignsMinionsGameProcess.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/assign/FreePeoplePlayerAssignsMinionsGameProcess.java @@ -4,7 +4,6 @@ import com.gempukku.lotro.common.CardType; import com.gempukku.lotro.common.Filterable; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Side; -import com.gempukku.lotro.filters.Filter; import com.gempukku.lotro.filters.Filters; import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.state.Assignment; @@ -15,7 +14,7 @@ import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; import com.gempukku.lotro.logic.decisions.PlayerAssignMinionsDecision; import com.gempukku.lotro.logic.effects.AssignmentPhaseEffect; import com.gempukku.lotro.logic.effects.TriggeringResultEffect; -import com.gempukku.lotro.logic.modifiers.ModifiersQuerying; +import com.gempukku.lotro.logic.timing.RuleUtils; import com.gempukku.lotro.logic.timing.UnrespondableEffect; import com.gempukku.lotro.logic.timing.processes.GameProcess; import com.gempukku.lotro.logic.timing.results.FreePlayerStartsAssigningResult; @@ -48,41 +47,7 @@ public class FreePeoplePlayerAssignsMinionsGameProcess implements GameProcess { final Collection minions = Filters.filterActive(gameState, game.getModifiersQuerying(), minionFilter, Filters.canBeAssignedToSkirmish(Side.FREE_PEOPLE)); if (minions.size() > 0) { - final Collection freePeopleTargets = Filters.filterActive(gameState, game.getModifiersQuerying(), - Filters.or( - Filters.and( - CardType.COMPANION, - Filters.or( - Filters.not(Keyword.UNHASTY), - new Filter() { - @Override - public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { - return modifiersQuerying.isAllowedToParticipateInSkirmishes(gameState, Side.FREE_PEOPLE, physicalCard); - } - } - ) - ), - Filters.and( - CardType.ALLY, - Filters.or( - Filters.and( - Filters.allyAtHome, - new Filter() { - @Override - public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { - return !modifiersQuerying.isAllyPreventedFromParticipatingInSkirmishes(gameState, Side.FREE_PEOPLE, physicalCard); - } - }), - new Filter() { - @Override - public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { - return modifiersQuerying.isAllowedToParticipateInSkirmishes(gameState, Side.FREE_PEOPLE, physicalCard); - } - } - ) - ) - ), - Filters.canBeAssignedToSkirmish(Side.FREE_PEOPLE)); + final Collection freePeopleTargets = Filters.filterActive(gameState, game.getModifiersQuerying(), RuleUtils.getSkirmishAssignableFPCharacterFilter(Side.FREE_PEOPLE, false)); game.getUserFeedback().sendAwaitingDecision(gameState.getCurrentPlayerId(), new PlayerAssignMinionsDecision(1, "Assign minions to companions or allies at home", freePeopleTargets, minions) { diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/IndividualCardAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/IndividualCardAtTest.java index d2a0c9b3a..7e8d9ced5 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/IndividualCardAtTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/IndividualCardAtTest.java @@ -8,6 +8,7 @@ import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.decisions.AwaitingDecisionType; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; import com.gempukku.lotro.logic.vo.LotroDeck; +import static junit.framework.Assert.assertEquals; import org.junit.Test; import java.util.Arrays; @@ -15,8 +16,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; -import static junit.framework.Assert.assertEquals; - public class IndividualCardAtTest extends AbstractAtTest { @Test public void dwarvenAxeDoesNotFreeze() throws DecisionResultInvalidException { @@ -351,4 +350,45 @@ public class IndividualCardAtTest extends AbstractAtTest { assertEquals(2, _game.getGameState().getWounds(urukHaiRaidingParty)); } + + @Test + public void orcAssassinAssignNotToAlly() throws DecisionResultInvalidException { + initializeSimplestGame(); + + skipMulligans(); + + PhysicalCardImpl merry = new PhysicalCardImpl(100, "1_303", P1, _library.getLotroCardBlueprint("1_303")); + PhysicalCardImpl hobbitPartyGuest = new PhysicalCardImpl(101, "1_297", P1, _library.getLotroCardBlueprint("1_297")); + PhysicalCardImpl orcAssassin = new PhysicalCardImpl(102, "1_262", P2, _library.getLotroCardBlueprint("1_262")); + + _game.getGameState().addCardToZone(_game, merry, Zone.FREE_CHARACTERS); + _game.getGameState().addCardToZone(_game, hobbitPartyGuest, Zone.SUPPORT); + + // End fellowship phase + playerDecided(P1, ""); + + _game.getGameState().addCardToZone(_game, orcAssassin, Zone.SHADOW_CHARACTERS); + + // End shadow phase + playerDecided(P2, ""); + + // End maneuvers phase + playerDecided(P1, ""); + playerDecided(P2, ""); + + // End arhcery phase + playerDecided(P1, ""); + playerDecided(P2, ""); + + // Assignment phase + playerDecided(P1, ""); + + AwaitingDecision assignmentActions = _userFeedback.getAwaitingDecision(P2); + assertEquals(AwaitingDecisionType.CARD_ACTION_CHOICE, assignmentActions.getDecisionType()); + playerDecided(P2, "0"); + + AwaitingDecision assignCharacter = _userFeedback.getAwaitingDecision(P1); + assertEquals(AwaitingDecisionType.CARD_SELECTION, assignCharacter.getDecisionType()); + validateContents(new String[]{String.valueOf(merry.getCardId()), String.valueOf(_game.getGameState().getRingBearer(P1).getCardId())}, (String[]) assignCharacter.getDecisionParameters().get("cardId")); + } } diff --git a/gemp-lotr/gemp-lotr-web/src/main/webapp/includes/changeLog.html b/gemp-lotr/gemp-lotr-web/src/main/webapp/includes/changeLog.html index 4ea9b9904..a4604dd10 100644 --- a/gemp-lotr/gemp-lotr-web/src/main/webapp/includes/changeLog.html +++ b/gemp-lotr/gemp-lotr-web/src/main/webapp/includes/changeLog.html @@ -1,6 +1,8 @@
 27 Dec. 2011
 - "Isengard Scout Troop" now exerts itself to take control of a site.
+- "Orc Assassin" and other similar cards should be working correctly now, allowing to assign allies only when allies
+are "on the site" (at home or allowed to participate otherwise).
 
 26 Dec. 2011
 - "Wizard Storm" should now work when fellowship moves from the site it's attached to.