diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set03/set3-isengard.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set03/set3-isengard.hjson index a731f9535..190c2a249 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set03/set3-isengard.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set03/set3-isengard.hjson @@ -645,47 +645,18 @@ type: exert select: self } - effect: [ - { - type: chooseActiveCards - select: choose(culture(isengard),minion,assignableToSkirmishAgainst(companion,not(ringBearer))) - text: Choose ISENGARD minion to assign - memorize: assignedMinion + effect: { + type: assignFpCharacterToSkirmish + fpCharacter: choose(companion,not(ringBearer)) + minion: choose(culture(isengard),minion) + memorizeFPCharacter: assignedCompanion + memorizeMinion: assignedMinion + preventText: Would you like to exert {assignedCompanion} to prevent it being assigned to {assignedMinion} + preventCost: { + type: exert + select: memory(assignedCompanion) } - { - type: chooseActiveCards - select: choose(companion,not(ringBearer),assignableToSkirmishAgainst(memory(assignedMinion))) - text: Choose companion (except Ring-Bearer) to assign - memorize: assignedCompanion - } - { - type: If - check: [ - { - type: hasInMemory - memory: assignedMinion - } - { - type: hasInMemory - memory: assignedCompanion - } - ] - true: { - type: preventable - player: fp - text: Would you like to exert {assignedCompanion} to prevent it being assigned to {assignedMinion} - cost: { - type: exert - select: memory(assignedCompanion) - } - effect: { - type: assignFpCharacterToSkirmish - fpCharacter: memory(assignedCompanion) - minion: memory(assignedMinion) - } - } - } - ] + } } ] } diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Isengard.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Isengard.hjson index 443e82393..30fb53b2d 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Isengard.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Isengard.hjson @@ -427,42 +427,17 @@ select: choose(culture(isengard),tracker) memorize: exertedTracker }, - effect: [ - { - type: chooseActiveCards - select: choose(unbound,companion,assignableToSkirmishAgainst(memory(exertedTracker))) - text: Choose companion to assign {exertedTracker} to - memorize: chosenCompanion - } - { - type: if - check: { - type: memoryMatches - memory: chosenCompanion - filter: hobbit - } - true: { - type: assignFPCharacterToSkirmish - fpCharacter: memory(chosenCompanion) - minion: memory(exertedTracker) - } - false: { - type: preventable - text: Would you like to exert {chosenCompanion} to prevent {exertedTracker} to be assigned to it? - player: fp - cost: { - type: exert - player: fp - select: memory(chosenCompanion) - } - effect: { - type: assignFPCharacterToSkirmish - fpCharacter: memory(chosenCompanion) - minion: memory(exertedTracker) - } - } - } - ] + effect: { + type: assignFPCharacterToSkirmish + fpCharacter: choose(unbound,companion) + minion: memory(exertedTracker) + memorizeFPCharacter: chosenCompanion + preventText: Would you like to exert {chosenCompanion} to prevent {exertedTracker} to be assigned to it? + preventCost: { + type: exert + select: choose(memory(chosenCompanion),not(hobbit)) + } + } } gametext: Search.
Assignment: Exert an [isengard] tracker to assign it to an unbound companion. That companion may exert to prevent this (unless that companion is a Hobbit). lore: What are they wanted for?... Why alive? Do they give good sport?' @@ -1319,18 +1294,14 @@ } ] effect: { - type: preventable - text: Would you like to exert bearer of Many Riddles to prevent {chosenTracker} being assigned to it? - player: fp - cost: { + type: assignFPCharacterToSkirmish + fpCharacter: bearer + minion: memory(chosenTracker) + preventText: Would you like to exert bearer of Many Riddles to prevent {chosenTracker} being assigned to it? + preventCost: { type: exert select: bearer } - effect: { - type: assignFPCharacterToSkirmish - fpCharacter: bearer - minion: memory(chosenTracker) - } } } ] @@ -1591,28 +1562,17 @@ select: self } ] - effect: [ - { - type: chooseActiveCards - select: choose(unbound,companion,assignableToSkirmishAgainst(self)) - text: Choose companion to assign it to - memorize: chosenCompanion + effect: { + type: assignFPCharacterToSkirmish + fpCharacter: choose(unbound,companion,assignableToSkirmishAgainst(self)) + minion: self + memorizeFPCharacter: chosenCompanion + preventText: Would you like to exert {chosenCompanion} to prevent {self} being assigned to it? + preventCost: { + type: exert + select: memory(chosenCompanion) } - { - type: preventable - text: Would you like to exert {chosenCompanion} to prevent Orthanc Champion being assigned to it? - player: fp - cost: { - type: exert - select: memory(chosenCompanion) - } - effect: { - type: assignFPCharacterToSkirmish - fpCharacter: memory(chosenCompanion) - minion: self - } - } - ] + } } ] gametext: Damage +1.
Assignment: Exert Orthanc Champion to assign it to an unbound companion. That companion may exert to prevent this. diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Raider.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Raider.hjson index 84d98396e..e25b9b315 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Raider.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Raider.hjson @@ -2052,21 +2052,16 @@ } ] effect: { - type: preventable - player: fp - text: Would you like to discard an unbound companion to prevent Southron Commander from being assigned to the Ring-bearer? - cost: { + type: assignFpCharacterToSkirmish + fpCharacter: choose(ringBearer) + minion: self + memorizeFPCharacter: ringBearer + preventText: Would you like to discard an unbound companion to prevent {self} from being assigned to {ringBearer}? + preventCost: { type: discard - player: fp select: choose(unbound,companion) } - effect: { - type: assignFpCharacterToSkirmish - fpCharacter: choose(ringBearer) - minion: self - } } - } ] gametext: Southron. Ambush (1).
Assignment: Spot 6 companions to assign this minion to the Ring-bearer. The Free Peoples player may discard an unbound companion to prevent this. @@ -2439,19 +2434,16 @@ } ] effect: { - type: preventable - player: fp - text: Would you like to make opponent discard a companion to prevent assigning Southron Troop to the Ring-bearer? - cost: { + type: assignFPCharacterToSkirmish + fpCharacter: choose(ringBearer) + minion: self + memorizeFPCharacter: ringBearer + preventText: Would you like to make opponent discard a companion to prevent assigning {self} to {ringBearer}? + preventCost: { type: discard player: shadow select: choose(companion,not(ringBearer)) } - effect: { - type: assignFpCharacterToSkirmish - fpCharacter: choose(ringBearer) - minion: self - } } } ] @@ -2576,18 +2568,15 @@ } ] effect: { - type: preventable - player: fp - text: Would you like to add 4 twilight to prevent Southron Wanderer getting assigned to skirmish against the Ring-bearer - cost: { + type: assignFpCharacterToSkirmish + fpCharacter: choose(ringBearer) + minion: self + memorizeFPCharacter: ringBearer + preventText: Would you like to add 4 twilight to prevent {self} getting assigned to skirmish against {ringBearer}? + preventCost: { type: addTwilight amount: 4 } - effect: { - type: assignFpCharacterToSkirmish - fpCharacter: choose(ringBearer) - minion: self - } } } @@ -2629,24 +2618,16 @@ type: event effect: [ { - type: chooseActiveCards - text: Choose an Easterling to assign to Ring-bearer - select: choose(easterling,assignableToSkirmishAgainst(ringBearer)) - memorize: chosenEasterling - } - { - type: preventable - player: fp - text: Would you like to add burden to prevent assigning {chosenEasterling} to the Ring-bearer? - cost: { + type: assignFpCharacterToSkirmish + fpCharacter: choose(ringBearer) + minion: choose(easterling) + memorizeFPCharacter: ringBearer + memorizeMinion: chosenEasterling + preventText: Would you like to add burden to prevent assigning {chosenEasterling} to {ringBearer}? + preventCost: { type: addBurdens amount: 1 } - effect: { - type: assignFpCharacterToSkirmish - fpCharacter: choose(ringBearer) - minion: memory(chosenEasterling) - } } ] } diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set10/set10-Gollum.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set10/set10-Gollum.hjson index da3c2ad01..f94f63526 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set10/set10-Gollum.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set10/set10-Gollum.hjson @@ -240,24 +240,21 @@ type: activated phase: assignment effect: { - type: preventable - player: free people - text: Would you like to add a burden and assign Gollum? - cost: [ - { - type: addBurdens - } - { - type: assignFpCharacterToSkirmish - fpCharacter: choose(any) - minion: choose(name(Gollum)) - } - ] - effect: { - type: assignFpCharacterToSkirmish - fpCharacter: choose(companion,hasAttached(artifact)) - minion: choose(name(Gollum)) + type: assignFpCharacterToSkirmish + fpCharacter: choose(companion,hasAttached(artifact)) + minion: choose(name(Gollum)) + memorizeFPCharacter: chosenCompanion + memorizeMinion: gollum + preventText: Would you like to add a burden and assign Gollum to prevent assigning {chosenCompanion} to {gollum}? + preventCost: { + type: addBurdens } + insteadEffect: { + type: assignFpCharacterToSkirmish + player: free people + fpCharacter: choose(any) + minion: choose(name(Gollum)) + } } } { diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set11/set11-Orc.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set11/set11-Orc.hjson index 216adde9f..5c4a0ad31 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set11/set11-Orc.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set11/set11-Orc.hjson @@ -178,19 +178,15 @@ select: self } effect: { - type: preventable - player: free people - text: Would you like to discard an artifact to prevent the assignment? - cost: { + type: assignFpCharacterToSkirmish + fpCharacter: choose(companion,hasAttached(artifact)) + minion: self + memorizeFPCharacter: chosenCompanion + preventText: Would you like to discard an artifact to prevent the assignment of {chosenCompanion} to {self}? + preventCost: { type: discard - player: free people select: choose(artifact) } - effect: { - type: assignFpCharacterToSkirmish - fpCharacter: choose(companion,hasAttached(artifact)) - minion: self - } } } ] diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set15/set15-Orc.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set15/set15-Orc.hjson index a1121017f..1d425bd8b 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set15/set15-Orc.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set15/set15-Orc.hjson @@ -1384,18 +1384,15 @@ count: 6 } true: { - type: preventable - player: free people - text: Would you like to exert a companion to prevent assigning Tower Troll to skirmish? - cost: { + type: assignFPCharacterToSkirmish + fpCharacter: choose(companion,not(ringBearer)) + minion: self + memorizeFPCharacter: chosenCompanion + preventText: Would you like to exert a companion to prevent assigning {chosenCompanion} to skirmish {self}? + preventCost: { type: exert select: choose(companion) } - effect: { - type: assignFPCharacterToSkirmish - fpCharacter: choose(companion,not(ringBearer)) - minion: self - } } false: { type: assignFPCharacterToSkirmish diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set18/set18-Uruk-hai.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set18/set18-Uruk-hai.hjson index 9a0b3eb06..92100cc3d 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set18/set18-Uruk-hai.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set18/set18-Uruk-hai.hjson @@ -290,16 +290,12 @@ } effect: [ { - type: chooseActiveCards - text: Choose unbound companion to assign Lurtz to - select: choose(unbound,companion,assignableToSkirmishAgainst(self)) - memorize: chosenCompanion - } - { - type: preventable - player: free people - text: Would you like to exert {chosenCompanion} or add a burden to prevent assigning it to Lurtz? - cost: { + type: assignFPCharacterToSkirmish + fpCharacter: choose(unbound,companion) + minion: self + memorizeFPCharacter: chosenCompanion + preventText: Would you like to exert {chosenCompanion} or add a burden to prevent assigning it to {self}? + preventCost: { type: choice texts: [ Exert - {chosenCompanion} @@ -315,11 +311,6 @@ } ] } - effect: { - type: assignFPCharacterToSkirmish - fpCharacter: memory(chosenCompanion) - minion: self - } } ] } diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set19/set19.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set19/set19.hjson index f7048615a..dda3f504b 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set19/set19.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set19/set19.hjson @@ -624,28 +624,17 @@ type: exert select: self } - effect: [ - { - type: chooseActiveCards - text: Choose unbound companion to assign Grima to - select: choose(unbound,companion,assignableToSkirmishAgainst(name(Grima))) - memorize: chosenCompanion - } - { - type: preventable - player: fp - text: Would you like to exert {chosenCompanion} to prevent Grima assigning to it - cost: { - type: exert - select: memory(chosenCompanion) - } - effect: { - type: assignFpCharacterToSkirmish - fpCharacter: memory(chosenCompanion) - minion: choose(name(Grima)) - } - } - ] + effect: { + type: assignFPCharacterToSkirmish + fpCharacter: choose(unbound,companion) + minion: self + memorizeFPCharacter: chosenCompanion + preventText: Would you like to exert {chosenCompanion} to prevent {self} assigning to it? + preventCost: { + type: exert + select: memory(chosenCompanion) + } + } } ] } diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/hobbit/set32/set32-shadow.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/hobbit/set32/set32-shadow.hjson index a26776398..7bfac4de1 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/hobbit/set32/set32-shadow.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/hobbit/set32/set32-shadow.hjson @@ -878,45 +878,31 @@ select: self } effect: [ - { - type: chooseActiveCards - select: choose(minion,or(culture(gundabad),culture(wraith)),assignableToSkirmishAgainst(companion,not(name(Bilbo)))) - text: Choose minion to assign to a companion - memorize: chosenMinion - } - { - type: chooseActiveCards - select: choose(companion,not(name(Bilbo)),assignableToSkirmishAgainst(memory(chosenMinion))) - text: Choose companion - memorize: chosenCompanion - } - { - type: preventable - player: fp - text: Would you like to add 2 doubts or exert {chosenCompanion} to prevent it from being assigned to {chosenMinion}? - cost: { - type: choice - texts: [ - Add 2 doubts - Exert the companion - ] - effects: [ - { - type: addBurdens - amount: 2 + { + type: assignFPCharacterToSkirmish + fpCharacter: choose(companion,not(name(Bilbo))) + minion: choose(minion,or(culture(gundabad),culture(wraith))) + memorizeFPCharacter: chosenCompanion + memorizeMinion: chosenMinion + preventText: Would you like to add 2 doubts or exert {chosenCompanion} to prevent it from being assigned to {chosenMinion}? + preventCost: { + type: choice + texts: [ + Add 2 doubts + Exert the companion + ] + effects: [ + { + type: addBurdens + amount: 2 + } + { + type: exert + select: memory(chosenCompanion) + } + ] } - { - type: exert - select: choose(memory(chosenCompanion)) - } - ] } - effect: { - type: assignFpCharacterToSkirmish - fpCharacter: choose(memory(chosenCompanion)) - minion: choose(memory(chosenMinion)) - } - } ] } ] diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV01/V1_moria.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV01/V1_moria.hjson index ea5e4b079..38ad5d0c1 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV01/V1_moria.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV01/V1_moria.hjson @@ -31,27 +31,19 @@ select: self } effect: [ - { - type: ChooseActiveCards - text: Choose a {moria} creature to assign to the Ring-bearer. - select: choose(culture(moria),creature) - memorize: chosenCreature - } - { - type: Preventable - player: freeps - text: Would you like to exert the Ring-bearer twice to prevent {chosenCreature} being assigned to them? - cost: { + { + type: assignFPCharacterToSkirmish + fpCharacter: choose(ringBearer) + minion: choose(culture(moria),creature) + memorizeFPCharacter: ringBearer + memorizeMinion: chosenCreature + preventText: Would you like to exert {ringBearer} twice to prevent {chosenCreature} being assigned to them? + preventCost: { type: Exert - select: choose(Ring-bearer) + select: memory(ringBearer) times: 2 - } - effect: { - type: assignFpCharacterToSkirmish - fpCharacter: choose(ringbearer) - minion: memory(chosenCreature) - } - } + } + } ] } ] diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/OpponentPlayerSource.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/OpponentPlayerSource.java new file mode 100644 index 000000000..5608f4ca4 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/OpponentPlayerSource.java @@ -0,0 +1,16 @@ +package com.gempukku.lotro.cards.build; + +import com.gempukku.lotro.logic.GameUtils; + +public class OpponentPlayerSource implements PlayerSource { + private PlayerSource playerSource; + + public OpponentPlayerSource(PlayerSource playerSource) { + this.playerSource = playerSource; + } + + @Override + public String getPlayer(ActionContext actionContext) { + return GameUtils.getFirstOpponent(actionContext.getGame(), playerSource.getPlayer(actionContext)); + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AssignFpCharacterToSkirmish.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AssignFpCharacterToSkirmish.java index ed82002a3..b05df803d 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AssignFpCharacterToSkirmish.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AssignFpCharacterToSkirmish.java @@ -17,18 +17,26 @@ import com.gempukku.lotro.logic.timing.Effect; import org.json.simple.JSONObject; import java.util.Collection; -import java.util.Collections; -import java.util.List; public class AssignFpCharacterToSkirmish implements EffectAppenderProducer { @Override public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(effectObject, "player", "fpCharacter", "minion", "memorizeMinion", "memorizeFPCharacter", "ignoreUnassigned"); + FieldUtils.validateAllowedFields(effectObject, "player", "fpCharacter", "minion", "memorizeMinion", "memorizeFPCharacter", "ignoreUnassigned", "preventCost", "preventText", "insteadEffect"); final String player = FieldUtils.getString(effectObject.get("player"), "player", "you"); final String fpCharacter = FieldUtils.getString(effectObject.get("fpCharacter"), "fpCharacter", "choose(any)"); final String minion = FieldUtils.getString(effectObject.get("minion"), "minion", "choose(any)"); + JSONObject[] preventCostArray = FieldUtils.getObjectArray(effectObject.get("preventCost"), "preventCost"); + JSONObject[] insteadEffectArray = FieldUtils.getObjectArray(effectObject.get("insteadEffect"), "insteadEffect"); + final String preventText = FieldUtils.getString(effectObject.get("preventText"), "preventText"); + if ((preventCostArray.length > 0 && preventText == null) || (preventCostArray.length == 0 && preventText != null)) + throw new InvalidCardDefinitionException("preventText and preventCost have to be specified (or not) together"); + if (insteadEffectArray.length > 0 && preventCostArray.length == 0) + throw new InvalidCardDefinitionException("preventCost is required if insteadEffect is present"); + EffectAppender[] preventEffectAppenders = environment.getEffectAppenderFactory().getEffectAppenders(preventCostArray, environment); + EffectAppender[] insteadEffectAppenders = environment.getEffectAppenderFactory().getEffectAppenders(insteadEffectArray, environment); + final String minionMemory = FieldUtils.getString(effectObject.get("memorizeMinion"), "memorizeMinion", "_tempMinion"); final String fpCharacterMemory = FieldUtils.getString(effectObject.get("memorizeFPCharacter"), "memorizeFPCharacter", "_tempFpCharacter"); final boolean ignoreUnassigned = FieldUtils.getBoolean(effectObject.get("ignoreUnassigned"), "ignoreUnassigned", false); @@ -38,7 +46,6 @@ public class AssignFpCharacterToSkirmish implements EffectAppenderProducer { final FilterableSource minionFilter = getSource(minion, environment); MultiEffectAppender result = new MultiEffectAppender(); - result.addEffectAppender( CardResolver.resolveCard(fpCharacter, (actionContext) -> { @@ -52,29 +59,41 @@ public class AssignFpCharacterToSkirmish implements EffectAppenderProducer { (actionContext) -> { final String assigningPlayer = playerSource.getPlayer(actionContext); Side assigningSide = GameUtils.getSide(actionContext.getGame(), assigningPlayer); - final Collection fpChar = actionContext.getCardsFromMemory("_tempFpCharacter"); + final Collection fpChar = actionContext.getCardsFromMemory(fpCharacterMemory); return Filters.assignableToSkirmishAgainst(assigningSide, Filters.in(fpChar), ignoreUnassigned, false); }, minionMemory, player, "Choose minion to assign to character", environment)); - result.addEffectAppender( - new DelayedAppender() { - @Override - protected List createEffects(boolean cost, CostToEffectAction action, ActionContext actionContext) { - final String assigningPlayer = playerSource.getPlayer(actionContext); - final Collection fpChar = actionContext.getCardsFromMemory(fpCharacterMemory); - final Collection minion = actionContext.getCardsFromMemory(minionMemory); - if (fpChar.size() == 1 && minion.size() == 1) { - AssignmentEffect effect = new AssignmentEffect(assigningPlayer, fpChar.iterator().next(), minion.iterator().next()); - effect.setIgnoreSingleMinionRestriction(ignoreUnassigned); - return Collections.singletonList(effect); - } - return null; - } - }); + + DelayedAppender assignAppender = new DelayedAppender() { + @Override + protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) { + final String assigningPlayer = playerSource.getPlayer(actionContext); + final Collection fpChar = actionContext.getCardsFromMemory(fpCharacterMemory); + final Collection minion = actionContext.getCardsFromMemory(minionMemory); + if (fpChar.size() == 1 && minion.size() == 1) { + AssignmentEffect effect = new AssignmentEffect(assigningPlayer, fpChar.iterator().next(), minion.iterator().next()); + effect.setIgnoreSingleMinionRestriction(ignoreUnassigned); + return effect; + } else { + return null; + } + } + }; + + if (preventEffectAppenders.length > 0) { + result.addEffectAppender( + new PreventableEffectAppender(new OpponentPlayerSource(playerSource), preventText, + actionContext -> { + final Collection fpChar = actionContext.getCardsFromMemory(fpCharacterMemory); + final Collection minion1 = actionContext.getCardsFromMemory(minionMemory); + return fpChar.size() == 1 && minion1.size() == 1; + }, preventEffectAppenders, new EffectAppender[]{assignAppender}, insteadEffectAppenders)); + } else { + result.addEffectAppender(assignAppender); + } return result; } - private FilterableSource getSource(String filter, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { if (filter.startsWith("choose(") && filter.endsWith(")")) return environment.getFilterFactory().generateFilter(filter.substring(filter.indexOf("(") + 1, filter.lastIndexOf(")")), environment); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableAppenderProducer.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableAppenderProducer.java index c4169db80..b26105050 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableAppenderProducer.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableAppenderProducer.java @@ -1,19 +1,13 @@ package com.gempukku.lotro.cards.build.field.effect.appender; -import com.gempukku.lotro.cards.build.*; +import com.gempukku.lotro.cards.build.CardGenerationEnvironment; +import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; +import com.gempukku.lotro.cards.build.PlayerSource; 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.state.LotroGame; -import com.gempukku.lotro.logic.GameUtils; -import com.gempukku.lotro.logic.actions.CostToEffectAction; -import com.gempukku.lotro.logic.actions.SubAction; -import com.gempukku.lotro.logic.decisions.YesNoDecision; -import com.gempukku.lotro.logic.effects.PlayoutDecisionEffect; -import com.gempukku.lotro.logic.effects.StackActionEffect; -import com.gempukku.lotro.logic.timing.Effect; -import com.gempukku.lotro.logic.timing.UnrespondableEffect; +import com.google.common.base.Predicates; import org.json.simple.JSONObject; public class PreventableAppenderProducer implements EffectAppenderProducer { @@ -37,87 +31,6 @@ public class PreventableAppenderProducer implements EffectAppenderProducer { final EffectAppender[] costAppenders = environment.getEffectAppenderFactory().getEffectAppenders(costArray, environment); final EffectAppender[] insteadAppenders = environment.getEffectAppenderFactory().getEffectAppenders(insteadArray, environment); - return new DelayedAppender() { - @Override - protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) { - if (areCostsPlayable(actionContext)) { - final String preventingPlayer = preventingPlayerSource.getPlayer(actionContext); - - String textToUse = GameUtils.substituteText(text, actionContext); - - SubAction subAction = new SubAction(action); - subAction.appendEffect( - new PlayoutDecisionEffect(preventingPlayer, - new YesNoDecision(textToUse) { - @Override - protected void yes() { - actionContext.getGame().getGameState().sendMessage(GameUtils.substituteText("{" + player + "} chooses to prevent.", actionContext)); - DelegateActionContext delegate = new DelegateActionContext(actionContext, - preventingPlayer, actionContext.getGame(), actionContext.getSource(), actionContext.getEffectResult(), - actionContext.getEffect()); - for (EffectAppender costAppender : costAppenders) - costAppender.appendEffect(false, subAction, delegate); - - subAction.appendEffect( - new UnrespondableEffect() { - @Override - protected void doPlayEffect(LotroGame game) { - // If the prevention was not carried out, need to do the original action anyway - if (!subAction.wasCarriedOut()) { - game.getGameState().sendMessage(GameUtils.substituteText("{" + player + "} attempted to prevent, but could not carry it out.", actionContext)); - for (EffectAppender effectAppender : effectAppenders) - effectAppender.appendEffect(false, subAction, actionContext); - } else { - for (EffectAppender insteadAppender : insteadAppenders) { - insteadAppender.appendEffect(false, subAction, actionContext); - } - } - } - - @Override - public boolean wasCarriedOut() { - // Cheating a bit, we need to check if the preventing effect was carried out, - // but have no way of doing this, as we can do that through subAction only, - // and this checking effect should be ALWAYS considered fine, even before it - // was done - return true; - } - }); - } - - @Override - protected void no() { - actionContext.getGame().getGameState().sendMessage(GameUtils.substituteText("{" + player + "} decides not to prevent.", actionContext)); - for (EffectAppender effectAppender : effectAppenders) - effectAppender.appendEffect(false, subAction, actionContext); - } - })); - return new StackActionEffect(subAction); - } else { - SubAction subAction = new SubAction(action); - for (EffectAppender effectAppender : effectAppenders) - effectAppender.appendEffect(false, subAction, actionContext); - return new StackActionEffect(subAction); - } - } - - private boolean areCostsPlayable(ActionContext actionContext) { - for (EffectAppender costAppender : costAppenders) { - if (!costAppender.isPlayableInFull(actionContext)) - return false; - } - return true; - } - - @Override - public boolean isPlayableInFull(ActionContext actionContext) { - for (EffectAppender effectAppender : effectAppenders) { - if (!effectAppender.isPlayableInFull(actionContext)) - return false; - } - - return true; - } - }; + return new PreventableEffectAppender(preventingPlayerSource, text, Predicates.alwaysTrue(), costAppenders, effectAppenders, insteadAppenders); } } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableEffectAppender.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableEffectAppender.java new file mode 100644 index 000000000..2c0e93c47 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableEffectAppender.java @@ -0,0 +1,106 @@ +package com.gempukku.lotro.cards.build.field.effect.appender; + +import com.gempukku.lotro.cards.build.ActionContext; +import com.gempukku.lotro.cards.build.DelegateActionContext; +import com.gempukku.lotro.cards.build.PlayerSource; +import com.gempukku.lotro.cards.build.field.effect.EffectAppender; +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.actions.SubAction; +import com.gempukku.lotro.logic.decisions.YesNoDecision; +import com.gempukku.lotro.logic.effects.PlayoutDecisionEffect; +import com.gempukku.lotro.logic.effects.StackActionEffect; +import com.gempukku.lotro.logic.timing.Effect; +import com.gempukku.lotro.logic.timing.UnrespondableEffect; + +import java.util.function.Predicate; + +public class PreventableEffectAppender extends DelayedAppender { + private PlayerSource preventingPlayer; + private String preventText; + private Predicate preventingPredicate; + private EffectAppender[] costAppenders; + private EffectAppender[] effectAppenders; + private EffectAppender[] insteadAppenders; + + public PreventableEffectAppender(PlayerSource preventingPlayer, String preventText, Predicate preventingPredicate, + EffectAppender[] costAppenders, EffectAppender[] effectAppenders, EffectAppender[] insteadAppenders) { + this.preventingPlayer = preventingPlayer; + this.preventText = preventText; + this.preventingPredicate = preventingPredicate; + this.costAppenders = costAppenders; + this.effectAppenders = effectAppenders; + this.insteadAppenders = insteadAppenders; + } + + @Override + protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) { + String textToUse = GameUtils.substituteText(preventText, actionContext); + String preventingPlayerId = preventingPlayer.getPlayer(actionContext); + + DelegateActionContext preventCostActionContext = new DelegateActionContext(actionContext, preventingPlayerId, actionContext.getGame(), actionContext.getSource(), actionContext.getEffectResult(), actionContext.getEffect()); + + if (preventingPredicate.test(actionContext) && areCostsPlayable(preventCostActionContext)) { + SubAction subAction = new SubAction(action); + subAction.appendEffect(new PlayoutDecisionEffect(preventingPlayerId, new YesNoDecision(textToUse) { + @Override + protected void yes() { + actionContext.getGame().getGameState().sendMessage(GameUtils.substituteText(preventingPlayerId + " chooses to prevent.", actionContext)); + for (EffectAppender costAppender : costAppenders) + costAppender.appendEffect(false, subAction, preventCostActionContext); + + subAction.appendEffect(new UnrespondableEffect() { + @Override + protected void doPlayEffect(LotroGame game) { + // If the prevention was not carried out, need to do the original action anyway + if (!subAction.wasCarriedOut()) { + game.getGameState().sendMessage(GameUtils.substituteText(preventingPlayerId + " attempted to prevent, but could not carry it out.", actionContext)); + for (EffectAppender effectAppender : effectAppenders) + effectAppender.appendEffect(false, subAction, actionContext); + } else { + for (EffectAppender insteadAppender : insteadAppenders) { + insteadAppender.appendEffect(false, subAction, preventCostActionContext); + } + } + } + + @Override + public boolean wasCarriedOut() { + return true; + } + }); + } + + @Override + protected void no() { + actionContext.getGame().getGameState().sendMessage(GameUtils.substituteText(preventingPlayerId + " decides not to prevent.", actionContext)); + for (EffectAppender effectAppender : effectAppenders) + effectAppender.appendEffect(false, subAction, actionContext); + } + })); + return new StackActionEffect(subAction); + } else { + SubAction subAction = new SubAction(action); + for (EffectAppender effectAppender : effectAppenders) + effectAppender.appendEffect(false, subAction, actionContext); + return new StackActionEffect(subAction); + } + } + + private boolean areCostsPlayable(ActionContext actionContext) { + for (EffectAppender costAppender : costAppenders) { + if (!costAppender.isPlayableInFull(actionContext)) return false; + } + return true; + } + + @Override + public boolean isPlayableInFull(ActionContext actionContext) { + for (EffectAppender effectAppender : effectAppenders) { + if (!effectAppender.isPlayableInFull(actionContext)) return false; + } + + return true; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/resolver/PlayerResolver.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/resolver/PlayerResolver.java index 4ad0c9e4a..b30164617 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/resolver/PlayerResolver.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/resolver/PlayerResolver.java @@ -11,7 +11,6 @@ import java.util.Locale; public class PlayerResolver { public static PlayerSource resolvePlayer(String type, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - if (type.equalsIgnoreCase("you")) return ActionContext::getPerformingPlayer; if (type.equalsIgnoreCase("owner"))