mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-14 09:48:02 +00:00
AbilityUtils: refactor Party types (#8967)
This commit is contained in:
@@ -547,7 +547,14 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
|
||||
if (!isCreature() && !isKindred()) {
|
||||
return false;
|
||||
}
|
||||
return !Collections.disjoint(getCreatureTypes(), Constant.OUTLAW_TYPES);
|
||||
return Constant.OUTLAW_TYPES.stream().anyMatch(s -> hasCreatureType(s));
|
||||
}
|
||||
@Override
|
||||
public boolean isParty() {
|
||||
if (!isCreature() && !isKindred()) {
|
||||
return false;
|
||||
}
|
||||
return Constant.PARTY_TYPES.stream().anyMatch(s -> hasCreatureType(s));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -916,6 +923,12 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
|
||||
"Pirate",
|
||||
"Rogue",
|
||||
"Warlock");
|
||||
|
||||
public static final Set<String> PARTY_TYPES = Sets.newHashSet(
|
||||
"Cleric",
|
||||
"Rogue",
|
||||
"Warrior",
|
||||
"Wizard");
|
||||
}
|
||||
public static class Predicates {
|
||||
public static Predicate<String> IS_LAND_TYPE = CardType::isALandType;
|
||||
|
||||
@@ -64,6 +64,7 @@ public interface CardTypeView extends Iterable<String>, Serializable {
|
||||
boolean isSaga();
|
||||
boolean isHistoric();
|
||||
boolean isOutlaw();
|
||||
boolean isParty();
|
||||
|
||||
CardTypeView getTypeWithChanges(Iterable<CardChangedType> changedCardTypes);
|
||||
}
|
||||
|
||||
@@ -93,6 +93,8 @@ public class ForgeScript {
|
||||
}
|
||||
} else if (property.equals("Outlaw")) {
|
||||
return type.isOutlaw();
|
||||
} else if (property.equals("Party")) {
|
||||
return type.isParty();
|
||||
} else if (property.startsWith("non")) {
|
||||
// ... Other Card types
|
||||
return !type.hasStringType(property.substring(3));
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.google.common.collect.*;
|
||||
import com.google.common.math.IntMath;
|
||||
import forge.card.CardStateName;
|
||||
import forge.card.CardType;
|
||||
import forge.card.CardTypeView;
|
||||
import forge.card.ColorSet;
|
||||
import forge.card.MagicColor;
|
||||
import forge.card.mana.ManaAtom;
|
||||
@@ -42,6 +43,7 @@ import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class AbilityUtils {
|
||||
private final static ImmutableList<String> cmpList = ImmutableList.of("LT", "LE", "EQ", "GE", "GT", "NE");
|
||||
@@ -2601,61 +2603,65 @@ public class AbilityUtils {
|
||||
}
|
||||
|
||||
if (sq[0].contains("Party")) {
|
||||
CardCollection adventurers = CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield),
|
||||
"Creature.Cleric,Creature.Rogue,Creature.Warrior,Creature.Wizard", player, c, ctb);
|
||||
|
||||
Set<String> partyTypes = Sets.newHashSet("Cleric", "Rogue", "Warrior", "Wizard");
|
||||
int partySize = 0;
|
||||
|
||||
HashMap<String, Card> chosenParty = new HashMap<>();
|
||||
List<Card> wildcard = Lists.newArrayList();
|
||||
HashMap<Card, Set<String>> multityped = new HashMap<>();
|
||||
Set<String> chosenParty = Sets.newHashSet();
|
||||
int wildcard = 0;
|
||||
ListMultimap<String, Card> multityped = MultimapBuilder.hashKeys().arrayListValues().build();
|
||||
List<Card> chosenMulti = Lists.newArrayList();
|
||||
|
||||
// Figure out how to count each class separately.
|
||||
for (Card card : adventurers) {
|
||||
// cards with all creature types will just return full list
|
||||
Set<String> creatureTypes = card.getType().getCreatureTypes();
|
||||
creatureTypes.retainAll(partyTypes);
|
||||
|
||||
if (creatureTypes.size() == 4) {
|
||||
wildcard.add(card);
|
||||
|
||||
if (wildcard.size() >= 4) {
|
||||
break;
|
||||
}
|
||||
for (Card card : player.getCardsIn(ZoneType.Battlefield)) {
|
||||
if (!card.isCreature()) {
|
||||
continue;
|
||||
} else if (creatureTypes.size() == 1) {
|
||||
String type = (String)(creatureTypes.toArray()[0]);
|
||||
}
|
||||
CardTypeView type = card.getType();
|
||||
Set<String> creatureTypes;
|
||||
|
||||
if (!chosenParty.containsKey(type)) {
|
||||
chosenParty.put(type, card);
|
||||
// extra logic for "all creature types" cards
|
||||
if (type.hasAllCreatureTypes()) {
|
||||
// one of the party types could be excluded, so check each of them separate
|
||||
creatureTypes = CardType.Constant.PARTY_TYPES.stream().filter(p -> type.hasCreatureType(p)).collect(Collectors.toSet());
|
||||
} else { // shortcut for others
|
||||
creatureTypes = type.getCreatureTypes();
|
||||
creatureTypes.retainAll(CardType.Constant.PARTY_TYPES);
|
||||
}
|
||||
|
||||
switch (creatureTypes.size()) {
|
||||
case 0:
|
||||
continue;
|
||||
case 4:
|
||||
wildcard++;
|
||||
break;
|
||||
case 1:
|
||||
chosenParty.addAll(creatureTypes);
|
||||
break;
|
||||
default:
|
||||
for (String t : creatureTypes) {
|
||||
multityped.put(t, card);
|
||||
}
|
||||
} else {
|
||||
multityped.put(card, creatureTypes);
|
||||
}
|
||||
|
||||
// found enough
|
||||
if (chosenParty.size() + wildcard >= 4) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
partySize = Math.min(chosenParty.size() + wildcard.size(), 4);
|
||||
if (chosenParty.size() + wildcard < 4) {
|
||||
multityped.keySet().removeAll(chosenParty);
|
||||
|
||||
if (partySize < 4) {
|
||||
partyTypes.removeAll(chosenParty.keySet());
|
||||
|
||||
// Here I'm left with just the party types that I haven't selected.
|
||||
for (Card multi : multityped.keySet()) {
|
||||
Set<String> types = multityped.get(multi);
|
||||
types.retainAll(partyTypes);
|
||||
|
||||
for (String type : types) {
|
||||
chosenParty.put(type, multi);
|
||||
partyTypes.remove(type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// sort by amount of members
|
||||
Multimaps.asMap(multityped).entrySet().stream()
|
||||
.sorted(Map.Entry.<String, List<Card>>comparingByValue(Comparator.<List<Card>>comparingInt(Collection::size)))
|
||||
.forEach(e -> {
|
||||
e.getValue().removeAll(chosenMulti);
|
||||
if (e.getValue().size() > 0) {
|
||||
chosenParty.add(e.getKey());
|
||||
chosenMulti.add(e.getValue().get(0));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
partySize = Math.min(chosenParty.size() + wildcard.size(), 4);
|
||||
|
||||
return doXMath(partySize, expr, c, ctb);
|
||||
return doXMath(Math.min(chosenParty.size() + wildcard, 4), expr, c, ctb);
|
||||
}
|
||||
|
||||
// TODO make AI part to understand Sunburst better so this isn't needed
|
||||
|
||||
@@ -131,8 +131,7 @@ public class ChooseCardEffect extends SpellAbilityEffect {
|
||||
}
|
||||
} else if (sa.hasParam("ChooseEach")) {
|
||||
final String s = sa.getParam("ChooseEach");
|
||||
final String[] types = s.equals("Party") ? new String[]{"Cleric","Rogue","Warrior","Wizard"}
|
||||
: s.split(" & ");
|
||||
final Collection<String> types = s.equals("Party") ? CardType.Constant.PARTY_TYPES : Arrays.asList(s.split(" & "));
|
||||
for (final String type : types) {
|
||||
CardCollection valids = CardLists.filter(pChoices, CardPredicates.isType(type));
|
||||
if (!valids.isEmpty()) {
|
||||
|
||||
@@ -2,7 +2,6 @@ package forge.game.card;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import forge.StaticData;
|
||||
import forge.card.CardDb;
|
||||
import forge.card.ColorSet;
|
||||
@@ -720,17 +719,6 @@ public class CardProperty {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (property.equals("Party")) {
|
||||
boolean isParty = false;
|
||||
Set<String> partyTypes = Sets.newHashSet("Cleric", "Rogue", "Warrior", "Wizard");
|
||||
Set<String> cTypes = card.getType().getCreatureTypes();
|
||||
for (String t : partyTypes) {
|
||||
if (cTypes.contains(t)) {
|
||||
isParty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isParty;
|
||||
} else if (property.startsWith("sharesCreatureTypeWith")) {
|
||||
if (property.equals("sharesCreatureTypeWith")) {
|
||||
if (!card.sharesCreatureTypeWith(source)) {
|
||||
|
||||
Reference in New Issue
Block a user