Consolidating card resolving

This commit is contained in:
marcin.sciesinski
2021-01-16 13:14:34 -08:00
parent 0b21422f0e
commit 601b3c4764

View File

@@ -44,57 +44,24 @@ public class CardResolver {
String memory, String choicePlayer, String choiceText, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
Function<ActionContext, Iterable<? extends PhysicalCard>> cardSource = actionContext -> {
final Filterable stackedOnFilter = stackedOn.getFilterable(actionContext);
return Filters.filterActive(actionContext.getGame(), stackedOnFilter);
return Filters.filterActive(actionContext.getGame(), Filters.stackedOn(stackedOnFilter));
};
if (type.startsWith("memory(") && type.endsWith(")")) {
return resolveMemoryCards(type, choiceFilter, playabilityFilter, countSource, memory, cardSource);
} else if (type.startsWith("choose(") && type.endsWith(")")) {
final String filter = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")"));
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
final PlayerSource playerSource = PlayerResolver.resolvePlayer(choicePlayer, environment);
return new DelayedAppender() {
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
final int min = countSource.getMinimum(actionContext);
final Filterable filterable = filterableSource.getFilterable(actionContext);
final Filterable stackedOnFilter = stackedOn.getFilterable(actionContext);
Filterable additionalFilterable = Filters.any;
if (playabilityFilter != null)
additionalFilterable = playabilityFilter.getFilterable(actionContext);
List<PhysicalCard> choice = new LinkedList<>();
final LotroGame game = actionContext.getGame();
for (PhysicalCard stackedOn : Filters.filterActive(game, stackedOnFilter)) {
final List<PhysicalCard> stackedCards = game.getGameState().getStackedCards(stackedOn);
choice.addAll(Filters.filter(stackedCards, game, filterable, additionalFilterable));
ChoiceEffectSource effectSource = (possibleCards, action, actionContext, min, max) -> {
String choicePlayerId = playerSource.getPlayer(actionContext);
return new ChooseStackedCardsEffect(action, choicePlayerId, min, max, stackedOn.getFilterable(actionContext), Filters.in(possibleCards)) {
@Override
protected void cardsChosen(LotroGame game, Collection<PhysicalCard> stackedCards) {
actionContext.setCardMemory(memory, stackedCards);
}
return choice.size() >= min;
}
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
final Filterable filterable = filterableSource.getFilterable(actionContext);
final Filterable stackedOnFilter = stackedOn.getFilterable(actionContext);
String choicePlayerId = playerSource.getPlayer(actionContext);
int min = countSource.getMinimum(actionContext);
int max = countSource.getMaximum(actionContext);
Filterable additionalFilterable = Filters.any;
if (choiceFilter != null)
additionalFilterable = choiceFilter.getFilterable(actionContext);
return new ChooseStackedCardsEffect(action, choicePlayerId, min, max, stackedOnFilter, Filters.and(filterable, additionalFilterable)) {
@Override
protected void cardsChosen(LotroGame game, Collection<PhysicalCard> stackedCards) {
actionContext.setCardMemory(memory, stackedCards);
}
};
}
};
};
return resolveChoiceCards(type, choiceFilter, playabilityFilter, countSource, environment, cardSource, effectSource);
}
throw new RuntimeException("Unable to resolve card resolver of type: " + type);
}
@@ -140,75 +107,19 @@ public class CardResolver {
} else if (type.startsWith("memory(") && type.endsWith(")")) {
return resolveMemoryCards(type, additionalFilter, additionalFilter, countSource, memory, cardSource);
} else if (type.startsWith("all(") && type.endsWith(")")) {
final String filter = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")"));
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);
String handId = handSource.getPlayer(actionContext);
Filterable additionalFilterable = Filters.any;
if (additionalFilter != null)
additionalFilterable = additionalFilter.getFilterable(actionContext);
actionContext.setCardMemory(memory, Filters.filter(game.getGameState().getHand(handId), game, filterable, additionalFilterable));
}
};
}
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
return true;
}
};
return resolveAllCards(type, additionalFilter, memory, environment, cardSource);
} else if (type.startsWith("choose(") && type.endsWith(")")) {
final String filter = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")"));
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
final PlayerSource playerSource = PlayerResolver.resolvePlayer(choicePlayer, environment);
return new DelayedAppender() {
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
int min = countSource.getMinimum(actionContext);
final Filterable filterable = filterableSource.getFilterable(actionContext);
String handId = handSource.getPlayer(actionContext);
Filterable additionalFilterable = Filters.any;
if (additionalFilter != null)
additionalFilterable = additionalFilter.getFilterable(actionContext);
final LotroGame game = actionContext.getGame();
return Filters.filter(game.getGameState().getHand(handId), game, filterable, additionalFilterable).size() >= min;
}
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
int min = countSource.getMinimum(actionContext);
int max = countSource.getMaximum(actionContext);
final Filterable filterable = filterableSource.getFilterable(actionContext);
String choicePlayerId = playerSource.getPlayer(actionContext);
String handId = handSource.getPlayer(actionContext);
Filterable additionalFilterable = Filters.any;
if (additionalFilter != null)
additionalFilterable = additionalFilter.getFilterable(actionContext);
if (handId.equals(choicePlayerId)) {
return new ChooseCardsFromHandEffect(choicePlayerId, min, max, filterable, additionalFilterable) {
@Override
protected void cardsSelected(LotroGame game, Collection<PhysicalCard> cards) {
actionContext.setCardMemory(memory, cards);
}
};
} else {
final LotroGame game = actionContext.getGame();
final Collection<PhysicalCard> matchingCards = Filters.filter(game.getGameState().getHand(handId), game, filterable, additionalFilterable);
return new ChooseArbitraryCardsEffect(choicePlayerId, choiceText, matchingCards, min, max) {
@Override
protected void cardsSelected(LotroGame game, Collection<PhysicalCard> selectedCards) {
actionContext.setCardMemory(memory, selectedCards);
}
};
ChoiceEffectSource effectSource = (possibleCards, action, actionContext, min, max) -> {
String handId = handSource.getPlayer(actionContext);
return new ChooseCardsFromHandEffect(handId, min, max, Filters.in(possibleCards)) {
@Override
protected void cardsSelected(LotroGame game, Collection<PhysicalCard> cards) {
actionContext.setCardMemory(memory, cards);
}
}
};
};
return resolveChoiceCards(type, additionalFilter, additionalFilter, countSource, environment, cardSource, effectSource);
}
throw new RuntimeException("Unable to resolve card resolver of type: " + type);
}
@@ -234,62 +145,19 @@ public class CardResolver {
} else if (type.startsWith("memory(") && type.endsWith(")")) {
return resolveMemoryCards(type, choiceFilter, playabilityFilter, countSource, memory, cardSource);
} else if (type.startsWith("all(") && type.endsWith(")")) {
final String filter = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")"));
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
return new DelayedAppender() {
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
return true;
}
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
return new UnrespondableEffect() {
@Override
protected void doPlayEffect(LotroGame game) {
final Filterable filter = filterableSource.getFilterable(actionContext);
String choicePlayerId = playerSource.getPlayer(actionContext);
Filterable filterable = Filters.any;
if (choiceFilter != null)
filterable = choiceFilter.getFilterable(actionContext);
actionContext.setCardMemory(memory, Filters.filter(game.getGameState().getDiscard(choicePlayerId), game, filter, filterable));
}
};
}
};
return resolveAllCards(type, choiceFilter, memory, environment, cardSource);
} else if (type.startsWith("choose(") && type.endsWith(")")) {
final String filter = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")"));
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
return new DelayedAppender() {
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
int min = countSource.getMinimum(actionContext);
final Filterable filter = filterableSource.getFilterable(actionContext);
String choicePlayerId = playerSource.getPlayer(actionContext);
Filterable additionalFilterable = Filters.any;
if (playabilityFilter != null)
additionalFilterable = playabilityFilter.getFilterable(actionContext);
final LotroGame game = actionContext.getGame();
return Filters.filter(game.getGameState().getDiscard(choicePlayerId), game, filter, additionalFilterable).size() >= min;
}
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
int min = countSource.getMinimum(actionContext);
int max = countSource.getMaximum(actionContext);
final Filterable filterable = filterableSource.getFilterable(actionContext);
String choicePlayerId = playerSource.getPlayer(actionContext);
Filterable additionalFilterable = Filters.any;
if (choiceFilter != null)
additionalFilterable = choiceFilter.getFilterable(actionContext);
return new ChooseCardsFromDiscardEffect(choicePlayerId, min, max, filterable, additionalFilterable) {
@Override
protected void cardsSelected(LotroGame game, Collection<PhysicalCard> cards) {
actionContext.setCardMemory(memory, cards);
}
};
}
ChoiceEffectSource effectSource = (possibleCards, action, actionContext, min, max) -> {
String choicePlayerId = playerSource.getPlayer(actionContext);
return new ChooseCardsFromDiscardEffect(choicePlayerId, min, max, Filters.in(possibleCards)) {
@Override
protected void cardsSelected(LotroGame game, Collection<PhysicalCard> cards) {
actionContext.setCardMemory(memory, cards);
}
};
};
return resolveChoiceCards(type, choiceFilter, playabilityFilter, countSource, environment, cardSource, effectSource);
}
throw new RuntimeException("Unable to resolve card resolver of type: " + type);
}
@@ -304,52 +172,19 @@ public class CardResolver {
if (type.startsWith("memory(") && type.endsWith(")")) {
return resolveMemoryCards(type, choiceFilter, choiceFilter, countSource, memory, cardSource);
} else if (type.startsWith("all(") && type.endsWith(")")) {
final String filter = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")"));
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 String player = playerSource.getPlayer(actionContext);
final Filterable filterable = filterableSource.getFilterable(actionContext);
actionContext.setCardMemory(memory, Filters.filter(game.getGameState().getDeck(player), game, filterable));
}
};
}
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
return true;
}
};
return resolveAllCards(type, choiceFilter, memory, environment, cardSource);
} else if (type.startsWith("choose(") && type.endsWith(")")) {
final String filter = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")"));
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
return new DelayedAppender() {
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
return true;
}
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
int min = countSource.getMinimum(actionContext);
int max = countSource.getMaximum(actionContext);
final Filterable filterable = filterableSource.getFilterable(actionContext);
String choicePlayerId = playerSource.getPlayer(actionContext);
Filterable additionalFilterable = Filters.any;
if (choiceFilter != null)
additionalFilterable = choiceFilter.getFilterable(actionContext);
return new ChooseCardsFromDeckEffect(choicePlayerId, min, max, filterable, additionalFilterable) {
@Override
protected void cardsSelected(LotroGame game, Collection<PhysicalCard> cards) {
actionContext.setCardMemory(memory, cards);
}
};
}
ChoiceEffectSource effectSource = (possibleCards, action, actionContext, min, max) -> {
String choicePlayerId = playerSource.getPlayer(actionContext);
return new ChooseCardsFromDeckEffect(choicePlayerId, min, max, Filters.in(possibleCards)) {
@Override
protected void cardsSelected(LotroGame game, Collection<PhysicalCard> cards) {
actionContext.setCardMemory(memory, cards);
}
};
};
return resolveChoiceCards(type, choiceFilter, choiceFilter, countSource, environment, cardSource, effectSource);
}
throw new RuntimeException("Unable to resolve card resolver of type: " + type);
}
@@ -401,57 +236,20 @@ public class CardResolver {
} else if (type.startsWith("memory(") && type.endsWith(")")) {
return resolveMemoryCards(type, additionalFilter, playabilityFilter, countSource, memory, cardSource);
} else if (type.startsWith("all(") && type.endsWith(")")) {
final String filter = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")"));
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);
actionContext.setCardMemory(memory, Filters.filterActive(game, filterable));
}
};
}
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
return true;
}
};
return resolveAllCards(type, additionalFilter, memory, environment, cardSource);
} else if (type.startsWith("choose(") && type.endsWith(")")) {
final String filter = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")"));
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
final PlayerSource playerSource = PlayerResolver.resolvePlayer(choicePlayer, environment);
return new DelayedAppender() {
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
int min = countSource.getMinimum(actionContext);
final Filterable filterable = filterableSource.getFilterable(actionContext);
Filterable additionalFilterable = Filters.any;
if (playabilityFilter != null)
additionalFilterable = playabilityFilter.getFilterable(actionContext);
return PlayConditions.isActive(actionContext.getGame(), min, filterable, additionalFilterable);
}
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
int min = countSource.getMinimum(actionContext);
int max = countSource.getMaximum(actionContext);
final Filterable filterable = filterableSource.getFilterable(actionContext);
Filterable additionalFilterable = Filters.any;
if (additionalFilter != null)
additionalFilterable = additionalFilter.getFilterable(actionContext);
String choicePlayerId = playerSource.getPlayer(actionContext);
return new ChooseActiveCardsEffect(actionContext.getSource(), choicePlayerId, choiceText, min, max, filterable, additionalFilterable) {
@Override
protected void cardsSelected(LotroGame game, Collection<PhysicalCard> cards) {
actionContext.setCardMemory(memory, cards);
}
};
}
ChoiceEffectSource effectSource = (possibleCards, action, actionContext, min, max) -> {
String choicePlayerId = playerSource.getPlayer(actionContext);
return new ChooseActiveCardsEffect(actionContext.getSource(), choicePlayerId, choiceText, min, max, Filters.in(possibleCards)) {
@Override
protected void cardsSelected(LotroGame game, Collection<PhysicalCard> cards) {
actionContext.setCardMemory(memory, cards);
}
};
};
return resolveChoiceCards(type, additionalFilter, playabilityFilter, countSource, environment, cardSource, effectSource);
}
throw new InvalidCardDefinitionException("Unable to resolve card resolver of type: " + type);
}
@@ -497,7 +295,7 @@ public class CardResolver {
return new DelayedAppender() {
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
int min = countSource.getMinimum(null);
int min = countSource.getMinimum(actionContext);
return filterCards(actionContext, playabilityFilter).size() >= min;
}
@@ -521,4 +319,62 @@ public class CardResolver {
}
};
}
private static DelayedAppender resolveChoiceCards(String type, FilterableSource choiceFilter, FilterableSource playabilityFilter,
ValueSource countSource, CardGenerationEnvironment environment, Function<ActionContext, Iterable<? extends PhysicalCard>> cardSource, ChoiceEffectSource effectSource) throws InvalidCardDefinitionException {
final String filter = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")"));
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
return new DelayedAppender() {
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
int min = countSource.getMinimum(actionContext);
return filterCards(actionContext, playabilityFilter).size() >= min;
}
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
int min = countSource.getMinimum(actionContext);
int max = countSource.getMaximum(actionContext);
return effectSource.createEffect(filterCards(actionContext, choiceFilter), action, actionContext, min, max);
}
private Collection<PhysicalCard> filterCards(ActionContext actionContext, FilterableSource filter) {
Filterable filterable = filterableSource.getFilterable(actionContext);
Filterable additionalFilterable = Filters.any;
if (filter != null)
additionalFilterable = filter.getFilterable(actionContext);
return Filters.filter(cardSource.apply(actionContext), actionContext.getGame(), filterable, additionalFilterable);
}
};
}
private static DelayedAppender resolveAllCards(String type, FilterableSource additionalFilter, String memory, CardGenerationEnvironment environment, Function<ActionContext, Iterable<? extends PhysicalCard>> cardSource) throws InvalidCardDefinitionException {
final String filter = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")"));
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) {
actionContext.setCardMemory(memory, filterCards(actionContext, additionalFilter));
}
private Collection<PhysicalCard> filterCards(ActionContext actionContext, FilterableSource filter) {
final Filterable filterable = filterableSource.getFilterable(actionContext);
Filterable additionalFilterable = Filters.any;
if (filter != null)
additionalFilterable = filter.getFilterable(actionContext);
return Filters.filter(cardSource.apply(actionContext), actionContext.getGame(), filterable, additionalFilterable);
}
};
}
};
}
private interface ChoiceEffectSource {
Effect createEffect(Collection<? extends PhysicalCard> possibleCards, CostToEffectAction action, ActionContext actionContext,
int min, int max);
}
}