Overhauled FilterFactory

- rearranged all simple and parameterized behavior filters to be alphabetized
- altered parameterized filters to all be case insensitive
- altered parameter interpretation to ignore spaces
- altered memory handling to be case insensitive
- improved Side and Signet interpretation to be case insensitive and to be flexible in what it accepts
This commit is contained in:
Christian 'ketura' McCarty
2022-08-17 18:56:38 -05:00
parent b9034b07ad
commit 294efcd80c
6 changed files with 351 additions and 305 deletions

View File

@@ -6,12 +6,13 @@ public enum Side implements Filterable {
public static Side Parse(String value) {
value = value
.toLowerCase()
.replace("_", " ")
.replace("-", " ");
.replace(" ", "")
.replace("_", "")
.replace("-", "");
if(value.contains("shadow"))
return SHADOW;
if(value.contains("freeps") || value.contains("free people") || value.contains("free peoples"))
if(value.contains("freeps") || value.contains("free") || value.contains("people"))
return FREE_PEOPLE;
return null;

View File

@@ -12,4 +12,15 @@ public enum Signet implements Filterable {
public String toString() {
return displayText;
}
public static Signet findSignet(String name) {
String nameCaps = name.toUpperCase().replace(" ", "");
String nameLower = name.toLowerCase();
for (Signet signet : values()) {
if (signet.toString().toLowerCase().equals(nameLower) || signet.toString().equals(nameCaps))
return signet;
}
return null;
}
}

View File

@@ -31,11 +31,12 @@ public class DefaultActionContext implements ActionContext {
@Override
public void setValueToMemory(String memory, String value) {
valueMemory.put(memory, value);
valueMemory.put(memory.toLowerCase(), value);
}
@Override
public String getValueFromMemory(String memory) {
memory = memory.toLowerCase();
final String result = valueMemory.get(memory);
if (result == null)
throw new IllegalArgumentException("Memory not found - " + memory);
@@ -44,6 +45,7 @@ public class DefaultActionContext implements ActionContext {
@Override
public void setCardMemory(String memory, PhysicalCard card) {
memory = memory.toLowerCase();
cardMemory.removeAll(memory);
if (card != null)
cardMemory.put(memory, card);
@@ -51,17 +53,19 @@ public class DefaultActionContext implements ActionContext {
@Override
public void setCardMemory(String memory, Collection<? extends PhysicalCard> cards) {
memory = memory.toLowerCase();
cardMemory.removeAll(memory);
cardMemory.putAll(memory, cards);
}
@Override
public Collection<? extends PhysicalCard> getCardsFromMemory(String memory) {
return cardMemory.get(memory);
return cardMemory.get(memory.toLowerCase());
}
@Override
public PhysicalCard getCardFromMemory(String memory) {
memory = memory.toLowerCase();
final Collection<PhysicalCard> physicalCards = cardMemory.get(memory);
if (physicalCards.size() == 0)
return null;

View File

@@ -27,32 +27,32 @@ public class DelegateActionContext implements ActionContext {
@Override
public void setValueToMemory(String memory, String value) {
delegate.setValueToMemory(memory, value);
delegate.setValueToMemory(memory.toLowerCase(), value);
}
@Override
public String getValueFromMemory(String memory) {
return delegate.getValueFromMemory(memory);
return delegate.getValueFromMemory(memory.toLowerCase());
}
@Override
public void setCardMemory(String memory, PhysicalCard card) {
delegate.setCardMemory(memory, card);
delegate.setCardMemory(memory.toLowerCase(), card);
}
@Override
public void setCardMemory(String memory, Collection<? extends PhysicalCard> cards) {
delegate.setCardMemory(memory, cards);
delegate.setCardMemory(memory.toLowerCase(), cards);
}
@Override
public Collection<? extends PhysicalCard> getCardsFromMemory(String memory) {
return delegate.getCardsFromMemory(memory);
return delegate.getCardsFromMemory(memory.toLowerCase());
}
@Override
public PhysicalCard getCardFromMemory(String memory) {
return delegate.getCardFromMemory(memory);
return delegate.getCardFromMemory(memory.toLowerCase());
}
@Override

View File

@@ -29,277 +29,83 @@ public class FilterFactory {
for (Race value : Race.values())
appendFilter(value);
simpleFilters.put("ring bearer", (actionContext) -> Filters.ringBearer);
simpleFilters.put("ringbearer", (actionContext) -> Filters.ringBearer);
simpleFilters.put("ring-bearer", (actionContext) -> Filters.ringBearer);
simpleFilters.put("any", (actionContext) -> Filters.any);
simpleFilters.put("self", ActionContext::getSource);
simpleFilters.put("allyincurrentregion", (actionContext) -> Filters.isAllyInCurrentRegion());
simpleFilters.put("another", (actionContext) -> Filters.not(actionContext.getSource()));
simpleFilters.put("your", (actionContext) -> Filters.owner(actionContext.getPerformingPlayer()));
simpleFilters.put("unique", (actionContext) -> Filters.unique);
simpleFilters.put("bearer", (actionContext -> Filters.hasAttached(actionContext.getSource())));
simpleFilters.put("character", (actionContext) -> Filters.character);
simpleFilters.put("mounted", (actionContext) -> Filters.mounted);
simpleFilters.put("weapon", (actionContext) -> Filters.weapon);
simpleFilters.put("item", (actionContext) -> Filters.item);
simpleFilters.put("wounded", (actionContext) -> Filters.wounded);
simpleFilters.put("unwounded", (actionContext) -> Filters.unwounded);
simpleFilters.put("exhausted", (actionContext) -> Filters.exhausted);
simpleFilters.put("inskirmish", (actionContext) -> Filters.inSkirmish);
simpleFilters.put("infierceskirmish", (actionContext) -> Filters.inFierceSkirmish);
simpleFilters.put("inplay", (actionContext) -> Filters.inPlay);
simpleFilters.put("notassignedtoskirmish",
(actionContext) -> Filters.notAssignedToSkirmish);
simpleFilters.put("skirmishloser",
(actionContext) -> {
final CharacterLostSkirmishResult lostSkirmish = (CharacterLostSkirmishResult) actionContext.getEffectResult();
return lostSkirmish.getLoser();
});
simpleFilters.put("ring bound",
(actionContext) -> Filters.ringBoundCompanion);
simpleFilters.put("ringbound",
(actionContext) -> Filters.ringBoundCompanion);
simpleFilters.put("ring-bound",
(actionContext) -> Filters.ringBoundCompanion);
simpleFilters.put("unbound",
(actionContext) -> Filters.unboundCompanion);
simpleFilters.put("any", (actionContext) -> Filters.any);
simpleFilters.put("attachedtoinsameregion",
actionContext -> {
final PhysicalCard attachedTo = actionContext.getSource().getAttachedTo();
return Filters.region(GameUtils.getRegion(attachedTo.getSiteNumber()));
});
simpleFilters.put("insameregion",
actionContext -> Filters.region(GameUtils.getRegion(actionContext.getSource().getSiteNumber())));
simpleFilters.put("bearer", (actionContext -> Filters.hasAttached(actionContext.getSource())));
simpleFilters.put("character", (actionContext) -> Filters.character);
simpleFilters.put("controlledsite",
(actionContext -> Filters.siteControlled(actionContext.getPerformingPlayer())));
simpleFilters.put("currentsite",
(actionContext) -> Filters.currentSite);
simpleFilters.put("currentsitenumber",
(actionContext -> Filters.siteNumber(actionContext.getGame().getGameState().getCurrentSiteNumber())));
simpleFilters.put("siteincurrentregion",
(actionContext) -> Filters.siteInCurrentRegion);
simpleFilters.put("sitehassitenumber",
(actionContext) -> Filters.siteHasSiteNumber);
simpleFilters.put("exhausted", (actionContext) -> Filters.exhausted);
simpleFilters.put("idinstored",
(actionContext ->
new Filter() {
@Override
public boolean accepts(LotroGame game, PhysicalCard physicalCard) {
final String whileInZoneData = (String) actionContext.getSource().getWhileInZoneData();
if (whileInZoneData == null)
return false;
for (String cardId : whileInZoneData.split(",")) {
if (cardId.equals(String.valueOf(physicalCard.getCardId())))
return true;
}
(Filter) (game, physicalCard) -> {
final String whileInZoneData = (String) actionContext.getSource().getWhileInZoneData();
if (whileInZoneData == null)
return false;
for (String cardId : whileInZoneData.split(",")) {
if (cardId.equals(String.valueOf(physicalCard.getCardId())))
return true;
}
}));
simpleFilters.put("controlledsite",
(actionContext -> Filters.siteControlled(actionContext.getPerformingPlayer())));
parameterFilters.put("culture", (parameter, environment) -> {
final Culture culture = Culture.valueOf(parameter.toUpperCase());
if (culture == null)
throw new InvalidCardDefinitionException("Unable to find culture for: " + parameter);
return (actionContext) -> culture;
});
parameterFilters.put("signet", (parameter, environment) -> {
final Signet signet = Signet.valueOf(parameter.toUpperCase());
if (signet == null)
throw new InvalidCardDefinitionException("Unable to find culture for: " + parameter);
return (actionContext) -> signet;
});
parameterFilters.put("cultureFromMemory", ((parameter, environment) -> actionContext -> {
Set<Culture> cultures = new HashSet<>();
for (PhysicalCard physicalCard : actionContext.getCardsFromMemory(parameter)) {
cultures.add(physicalCard.getBlueprint().getCulture());
}
return Filters.or(cultures.toArray(new Culture[0]));
}));
parameterFilters.put("side", (parameter, environment) -> {
final Side side = Side.Parse(parameter);
if (side == null)
throw new InvalidCardDefinitionException("Unable to find side for: " + parameter);
return (actionContext) -> side;
});
parameterFilters.put("hasToken", (parameter, environment) -> {
final Culture culture = Culture.valueOf(parameter.toUpperCase());
if (culture == null)
throw new InvalidCardDefinitionException("Unable to find culture for: " + parameter);
final Token token = Token.findTokenForCulture(culture);
if (token == null)
throw new InvalidCardDefinitionException("Unable to find token for culture: " + parameter);
return (actionContext) -> Filters.hasToken(token);
});
parameterFilters.put("hasTokenCount", (parameter, environment) -> {
String[] parameterSplit = parameter.split(",", 2);
int count = Integer.parseInt(parameterSplit[0]);
final Culture culture = Culture.valueOf(parameterSplit[1].toUpperCase());
if (culture == null)
throw new InvalidCardDefinitionException("Unable to find culture for: " + parameter);
final Token token = Token.findTokenForCulture(culture);
if (token == null)
throw new InvalidCardDefinitionException("Unable to find token for culture: " + parameter);
return (actionContext) -> Filters.hasToken(token, count);
});
parameterFilters.put("hasAttached",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return (actionContext) -> Filters.hasAttached(filterableSource.getFilterable(actionContext));
});
parameterFilters.put("hasAttachedCount",
(parameter, environment) -> {
String[] parameterSplit = parameter.split(",", 2);
int count = Integer.parseInt(parameterSplit[0]);
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameterSplit[1], environment);
return (actionContext) -> Filters.hasAttached(count, filterableSource.getFilterable(actionContext));
});
parameterFilters.put("hasStacked",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return (actionContext) -> Filters.hasStacked(filterableSource.getFilterable(actionContext));
});
parameterFilters.put("hasStackedCount",
(parameter, environment) -> {
String[] parameterSplit = parameter.split(",", 2);
int count = Integer.parseInt(parameterSplit[0]);
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameterSplit[1], environment);
return (actionContext) -> Filters.hasStacked(count, filterableSource.getFilterable(actionContext));
});
parameterFilters.put("attachedTo",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return (actionContext) -> Filters.attachedTo(filterableSource.getFilterable(actionContext));
});
parameterFilters.put("name",
(parameter, environment) -> (actionContext) -> (Filter)
(game, physicalCard) -> physicalCard.getBlueprint().getTitle().equalsIgnoreCase(parameter));
parameterFilters.put("title",parameterFilters.get("name"));
parameterFilters.put("nameInStackedOn",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return actionContext -> {
final Filterable sourceFilterable = filterableSource.getFilterable(actionContext);
return (Filter) (game, physicalCard) -> {
for (PhysicalCard cardWithStack : Filters.filterActive(game, sourceFilterable)) {
for (PhysicalCard stackedCard : game.getGameState().getStackedCards(cardWithStack)) {
if (stackedCard.getBlueprint().getTitle().equals(physicalCard.getBlueprint().getTitle()))
return true;
}
}
return false;
};
};
}));
simpleFilters.put("infierceskirmish", (actionContext) -> Filters.inFierceSkirmish);
simpleFilters.put("inplay", (actionContext) -> Filters.inPlay);
simpleFilters.put("insameregion",
actionContext -> Filters.region(GameUtils.getRegion(actionContext.getSource().getSiteNumber())));
simpleFilters.put("inskirmish", (actionContext) -> Filters.inSkirmish);
simpleFilters.put("item", (actionContext) -> Filters.item);
simpleFilters.put("mounted", (actionContext) -> Filters.mounted);
simpleFilters.put("notassignedtoskirmish",
(actionContext) -> Filters.notAssignedToSkirmish);
simpleFilters.put("ringbearer", (actionContext) -> Filters.ringBearer);
simpleFilters.put("ring-bearer", (actionContext) -> Filters.ringBearer);
simpleFilters.put("ringbound",
(actionContext) -> Filters.ringBoundCompanion);
simpleFilters.put("ring-bound",
(actionContext) -> Filters.ringBoundCompanion);
simpleFilters.put("self", ActionContext::getSource);
simpleFilters.put("sitehassitenumber",
(actionContext) -> Filters.siteHasSiteNumber);
simpleFilters.put("siteincurrentregion",
(actionContext) -> Filters.siteInCurrentRegion);
simpleFilters.put("skirmishloser",
(actionContext) -> {
final CharacterLostSkirmishResult lostSkirmish = (CharacterLostSkirmishResult) actionContext.getEffectResult();
return lostSkirmish.getLoser();
});
parameterFilters.put("inSkirmishAgainst",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return (actionContext) -> Filters.inSkirmishAgainst(filterableSource.getFilterable(actionContext));
});
parameterFilters.put("assignedToSkirmish",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return (actionContext) -> Filters.assignedToSkirmishAgainst(filterableSource.getFilterable(actionContext));
});
parameterFilters.put("resistanceLessThan",
(parameter, environment) -> {
int amount = Integer.parseInt(parameter);
return (actionContext) -> Filters.maxResistance(amount - 1);
});
parameterFilters.put("resistanceMoreThan",
(parameter, environment) -> {
int amount = Integer.parseInt(parameter);
return (actionContext) -> Filters.minResistance(amount + 1);
});
parameterFilters.put("strengthLessThan",
(parameter, environment) -> {
int amount = Integer.parseInt(parameter);
return (actionContext) -> Filters.lessStrengthThan(amount);
});
parameterFilters.put("strengthMoreThan",
(parameter, environment) -> {
int amount = Integer.parseInt(parameter);
return (actionContext) -> Filters.moreStrengthThan(amount);
});
parameterFilters.put("vitalityMoreThan",
(parameter, environment) -> {
int amount = Integer.parseInt(parameter);
return (actionContext) -> Filters.moreVitalityThan(amount);
});
parameterFilters.put("not",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return (actionContext) -> Filters.not(filterableSource.getFilterable(actionContext));
});
parameterFilters.put("allyHome",
simpleFilters.put("unbound",
(actionContext) -> Filters.unboundCompanion);
simpleFilters.put("unique", (actionContext) -> Filters.unique);
simpleFilters.put("unwounded", (actionContext) -> Filters.unwounded);
simpleFilters.put("weapon", (actionContext) -> Filters.weapon);
simpleFilters.put("wounded", (actionContext) -> Filters.wounded);
simpleFilters.put("your", (actionContext) -> Filters.owner(actionContext.getPerformingPlayer()));
parameterFilters.put("allyhome",
(parameter, environment) -> {
final String[] parameterSplit = parameter.split(",");
final SitesBlock sitesBlock = Enum.valueOf(SitesBlock.class, parameterSplit[0].toUpperCase().replace('_', ' '));
final SitesBlock sitesBlock = SitesBlock.findBlock(parameterSplit[0]);
int number = Integer.parseInt(parameterSplit[1]);
return (actionContext) -> Filters.isAllyHome(number, sitesBlock);
});
parameterFilters.put("allyInRegion",
parameterFilters.put("allyinregion",
(parameter, environment) -> {
final String[] parameterSplit = parameter.split(",");
final SitesBlock sitesBlock = Enum.valueOf(SitesBlock.class, parameterSplit[0].toUpperCase().replace('_', ' '));
int number = Integer.parseInt(parameterSplit[1]);
return (actionContext) -> Filters.isAllyInRegion(number, sitesBlock);
});
parameterFilters.put("allyInCurrentRegion",
(parameter, environment) -> (actionContext) -> Filters.isAllyInCurrentRegion());
parameterFilters.put("siteBlock",
(parameter, environment) -> {
final SitesBlock sitesBlock = Enum.valueOf(SitesBlock.class, parameter.toUpperCase().replace(' ', '_'));
return (actionContext) -> Filters.siteBlock(sitesBlock);
});
parameterFilters.put("siteNumber",
(parameter, environment) -> {
int min, max;
if (parameter.contains("-")) {
final String[] split = parameter.split("-", 2);
min = Integer.parseInt(split[0]);
max = Integer.parseInt(split[1]);
} else {
min = max = Integer.parseInt(parameter);
}
return (actionContext) -> Filters.siteNumberBetweenInclusive(min, max);
});
parameterFilters.put("regionNumber",
(parameter, environment) -> {
int min, max;
if (parameter.contains("-")) {
final String[] split = parameter.split("-", 2);
min = Integer.parseInt(split[0]);
max = Integer.parseInt(split[1]);
} else {
min = max = Integer.parseInt(parameter);
}
if(min < 0 || max > 3 || max < min)
throw new InvalidCardDefinitionException("Region number definition is invalid: " + parameter);
return (actionContext) -> Filters.regionNumberBetweenInclusive(min, max);
});
parameterFilters.put("or",
(parameter, environment) -> {
final String[] filters = splitIntoFilters(parameter);
FilterableSource[] filterables = new FilterableSource[filters.length];
for (int i = 0; i < filters.length; i++)
filterables[i] = environment.getFilterFactory().generateFilter(filters[i], environment);
return (actionContext) -> {
Filterable[] filters1 = new Filterable[filterables.length];
for (int i = 0; i < filterables.length; i++)
filters1[i] = filterables[i].getFilterable(actionContext);
return Filters.or(filters1);
};
});
parameterFilters.put("and",
(parameter, environment) -> {
final String[] filters = splitIntoFilters(parameter);
@@ -314,9 +120,116 @@ public class FilterFactory {
return Filters.and(filters1);
};
});
parameterFilters.put("memory",
(parameter, environment) -> (actionContext) -> Filters.in(actionContext.getCardsFromMemory(parameter)));
parameterFilters.put("maxTwilight",
parameterFilters.put("assignabletoskirmishagainst",
(parameter, environment) -> {
final FilterableSource againstFilterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return actionContext -> {
final Side side = GameUtils.getSide(actionContext.getGame(), actionContext.getPerformingPlayer());
return Filters.assignableToSkirmishAgainst(side, againstFilterableSource.getFilterable(actionContext));
};
});
parameterFilters.put("assignedtoskirmish",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return (actionContext) -> Filters.assignedToSkirmishAgainst(filterableSource.getFilterable(actionContext));
});
parameterFilters.put("attachedto",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return (actionContext) -> Filters.attachedTo(filterableSource.getFilterable(actionContext));
});
parameterFilters.put("culture", (parameter, environment) -> {
final Culture culture = Culture.findCulture(parameter);
if (culture == null)
throw new InvalidCardDefinitionException("Unable to find culture for: " + parameter);
return (actionContext) -> culture;
});
parameterFilters.put("culturefrommemory", ((parameter, environment) -> actionContext -> {
Set<Culture> cultures = new HashSet<>();
for (PhysicalCard physicalCard : actionContext.getCardsFromMemory(parameter)) {
cultures.add(physicalCard.getBlueprint().getCulture());
}
return Filters.or(cultures.toArray(new Culture[0]));
}));
parameterFilters.put("hasattached",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return (actionContext) -> Filters.hasAttached(filterableSource.getFilterable(actionContext));
});
parameterFilters.put("hasattachedcount",
(parameter, environment) -> {
String[] parameterSplit = parameter.split(",", 2);
int count = Integer.parseInt(parameterSplit[0]);
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameterSplit[1], environment);
return (actionContext) -> Filters.hasAttached(count, filterableSource.getFilterable(actionContext));
});
parameterFilters.put("hasstacked",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return (actionContext) -> Filters.hasStacked(filterableSource.getFilterable(actionContext));
});
parameterFilters.put("hasstackedcount",
(parameter, environment) -> {
String[] parameterSplit = parameter.split(",", 2);
int count = Integer.parseInt(parameterSplit[0]);
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameterSplit[1], environment);
return (actionContext) -> Filters.hasStacked(count, filterableSource.getFilterable(actionContext));
});
parameterFilters.put("hasanytokens", (parameter, environment) -> {
int count = Integer.parseInt(parameter != null ? parameter : "1");
return (actionContext) -> Filters.hasAnyCultureTokens(count);
});
parameterFilters.put("hastoken", (parameter, environment) -> {
final Culture culture = Culture.findCulture(parameter);
if (culture == null)
throw new InvalidCardDefinitionException("Unable to find culture for: " + parameter);
final Token token = Token.findTokenForCulture(culture);
if (token == null)
throw new InvalidCardDefinitionException("Unable to find token for culture: " + parameter);
return (actionContext) -> Filters.hasToken(token);
});
parameterFilters.put("hastokencount", (parameter, environment) -> {
String[] parameterSplit = parameter.split(",", 2);
int count = Integer.parseInt(parameterSplit[0]);
final Culture culture = Culture.findCulture(parameterSplit[1]);
if (culture == null)
throw new InvalidCardDefinitionException("Unable to find culture for: " + parameter);
final Token token = Token.findTokenForCulture(culture);
if (token == null)
throw new InvalidCardDefinitionException("Unable to find token for culture: " + parameter);
return (actionContext) -> Filters.hasToken(token, count);
});
parameterFilters.put("inskirmishagainst",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return (actionContext) -> Filters.inSkirmishAgainst(filterableSource.getFilterable(actionContext));
});
parameterFilters.put("loweststrength",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return actionContext -> {
final Filterable sourceFilterable = filterableSource.getFilterable(actionContext);
return Filters.and(
sourceFilterable, Filters.strengthEqual(
new SingleMemoryEvaluator(
new Evaluator() {
@Override
public int evaluateExpression(LotroGame game, PhysicalCard cardAffected) {
int minStrength = Integer.MAX_VALUE;
for (PhysicalCard card : Filters.filterActive(game, sourceFilterable))
minStrength = Math.min(minStrength, game.getModifiersQuerying().getStrength(game, card));
return minStrength;
}
}
)
)
);
};
});
parameterFilters.put("maxtwilight",
(parameter, environment) -> {
if (parameter.startsWith("memory(") && parameter.endsWith(")")) {
String memory = parameter.substring(parameter.indexOf("(") + 1, parameter.lastIndexOf(")"));
@@ -337,7 +250,9 @@ public class FilterFactory {
};
}
});
parameterFilters.put("minTwilight",
parameterFilters.put("memory",
(parameter, environment) -> (actionContext) -> Filters.in(actionContext.getCardsFromMemory(parameter)));
parameterFilters.put("mintwilight",
(parameter, environment) -> {
if (parameter.startsWith("memory(") && parameter.endsWith(")")) {
String memory = parameter.substring(parameter.indexOf("(") + 1, parameter.lastIndexOf(")"));
@@ -358,34 +273,55 @@ public class FilterFactory {
};
}
});
parameterFilters.put("lowestStrength",
parameterFilters.put("name",
(parameter, environment) -> {
String name = Sanitize(parameter);
return (actionContext) -> (Filter)
(game, physicalCard) -> name != null
&& physicalCard.getBlueprint().getTitle() != null
&& name.equals(Sanitize(physicalCard.getBlueprint().getTitle()));
});
parameterFilters.put("namefrommemory",
(parameter, environment) -> actionContext -> {
Set<String> titles = new HashSet<>();
for (PhysicalCard physicalCard : actionContext.getCardsFromMemory(parameter))
titles.add(physicalCard.getBlueprint().getTitle());
return (Filter) (game, physicalCard) -> titles.contains(physicalCard.getBlueprint().getTitle());
});
parameterFilters.put("nameinstackedon",
(parameter, environment) -> {
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return actionContext -> {
final Filterable sourceFilterable = filterableSource.getFilterable(actionContext);
return Filters.and(
sourceFilterable, Filters.strengthEqual(
new SingleMemoryEvaluator(
new Evaluator() {
@Override
public int evaluateExpression(LotroGame game, PhysicalCard cardAffected) {
int minStrength = Integer.MAX_VALUE;
for (PhysicalCard card : Filters.filterActive(game, sourceFilterable))
minStrength = Math.min(minStrength, game.getModifiersQuerying().getStrength(game, card));
return minStrength;
}
}
)
)
);
return (Filter) (game, physicalCard) -> {
for (PhysicalCard cardWithStack : Filters.filterActive(game, sourceFilterable)) {
for (PhysicalCard stackedCard : game.getGameState().getStackedCards(cardWithStack)) {
if (stackedCard.getBlueprint().getTitle().equals(physicalCard.getBlueprint().getTitle()))
return true;
}
}
return false;
};
};
});
parameterFilters.put("assignableToSkirmishAgainst",
parameterFilters.put("not",
(parameter, environment) -> {
final FilterableSource againstFilterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return actionContext -> {
final Side side = GameUtils.getSide(actionContext.getGame(), actionContext.getPerformingPlayer());
return Filters.assignableToSkirmishAgainst(side, againstFilterableSource.getFilterable(actionContext));
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(parameter, environment);
return (actionContext) -> Filters.not(filterableSource.getFilterable(actionContext));
});
parameterFilters.put("or",
(parameter, environment) -> {
final String[] filters = splitIntoFilters(parameter);
FilterableSource[] filterables = new FilterableSource[filters.length];
for (int i = 0; i < filters.length; i++)
filterables[i] = environment.getFilterFactory().generateFilter(filters[i], environment);
return (actionContext) -> {
Filterable[] filters1 = new Filterable[filterables.length];
for (int i = 0; i < filterables.length; i++)
filters1[i] = filterables[i].getFilterable(actionContext);
return Filters.or(filters1);
};
});
parameterFilters.put("race",
@@ -398,7 +334,7 @@ public class FilterFactory {
else
return Race.valueOf(value) == physicalCard.getBlueprint().getRace();
};
} else if (parameter.equals("cannotSpot")) {
} else if (parameter.equals("cannotspot")) {
return actionContext -> (Filter) (game, physicalCard) -> {
final Race race = physicalCard.getBlueprint().getRace();
if (race != null)
@@ -406,27 +342,108 @@ public class FilterFactory {
return false;
};
}
throw new InvalidCardDefinitionException("Unknown race definition in filter");
throw new InvalidCardDefinitionException("Unknown race definition in filter: " + parameter
+ ". Do not use race() for races; instead just list the race by itself.");
});
parameterFilters.put("nameFromMemory",
new FilterableSourceProducer() {
@Override
public FilterableSource createFilterableSource(String parameter, CardGenerationEnvironment environment) {
return new FilterableSource() {
@Override
public Filterable getFilterable(ActionContext actionContext) {
Set<String> titles = new HashSet<>();
for (PhysicalCard physicalCard : actionContext.getCardsFromMemory(parameter))
titles.add(physicalCard.getBlueprint().getTitle());
return new Filter() {
@Override
public boolean accepts(LotroGame game, PhysicalCard physicalCard) {
return titles.contains(physicalCard.getBlueprint().getTitle());
}
};
}
};
parameterFilters.put("regionnumber",
(parameter, environment) -> {
int min, max;
if (parameter.contains("-")) {
final String[] split = parameter.split("-", 2);
min = Integer.parseInt(split[0]);
max = Integer.parseInt(split[1]);
} else {
min = max = Integer.parseInt(parameter);
}
if(min < 0 || max > 3 || max < min)
throw new InvalidCardDefinitionException("Region number definition is invalid: " + parameter);
return (actionContext) -> Filters.regionNumberBetweenInclusive(min, max);
});
parameterFilters.put("resistancelessthan",
(parameter, environment) -> {
final ValueSource valueSource = ValueResolver.resolveEvaluator(parameter, environment);
return (actionContext) -> {
int amount = valueSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
return Filters.maxResistance(amount - 1);
};
});
parameterFilters.put("resistancemorethan",
(parameter, environment) -> {
final ValueSource valueSource = ValueResolver.resolveEvaluator(parameter, environment);
return (actionContext) -> {
int amount = valueSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
return Filters.minResistance(amount + 1);
};
});
parameterFilters.put("side", (parameter, environment) -> {
final Side side = Side.Parse(parameter);
if (side == null)
throw new InvalidCardDefinitionException("Unable to find side for: " + parameter);
return (actionContext) -> side;
});
parameterFilters.put("signet", (parameter, environment) -> {
final Signet signet = Signet.findSignet(parameter);
if (signet == null)
throw new InvalidCardDefinitionException("Unable to find signet for: " + parameter);
return (actionContext) -> signet;
});
parameterFilters.put("siteblock",
(parameter, environment) -> {
final SitesBlock sitesBlock = SitesBlock.findBlock(parameter);
return (actionContext) -> Filters.siteBlock(sitesBlock);
});
parameterFilters.put("sitenumber",
(parameter, environment) -> {
int min, max;
if (parameter.contains("-")) {
final String[] split = parameter.split("-", 2);
min = Integer.parseInt(split[0]);
max = Integer.parseInt(split[1]);
} else {
min = max = Integer.parseInt(parameter);
}
return (actionContext) -> Filters.siteNumberBetweenInclusive(min, max);
});
parameterFilters.put("strengthlessthan",
(parameter, environment) -> {
final ValueSource valueSource = ValueResolver.resolveEvaluator(parameter, environment);
return (actionContext) -> {
int amount = valueSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
return Filters.lessStrengthThan(amount);
};
});
parameterFilters.put("strengthmorethan",
(parameter, environment) -> {
final ValueSource valueSource = ValueResolver.resolveEvaluator(parameter, environment);
return (actionContext) -> {
int amount = valueSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
return Filters.moreStrengthThan(amount);
};
});
parameterFilters.put("title",parameterFilters.get("name"));
parameterFilters.put("vitalitylessthan",
(parameter, environment) -> {
final ValueSource valueSource = ValueResolver.resolveEvaluator(parameter, environment);
return (actionContext) -> {
int amount = valueSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
return Filters.lessVitalityThan(amount);
};
});
parameterFilters.put("vitalitymorethan",
(parameter, environment) -> {
final ValueSource valueSource = ValueResolver.resolveEvaluator(parameter, environment);
return (actionContext) -> {
int amount = valueSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
return Filters.moreVitalityThan(amount);
};
});
parameterFilters.put("zone",
(parameter, environment) -> {
@@ -436,7 +453,7 @@ public class FilterFactory {
}
private void appendFilter(Filterable value) {
final String filterName = value.toString().toLowerCase().replace("_", " ");
final String filterName = Sanitize(value.toString());
final String optionalFilterName = value.toString().toLowerCase().replace("_", "-");
if (simpleFilters.containsKey(filterName))
throw new RuntimeException("Duplicate filter name: " + filterName);
@@ -508,23 +525,33 @@ public class FilterFactory {
if (filterString.contains("(") && filterString.endsWith(")")) {
String filterName = filterString.substring(0, filterString.indexOf("("));
String filterParameter = filterString.substring(filterString.indexOf("(") + 1, filterString.lastIndexOf(")"));
return lookupFilter(filterName, filterParameter, environment);
return lookupFilter(Sanitize(filterName), Sanitize(filterParameter), environment);
}
return lookupFilter(filterString, null, environment);
return lookupFilter(Sanitize(filterString), null, environment);
}
private FilterableSource lookupFilter(String name, String parameter, CardGenerationEnvironment environment) throws
InvalidCardDefinitionException {
if (parameter == null) {
FilterableSource result = simpleFilters.get(name.toLowerCase());
FilterableSource result = simpleFilters.get(Sanitize(name));
if (result != null)
return result;
}
final FilterableSourceProducer filterableSourceProducer = parameterFilters.get(name);
final FilterableSourceProducer filterableSourceProducer = parameterFilters.get(Sanitize(name));
if (filterableSourceProducer == null)
throw new InvalidCardDefinitionException("Unable to find filter: " + name);
return filterableSourceProducer.createFilterableSource(parameter, environment);
}
public static String Sanitize(String input)
{
return input
.toLowerCase()
.replace(" ", "")
.replace("_", "");
}
}

View File

@@ -37,7 +37,10 @@ public class AddTokenEffect extends AbstractEffect {
@Override
public String getText(LotroGame game) {
return null;
if (_token != null)
return "Add " + _count + " " + _token.getCulture().getHumanReadable() + " token" + (_count > 1 ? "s" : "");
else
return "Add " + _count + " culture token" + (_count > 1 ? "s" : "");
}
@Override