Reinstating the ChooseOpponent effect type

- Reinstated ChooseOpponent and ChooseOpponentEffect (these really shouldn't have been deleted in the first place, as they will be crucial once multiplayer is worked on)
- Renamed HasInMemory -> HasCardInMemory
- Added HasMemory effect for checking whether anything has been saved to a given memory key
- Fixed Crashed Gate auto-adding threats if no site can be controlled
- Added missing Hunter keyword to the previous Elven Guardian fix unit tests
This commit is contained in:
Christian 'ketura' McCarty
2025-03-22 20:50:03 -05:00
parent 0580fa4da6
commit d598486f91
12 changed files with 128 additions and 28 deletions

View File

@@ -240,7 +240,7 @@
{
type: If
check: {
type: hasInMemory
type: HasCardInMemory
memory: revealedCard
}
true: {

View File

@@ -29,7 +29,7 @@
{
type: If
check: {
type: hasInMemory
type: HasCardInMemory
memory: revealedCard
}
true: {

View File

@@ -277,7 +277,7 @@
type: If
check: [
{
type: HasInMemory
type: HasCardInMemory
memory: discardedCard
}
{

View File

@@ -120,11 +120,12 @@
phase: regroup
}
player: free people
effect: {
effect: [
{
type: choice
texts: [
Add 3 threats
Opponent takes control of site
Choose an opponent to take control of a site
]
effects: [
{
@@ -132,6 +133,18 @@
amount: 3
}
{
type: ChooseOpponent
memorize: opponent
}
]
}
{
type: If
check: {
type: HasMemory
memory: opponent
}
true: {
type: Optional
player: shadow
text: Would you like to take control of a site?
@@ -140,8 +153,8 @@
player: shadow
}
}
]
}
]
}
]
gametext: At the start of the regroup phase, the Free Peoples player must add 3 threats or choose an opponent who may take control of a site.

View File

@@ -58,6 +58,7 @@ public class EffectAppenderFactory {
effectAppenderProducers.put("choosehowmanytospot", new ChooseHowManyToSpot());
effectAppenderProducers.put("choosehowmanythreatstospot", new ChooseHowManyThreatsToSpot());
effectAppenderProducers.put("choosehowmanytwilighttokenstospot", new ChooseHowManyTwilightTokensToSpot());
effectAppenderProducers.put("chooseopponent", new ChooseOpponent());
effectAppenderProducers.put("chooseyesorno", new ChooseYesOrNo());
effectAppenderProducers.put("consumesurplusdamage", new ConsumeSurplusDamage());
effectAppenderProducers.put("corruptringbearer", new CorruptRingBearer());

View File

@@ -0,0 +1,34 @@
package com.gempukku.lotro.cards.build.field.effect.appender;
import com.gempukku.lotro.cards.build.ActionContext;
import com.gempukku.lotro.cards.build.CardGenerationEnvironment;
import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
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.logic.actions.CostToEffectAction;
import com.gempukku.lotro.logic.effects.choose.ChooseOpponentEffect;
import com.gempukku.lotro.logic.timing.Effect;
import org.json.simple.JSONObject;
public class ChooseOpponent implements EffectAppenderProducer {
@Override
public EffectAppender createEffectAppender(boolean cost, JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(effectObject, "memorize");
final String memorize = FieldUtils.getString(effectObject.get("memorize"), "memorize");
return new DelayedAppender() {
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
return new ChooseOpponentEffect(actionContext.getPerformingPlayer()) {
@Override
protected void opponentChosen(String opponentId) {
actionContext.setValueToMemory(memorize, opponentId);
}
};
}
};
}
}

View File

@@ -1,6 +1,5 @@
package com.gempukku.lotro.cards.build.field.effect.requirement;
import com.gempukku.lotro.cards.build.ActionContext;
import com.gempukku.lotro.cards.build.CardGenerationEnvironment;
import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
import com.gempukku.lotro.cards.build.Requirement;
@@ -10,19 +9,16 @@ import org.json.simple.JSONObject;
import java.util.Collection;
public class HasInMemory implements RequirementProducer {
public class HasCardInMemory implements RequirementProducer {
@Override
public Requirement getPlayRequirement(JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(object, "memory");
final String memory = FieldUtils.getString(object.get("memory"), "memory");
return new Requirement() {
@Override
public boolean accepts(ActionContext actionContext) {
return actionContext -> {
Collection<? extends PhysicalCard> cardsFromMemory = actionContext.getCardsFromMemory(memory);
return cardsFromMemory.size() > 0;
}
return !cardsFromMemory.isEmpty();
};
}
}

View File

@@ -0,0 +1,23 @@
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 org.json.simple.JSONObject;
public class HasMemory implements RequirementProducer {
@Override
public Requirement getPlayRequirement(
JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(object, "memory");
final String memory = FieldUtils.getString(object.get("memory"), "memory");
return actionContext ->
actionContext.getValueFromMemory(memory) != null && actionContext.getCardsFromMemory(memory) != null;
}
}

View File

@@ -48,7 +48,8 @@ public class RequirementFactory {
requirementProducers.put("hascardinhand", new HasCardInHand());
requirementProducers.put("hascardinremoved", new HasCardInRemoved());
requirementProducers.put("hascardstacked", new HasCardStacked());
requirementProducers.put("hasinmemory", new HasInMemory());
requirementProducers.put("hascardinmemory", new HasCardInMemory());
requirementProducers.put("hasmemory", new HasMemory());
requirementProducers.put("hasinzonedata", new HasInZoneData());
requirementProducers.put("haveinitiative", new HaveInitiative());
requirementProducers.put("isahead", new IsAhead());

View File

@@ -0,0 +1,31 @@
package com.gempukku.lotro.logic.effects.choose;
import com.gempukku.lotro.game.state.LotroGame;
import com.gempukku.lotro.logic.GameUtils;
import com.gempukku.lotro.logic.decisions.MultipleChoiceAwaitingDecision;
import com.gempukku.lotro.logic.timing.UnrespondableEffect;
public abstract class ChooseOpponentEffect extends UnrespondableEffect {
private final String _playerId;
public ChooseOpponentEffect(String playerId) {
_playerId = playerId;
}
@Override
public void doPlayEffect(LotroGame game) {
String[] opponents = GameUtils.getOpponents(game, _playerId);
if (opponents.length == 1)
opponentChosen(opponents[0]);
else
game.getUserFeedback().sendAwaitingDecision(_playerId,
new MultipleChoiceAwaitingDecision(1, "Choose an opponent", opponents) {
@Override
protected void validDecisionMade(int index, String result) {
opponentChosen(result);
}
});
}
protected abstract void opponentChosen(String opponentId);
}

View File

@@ -270,7 +270,7 @@ public class RequirementsAtTest extends AbstractAtTest {
obj.put("memory", "m");
DefaultActionContext actionContext = new DefaultActionContext(P1, _game, null, null, null);
Requirement requirement = new HasInMemory().getPlayRequirement(obj, lotroCardBlueprintBuilder);
Requirement requirement = new HasCardInMemory().getPlayRequirement(obj, lotroCardBlueprintBuilder);
assertFalse(requirement.accepts(actionContext));
actionContext.setCardMemory("m", createCard(P1, "1_3"));
assertTrue(requirement.accepts(actionContext));

View File

@@ -3,7 +3,6 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set17;
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;
@@ -58,6 +57,8 @@ public class Card_17_007_ErrataTests
assertEquals(CardType.COMPANION, card.getBlueprint().getCardType());
assertEquals(Race.ELF, card.getBlueprint().getRace());
assertTrue(scn.hasKeyword(card, Keyword.VALIANT));
assertTrue(scn.hasKeyword(card, Keyword.HUNTER));
assertEquals(1, scn.GetKeywordCount(card, Keyword.HUNTER));
assertEquals(2, card.getBlueprint().getTwilightCost());
assertEquals(6, card.getBlueprint().getStrength());
assertEquals(3, card.getBlueprint().getVitality());