Added more ATs

This commit is contained in:
Marcin Sciesinski
2024-10-17 01:49:26 +07:00
parent 5a32d8d20b
commit 5400954588
11 changed files with 190 additions and 209 deletions

View File

@@ -30,8 +30,10 @@
effects: [
{
type: modifier
modifier: modifyMoveLimit
amount: 1
modifier: {
type: modifyMoveLimit
amount: 1
}
}
{
type: trigger

View File

@@ -80,7 +80,6 @@ public class EffectAppenderFactory {
effectAppenderProducers.put("exchangesite", new ExchangeSite());
effectAppenderProducers.put("exert", new Exert());
effectAppenderProducers.put("exhaust", new Exhaust());
effectAppenderProducers.put("filtercardsinmemory", new FilterCardsInMemory());
effectAppenderProducers.put("getcardsfromtopofdeck", new GetCardsFromTopOfDeck());
effectAppenderProducers.put("heal", new Heal());
effectAppenderProducers.put("incrementperphaselimit", new IncrementPerPhaseLimit());
@@ -155,7 +154,6 @@ public class EffectAppenderFactory {
effectAppenderProducers.put("removetokenscumulative", new RemoveTokensCumulative());
effectAppenderProducers.put("removetwilight", new RemoveTwilight());
effectAppenderProducers.put("reordertopcardsofdrawdeck", new ReorderTopCardsOfDrawDeck());
effectAppenderProducers.put("replaceinassignment", new ReplaceInAssignment());
effectAppenderProducers.put("replaceinskirmish", new ReplaceInSkirmish());
effectAppenderProducers.put("resetwhileinzonedata", new ResetWhileInZoneData());
effectAppenderProducers.put("returntohand", new ReturnToHand());

View File

@@ -1,70 +0,0 @@
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.FilterableSource;
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.common.Filterable;
import com.gempukku.lotro.filters.Filters;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.game.state.LotroGame;
import com.gempukku.lotro.logic.actions.CostToEffectAction;
import com.gempukku.lotro.logic.timing.Effect;
import com.gempukku.lotro.logic.timing.UnrespondableEffect;
import org.json.simple.JSONObject;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
public class FilterCardsInMemory implements EffectAppenderProducer {
@Override
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(effectObject, "filter", "memory", "memorizeMatching", "memorizeNotMatching");
final String filter = FieldUtils.getString(effectObject.get("filter"), "filter");
final String memory = FieldUtils.getString(effectObject.get("memory"), "memory");
final String memorizeMatching = FieldUtils.getString(effectObject.get("memorizeMatching"), "memorizeMatching");
final String memorizeNotMatching = FieldUtils.getString(effectObject.get("memorizeNotMatching"), "memorizeNotMatching");
if (filter == null)
throw new InvalidCardDefinitionException("Filter is required for a FilterCardsInMemory effect.");
if (memory == null)
throw new InvalidCardDefinitionException("Memory is required for a FilterCardsInMemory effect.");
if (memorizeMatching == null && memorizeNotMatching == null)
throw new InvalidCardDefinitionException("One of memorizeMatching or memorizeNotMatching is required for a FilterCardsInMemory effect.");
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
return new DelayedAppender() {
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
return new UnrespondableEffect() {
@Override
protected void doPlayEffect(LotroGame game) {
final Filterable filterable = filterableSource.getFilterable(actionContext);
final Collection<? extends PhysicalCard> cardsFromMemory = actionContext.getCardsFromMemory(memory);
List<PhysicalCard> matchingCards = new LinkedList<>();
List<PhysicalCard> notMatchingCards = new LinkedList<>();
for (PhysicalCard physicalCard : cardsFromMemory) {
if (Filters.accepts(game, filterable, physicalCard))
matchingCards.add(physicalCard);
else
notMatchingCards.add(physicalCard);
}
if (memorizeMatching != null)
actionContext.setCardMemory(memorizeMatching, matchingCards);
if (memorizeNotMatching != null)
actionContext.setCardMemory(memorizeNotMatching, notMatchingCards);
}
};
}
};
}
}

View File

@@ -1,59 +0,0 @@
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.common.Side;
import com.gempukku.lotro.logic.actions.CostToEffectAction;
import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
import com.gempukku.lotro.logic.decisions.IntegerAwaitingDecision;
import com.gempukku.lotro.logic.effects.AddUntilEndOfPhaseModifierEffect;
import com.gempukku.lotro.logic.effects.PlayoutDecisionEffect;
import com.gempukku.lotro.logic.modifiers.ArcheryTotalModifier;
import com.gempukku.lotro.logic.timing.Effect;
import com.gempukku.lotro.logic.timing.RuleUtils;
import org.json.simple.JSONObject;
public class ReduceArcheryTotal implements EffectAppenderProducer {
@Override
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(effectObject, "side", "memorize");
final Side side = FieldUtils.getEnum(Side.class, effectObject.get("side"), "side");
final String memorize = FieldUtils.getString(effectObject.get("memorize"), "memorize", "_temp");
MultiEffectAppender result = new MultiEffectAppender();
result.addEffectAppender(
new DelayedAppender() {
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
int archeryTotal = RuleUtils.calculateArcheryTotal(actionContext.getGame(), side);
return new PlayoutDecisionEffect(
actionContext.getPerformingPlayer(),
new IntegerAwaitingDecision(1, "Choose number to reduce archery by", 0, archeryTotal, archeryTotal) {
@Override
public void decisionMade(String result) throws DecisionResultInvalidException {
final int validatedResult = getValidatedResult(result);
actionContext.setValueToMemory(memorize, String.valueOf(validatedResult));
}
});
}
});
result.addEffectAppender(
new DelayedAppender() {
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
int modifier = Integer.parseInt(actionContext.getValueFromMemory(memorize));
return new AddUntilEndOfPhaseModifierEffect(
new ArcheryTotalModifier(actionContext.getSource(), side, -modifier));
}
}
);
return result;
}
}

View File

@@ -1,46 +0,0 @@
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.cards.build.field.effect.appender.resolver.CardResolver;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.logic.actions.CostToEffectAction;
import com.gempukku.lotro.logic.effects.ReplaceFpCharacterInAssignmentEffect;
import com.gempukku.lotro.logic.timing.DoNothingEffect;
import com.gempukku.lotro.logic.timing.Effect;
import org.json.simple.JSONObject;
public class ReplaceInAssignment implements EffectAppenderProducer {
@Override
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(effectObject, "select", "with");
final String select = FieldUtils.getString(effectObject.get("select"), "select");
final String with = FieldUtils.getString(effectObject.get("with"), "with");
MultiEffectAppender result = new MultiEffectAppender();
result.addEffectAppender(
CardResolver.resolveCard(select, "_oldAssignee", "you", "Choose assigned character to replace", environment));
result.addEffectAppender(
CardResolver.resolveCard(with, "_newAssignee", "you", "Choose character to replace with in assignment", environment));
result.addEffectAppender(
new DelayedAppender() {
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
final PhysicalCard oldCard = actionContext.getCardFromMemory("_oldAssignee");
final PhysicalCard newCard = actionContext.getCardFromMemory("_newAssignee");
if (oldCard != null && newCard != null)
return new ReplaceFpCharacterInAssignmentEffect(newCard, oldCard);
else
return new DoNothingEffect();
}
});
return result;
}
}

View File

@@ -1,25 +0,0 @@
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.ValueSource;
import com.gempukku.lotro.cards.build.field.FieldUtils;
import com.gempukku.lotro.cards.build.field.effect.appender.resolver.ValueResolver;
import org.json.simple.JSONObject;
public class IsNotEqual implements RequirementProducer {
@Override
public Requirement getPlayRequirement(JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(object, "firstNumber", "secondNumber");
final ValueSource firstNumber = ValueResolver.resolveEvaluator(object.get("firstNumber"), environment);
final ValueSource secondNumber = ValueResolver.resolveEvaluator(object.get("secondNumber"), environment);
return actionContext -> {
final int first = firstNumber.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
final int second = secondNumber.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
return first != second;
};
}
}

View File

@@ -17,7 +17,6 @@ public class RequirementFactory {
requirementProducers.put("not", new NotRequirementProducer());
requirementProducers.put("or", new OrRequirementProducer());
requirementProducers.put("isequal", new IsEqual());
requirementProducers.put("isnotequal", new IsNotEqual());
requirementProducers.put("isgreaterthan", new IsGreaterThan());
requirementProducers.put("isgreaterthanorequal", new IsGreaterThanOrEqual());
requirementProducers.put("islessthan", new IsLessThan());

View File

@@ -243,7 +243,6 @@ public class Filters {
|| game.getModifiersQuerying().isUnhastyCompanionAllowedToParticipateInSkirmishes(game, physicalCard)),
Filters.and(
CardType.MINION,
Filters.notAssignedToSkirmish,
(Filter) (game, physicalCard) -> (!game.getGameState().isFierceSkirmishes()) || game.getModifiersQuerying().hasKeyword(game, physicalCard, Keyword.FIERCE)));
return Filters.and(

View File

@@ -1,6 +1,8 @@
package com.gempukku.lotro.at;
import com.gempukku.lotro.common.Culture;
import com.gempukku.lotro.common.Phase;
import com.gempukku.lotro.common.Token;
import com.gempukku.lotro.common.Zone;
import com.gempukku.lotro.game.*;
import com.gempukku.lotro.game.formats.LotroFormatLibrary;
@@ -63,6 +65,10 @@ public abstract class AbstractAtTest {
return card;
}
public int getCultureTokens(PhysicalCard tomBombadilsHat, Culture culture) {
return _game.getGameState().getTokenCount(tomBombadilsHat, Token.findTokenForCulture(culture));
}
public void selectArbitraryCards(String player, String[] blueprintIds) throws DecisionResultInvalidException {
playerDecided(player, StringUtils.join(blueprintIds, ","));
}
@@ -128,8 +134,8 @@ public abstract class AbstractAtTest {
_game.getGameState().setTwilight(twilightPool);
}
public void addThreats(int threats) {
_game.getGameState().addThreats(_game.getGameState().getCurrentPlayerId(), threats);
public void addThreats(String player, int threats) {
_game.getGameState().addThreats(player, threats);
}
public int getThreats() {

View File

@@ -72,7 +72,7 @@ public class DiscountAtTest extends AbstractAtTest {
skipMulligans();
setTwilightPool(9);
addThreats(1);
addThreats(P1, 1);
// End fellowship phase
assertEquals(Phase.FELLOWSHIP, getPhase());

View File

@@ -1,5 +1,6 @@
package com.gempukku.lotro.at;
import com.gempukku.lotro.common.Culture;
import com.gempukku.lotro.common.Keyword;
import com.gempukku.lotro.common.Phase;
import com.gempukku.lotro.common.Zone;
@@ -710,4 +711,180 @@ public class TriggersAtTest extends AbstractAtTest {
selectNo(P1);
assertEquals(Zone.DISCARD, sarumansChill.getZone());
}
@Test
public void discardedFromPlay() throws Exception {
initializeSimplestGame();
PhysicalCard swordRack = addToZone(createCard(P1, "11_158"), Zone.SUPPORT);
PhysicalCard beyondTheHeightOfMen = addToZone(createCard(P2, "2_39"), Zone.HAND);
PhysicalCard urukScout = addToZone(createCard(P2, "2_47"), Zone.SHADOW_CHARACTERS);
PhysicalCard ringBearer = getRingBearer(P1);
PhysicalCard heavyChain = attachTo(createCard(P1, "4_278"), ringBearer);
passUntil(Phase.MANEUVER);
pass(P1);
assertEquals(Zone.ATTACHED, heavyChain.getZone());
selectCardAction(P2, beyondTheHeightOfMen);
assertEquals(Zone.DISCARD, heavyChain.getZone());
selectCardAction(P1, swordRack);
assertEquals(Zone.STACKED, heavyChain.getZone());
}
@Test
public void beforeThreatWounds() throws Exception {
initializeSimplestGame();
PhysicalCard mordorAssassin = addToZone(createCard(P2, "7_284"), Zone.SHADOW_CHARACTERS);
PhysicalCard attea = addToZone(createCard(P2, "1_229"), Zone.SHADOW_CHARACTERS);
PhysicalCard gimli = addToZone(createCard(P1, "5_7"), Zone.FREE_CHARACTERS);
addWounds(gimli, 2);
addThreats(P1, 2);
PhysicalCard ringBearer = getRingBearer(P1);
passUntil(Phase.ASSIGNMENT);
pass(P1);
pass(P2);
playerDecided(P1, gimli.getCardId() + " " + attea.getCardId());
playerDecided(P2, gimli.getCardId() + " " + mordorAssassin.getCardId());
selectCard(P1, gimli);
pass(P1);
pass(P2);
selectCardAction(P2, mordorAssassin);
assertTrue(_game.getGameState().getAssignments().stream().anyMatch(assignment ->
assignment.getFellowshipCharacter() == ringBearer && assignment.getShadowCharacters().stream().anyMatch(shadowCharacter -> shadowCharacter == mordorAssassin)));
}
@Test
public void assignedToSkirmish() throws Exception {
initializeSimplestGame();
PhysicalCard ringBearer = getRingBearer(P1);
PhysicalCard desperateDefenseOfTheRing = attachTo(createCard(P2, "1_244"), ringBearer);
PhysicalCard goblinRunner = addToZone(createCard(P2, "1_178"), Zone.SHADOW_CHARACTERS);
passUntil(Phase.ASSIGNMENT);
pass(P1);
pass(P2);
assertEquals(1, getBurdens());
playerDecided(P1, ringBearer.getCardId() + " " + goblinRunner.getCardId());
assertEquals(2, getBurdens());
}
@Test
public void assignedAgainst() throws Exception {
initializeSimplestGame();
PhysicalCard ringBearer = getRingBearer(P1);
PhysicalCard unferth = addToZone(createCard(P2, "4_178"), Zone.SHADOW_CHARACTERS);
passUntil(Phase.ASSIGNMENT);
pass(P1);
pass(P2);
assertEquals(0, getWounds(ringBearer));
playerDecided(P1, ringBearer.getCardId() + " " + unferth.getCardId());
assertEquals(1, getWounds(ringBearer));
}
@Test
public void afterAllSkirmishes() throws Exception {
initializeSimplestGame();
PhysicalCard witchKing = addToZone(createCard(P2, "12_183"), Zone.SHADOW_CHARACTERS);
PhysicalCard witchKingsBeast = attachTo(createCard(P2, "12_184"), witchKing);
passUntil(Phase.ASSIGNMENT);
// Normal Assignment actions
pass(P1);
pass(P2);
// Normal Assignments
pass(P1);
pass(P2);
// Fierce Assignment actions
pass(P1);
pass(P2);
// Fierce Assignments
pass(P1);
pass(P2);
hasCardAction(P2, witchKingsBeast);
}
@Test
public void addsThreat() throws Exception {
initializeSimplestGame();
PhysicalCard tomBombadilsHat = addToZone(createCard(P1, "0_60"), Zone.SUPPORT);
PhysicalCard warTowers = addToZone(createCard(P2, "7_173"), Zone.HAND);
PhysicalCard desertNomad = addToZone(createCard(P2, "7_132"), Zone.SHADOW_CHARACTERS);
passUntil(Phase.MANEUVER);
pass(P1);
selectCardAction(P2, warTowers);
assertEquals(1, getCultureTokens(tomBombadilsHat, Culture.SHIRE));
}
@Test
public void addsBurden() throws Exception {
initializeSimplestGame();
PhysicalCard ringBearer = getRingBearer(P1);
PhysicalCard tomBombadilsHat = addToZone(createCard(P1, "0_60"), Zone.SUPPORT);
PhysicalCard desperateDefenseOfTheRing = attachTo(createCard(P2, "1_244"), ringBearer);
PhysicalCard goblinRunner = addToZone(createCard(P2, "1_178"), Zone.SHADOW_CHARACTERS);
passUntil(Phase.ASSIGNMENT);
pass(P1);
pass(P2);
playerDecided(P1, ringBearer.getCardId() + " " + goblinRunner.getCardId());
assertEquals(1, getCultureTokens(tomBombadilsHat, Culture.SHIRE));
}
@Test
public void aboutToTakeControlOfSite() throws Exception {
initializeSimplestGame();
PhysicalCard whiteHandIntruder = addToZone(createCard(P2, "17_127"), Zone.SHADOW_CHARACTERS);
PhysicalCard gimli = addToZone(createCard(P1, "5_7"), Zone.FREE_CHARACTERS);
for (int i = 0; i < 2; i++) {
addToZone(createCard(P2, "17_119"), Zone.SHADOW_CHARACTERS);
}
PhysicalCard ceorl = addToZone(createCard(P1, "4_264"), Zone.SUPPORT);
PhysicalCard guma = addToZone(createCard(P1, "4_277"), Zone.SUPPORT);
passUntil(Phase.SHADOW);
_game.getGameState().setPlayerPosition(P2, 2);
passUntil(Phase.ASSIGNMENT);
pass(P1);
pass(P2);
playerDecided(P1, gimli.getCardId() + " " + whiteHandIntruder.getCardId());
pass(P2);
selectCard(P1, gimli);
pass(P1);
pass(P2);
selectCardAction(P2, whiteHandIntruder);
hasCardAction(P1, ceorl);
}
@Test
public void aboutToHeal() throws Exception {
initializeSimplestGame();
PhysicalCard frodo = getRingBearer(P1);
PhysicalCard extraordinaryResilience = addToZone(createCard(P1, "1_287"), Zone.HAND);
PhysicalCard theGaffer = addToZone(createCard(P1, "1_291"), Zone.SUPPORT);
addWounds(frodo, 1);
passUntil(Phase.FELLOWSHIP);
assertEquals(1, getBurdens());
selectCardAction(P1, theGaffer);
selectCardAction(P1, extraordinaryResilience);
assertEquals(1, getWounds(frodo));
assertEquals(0, getBurdens());
}
}