Guava migration - Add common helper predicates

This commit is contained in:
Jetz
2024-09-06 09:24:32 -04:00
parent 2d233f8ad5
commit 0bf04c2fc8
23 changed files with 62 additions and 54 deletions

View File

@@ -404,7 +404,7 @@ public class AiController {
private CardCollection filterLandsToPlay(CardCollection landList) { private CardCollection filterLandsToPlay(CardCollection landList) {
final CardCollectionView hand = player.getCardsIn(ZoneType.Hand); final CardCollectionView hand = player.getCardsIn(ZoneType.Hand);
CardCollection nonLandList = CardLists.filter(hand, Presets.LANDS.negate()); CardCollection nonLandList = CardLists.filter(hand, Presets.NON_LANDS);
if (landList.size() == 1 && nonLandList.size() < 3) { if (landList.size() == 1 && nonLandList.size() < 3) {
CardCollectionView cardsInPlay = player.getCardsIn(ZoneType.Battlefield); CardCollectionView cardsInPlay = player.getCardsIn(ZoneType.Battlefield);
CardCollection landsInPlay = CardLists.filter(cardsInPlay, Presets.LANDS); CardCollection landsInPlay = CardLists.filter(cardsInPlay, Presets.LANDS);
@@ -469,7 +469,7 @@ public class AiController {
return null; return null;
} }
CardCollection nonLandsInHand = CardLists.filter(player.getCardsIn(ZoneType.Hand), Presets.LANDS.negate()); CardCollection nonLandsInHand = CardLists.filter(player.getCardsIn(ZoneType.Hand), Presets.NON_LANDS);
// Some considerations for Momir/MoJhoSto // Some considerations for Momir/MoJhoSto
boolean hasMomir = player.isCardInCommand("Momir Vig, Simic Visionary Avatar"); boolean hasMomir = player.isCardInCommand("Momir Vig, Simic Visionary Avatar");
@@ -598,8 +598,8 @@ public class AiController {
} }
// pick dual lands if available // pick dual lands if available
if (Iterables.any(landList, Presets.BASIC_LANDS.negate())) { if (Iterables.any(landList, Presets.NONBASIC_LANDS)) {
landList = CardLists.filter(landList, Presets.BASIC_LANDS.negate()); landList = CardLists.filter(landList, Presets.NONBASIC_LANDS);
} }
} }
return ComputerUtilCard.getBestLandToPlayAI(landList); return ComputerUtilCard.getBestLandToPlayAI(landList);
@@ -1397,11 +1397,11 @@ public class AiController {
return false; return false;
} }
CardCollection inHand = CardLists.filter(player.getCardsIn(ZoneType.Hand), Presets.LANDS.negate()); CardCollection inHand = CardLists.filter(player.getCardsIn(ZoneType.Hand), Presets.NON_LANDS);
CardCollectionView otb = player.getCardsIn(ZoneType.Battlefield); CardCollectionView otb = player.getCardsIn(ZoneType.Battlefield);
if (getBooleanProperty(AiProps.HOLD_LAND_DROP_ONLY_IF_HAVE_OTHER_PERMS)) { if (getBooleanProperty(AiProps.HOLD_LAND_DROP_ONLY_IF_HAVE_OTHER_PERMS)) {
if (!Iterables.any(otb, Presets.LANDS.negate())) { if (!Iterables.any(otb, Presets.NON_LANDS)) {
return false; return false;
} }
} }

View File

@@ -2218,7 +2218,7 @@ public class ComputerUtil {
} }
CardCollectionView library = ai.getCardsIn(ZoneType.Library); CardCollectionView library = ai.getCardsIn(ZoneType.Library);
int landsInDeck = CardLists.count(library, CardPredicates.isType("Land")); int landsInDeck = CardLists.count(library, Presets.LANDS);
// no land deck, can't do anything better // no land deck, can't do anything better
if (landsInDeck == 0) { if (landsInDeck == 0) {

View File

@@ -206,7 +206,7 @@ public class ComputerUtilCard {
} }
// prefer to target non basic lands // prefer to target non basic lands
final List<Card> nbLand = CardLists.filter(land, CardPredicates.Presets.BASIC_LANDS.negate()); final List<Card> nbLand = CardLists.filter(land, CardPredicates.Presets.NONBASIC_LANDS);
if (!nbLand.isEmpty()) { if (!nbLand.isEmpty()) {
// TODO - Improve ranking various non-basic lands depending on context // TODO - Improve ranking various non-basic lands depending on context
@@ -521,8 +521,7 @@ public class ComputerUtilCard {
public static final Card getCheapestSpellAI(final Iterable<Card> list) { public static final Card getCheapestSpellAI(final Iterable<Card> list) {
if (!Iterables.isEmpty(list)) { if (!Iterables.isEmpty(list)) {
CardCollection cc = CardLists.filter(list, CardCollection cc = CardLists.filter(list, CardPredicates.Presets.INSTANTS_AND_SORCERIES);
CardPredicates.isType("Instant").or(CardPredicates.isType("Sorcery")));
if (cc.isEmpty()) { if (cc.isEmpty()) {
return null; return null;

View File

@@ -1436,7 +1436,7 @@ public class PlayerControllerAi extends PlayerController {
if (consp.getState(CardStateName.Original).hasIntrinsicKeyword("Hidden agenda")) { if (consp.getState(CardStateName.Original).hasIntrinsicKeyword("Hidden agenda")) {
String chosenName = consp.getNamedCard(); String chosenName = consp.getNamedCard();
if (!chosenName.isEmpty()) { if (!chosenName.isEmpty()) {
aiLibrary = CardLists.filter(aiLibrary, CardPredicates.nameEquals(chosenName).negate()); aiLibrary = CardLists.filter(aiLibrary, CardPredicates.nameNotEquals(chosenName));
} }
} }
} }
@@ -1469,7 +1469,7 @@ public class PlayerControllerAi extends PlayerController {
} }
} else { } else {
CardCollectionView list = CardLists.filterControlledBy(getGame().getCardsInGame(), player.getOpponents()); CardCollectionView list = CardLists.filterControlledBy(getGame().getCardsInGame(), player.getOpponents());
list = CardLists.filter(list, Presets.LANDS.negate()); list = CardLists.filter(list, Presets.NON_LANDS);
if (!list.isEmpty()) { if (!list.isEmpty()) {
return list.get(0).getName(); return list.get(0).getName();
} }

View File

@@ -125,7 +125,7 @@ public class SpecialCardAi {
int numManaSrcs = manaSources.size(); int numManaSrcs = manaSources.size();
CardCollection allCards = CardLists.filter(ai.getAllCards(), Arrays.asList(CardPredicates.Presets.NON_TOKEN, CardCollection allCards = CardLists.filter(ai.getAllCards(), Arrays.asList(CardPredicates.Presets.NON_TOKEN,
CardPredicates.Presets.LANDS.negate(), CardPredicates.isOwner(ai))); CardPredicates.Presets.NON_LANDS, CardPredicates.isOwner(ai)));
int numHighCMC = CardLists.count(allCards, CardPredicates.greaterCMC(5)); int numHighCMC = CardLists.count(allCards, CardPredicates.greaterCMC(5));
int numLowCMC = CardLists.count(allCards, CardPredicates.lessCMC(3)); int numLowCMC = CardLists.count(allCards, CardPredicates.lessCMC(3));
@@ -156,7 +156,7 @@ public class SpecialCardAi {
int libsize = ai.getCardsIn(ZoneType.Library).size(); int libsize = ai.getCardsIn(ZoneType.Library).size();
final CardCollection hand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), final CardCollection hand = CardLists.filter(ai.getCardsIn(ZoneType.Hand),
CardPredicates.isType("Instant").or(CardPredicates.isType("Sorcery"))); CardPredicates.Presets.INSTANTS_AND_SORCERIES);
if (!hand.isEmpty()) { if (!hand.isEmpty()) {
// has spell that can be cast in hand with put ability // has spell that can be cast in hand with put ability
if (Iterables.any(hand, CardPredicates.hasCMC(counterNum + 1))) { if (Iterables.any(hand, CardPredicates.hasCMC(counterNum + 1))) {
@@ -169,7 +169,7 @@ public class SpecialCardAi {
} }
} }
final CardCollection library = CardLists.filter(ai.getCardsIn(ZoneType.Library), final CardCollection library = CardLists.filter(ai.getCardsIn(ZoneType.Library),
CardPredicates.isType("Instant").or(CardPredicates.isType("Sorcery"))); CardPredicates.Presets.INSTANTS_AND_SORCERIES);
if (!library.isEmpty()) { if (!library.isEmpty()) {
// get max cmc of instant or sorceries in the libary // get max cmc of instant or sorceries in the libary
int maxCMC = 0; int maxCMC = 0;
@@ -206,7 +206,7 @@ public class SpecialCardAi {
List<Card> AiLandsOnly = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), List<Card> AiLandsOnly = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield),
CardPredicates.Presets.LANDS); CardPredicates.Presets.LANDS);
List<Card> OppPerms = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), List<Card> OppPerms = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield),
CardPredicates.Presets.CREATURES.negate()); CardPredicates.Presets.NON_CREATURES);
// TODO: improve this logic (currently the AI has difficulty evaluating non-creature permanents, // TODO: improve this logic (currently the AI has difficulty evaluating non-creature permanents,
// which it can only distinguish by their CMC, considering >CMC higher value). // which it can only distinguish by their CMC, considering >CMC higher value).
@@ -331,12 +331,12 @@ public class SpecialCardAi {
public static class DeathgorgeScavenger { public static class DeathgorgeScavenger {
public static boolean consider(final Player ai, final SpellAbility sa) { public static boolean consider(final Player ai, final SpellAbility sa) {
Card worstCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.CREATURES)); Card worstCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.CREATURES));
Card worstNonCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.CREATURES.negate())); Card worstNonCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.NON_CREATURES));
if (worstCreat == null) { if (worstCreat == null) {
worstCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.CREATURES)); worstCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.CREATURES));
} }
if (worstNonCreat == null) { if (worstNonCreat == null) {
worstNonCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.CREATURES.negate())); worstNonCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.NON_CREATURES));
} }
sa.resetTargets(); sa.resetTargets();
@@ -786,7 +786,7 @@ public class SpecialCardAi {
int changeNum = AbilityUtils.calculateAmount(sa.getHostCard(), int changeNum = AbilityUtils.calculateAmount(sa.getHostCard(),
sa.getParamOrDefault("ChangeNum", "1"), sa); sa.getParamOrDefault("ChangeNum", "1"), sa);
CardCollection lib = CardLists.filter(ai.getCardsIn(ZoneType.Library), CardCollection lib = CardLists.filter(ai.getCardsIn(ZoneType.Library),
CardPredicates.nameEquals(sa.getHostCard().getName()).negate()); CardPredicates.nameNotEquals(sa.getHostCard().getName()));
lib.sort(CardLists.CmcComparatorInv); lib.sort(CardLists.CmcComparatorInv);
// Additional cards which are difficult to auto-classify but which are generally good to Intuition for // Additional cards which are difficult to auto-classify but which are generally good to Intuition for
@@ -1316,7 +1316,7 @@ public class SpecialCardAi {
return false; return false;
} }
int aiLands = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.LANDS.and(CardPredicates.Presets.BASIC_LANDS.negate())).size(); int aiLands = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.NONBASIC_LANDS).size();
boolean hasBridge = false; boolean hasBridge = false;
for (Card c : ai.getCardsIn(ZoneType.Battlefield)) { for (Card c : ai.getCardsIn(ZoneType.Battlefield)) {
@@ -1334,7 +1334,7 @@ public class SpecialCardAi {
} }
for (Player opp : ai.getOpponents()) { for (Player opp : ai.getOpponents()) {
int oppLands = CardLists.filter(opp.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.LANDS.and(CardPredicates.Presets.BASIC_LANDS.negate())).size(); int oppLands = CardLists.filter(opp.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.NONBASIC_LANDS).size();
// Always if enemy would die and we don't! // Always if enemy would die and we don't!
// TODO : predict actual damage instead of assuming it'll be 2*lands // TODO : predict actual damage instead of assuming it'll be 2*lands
// Don't if we lose, unless we lose anyway to unblocked creatures next turn // Don't if we lose, unless we lose anyway to unblocked creatures next turn

View File

@@ -1143,8 +1143,8 @@ public class AttachAi extends SpellAbilityAi {
//some auras/equipments aren't useful in multiples //some auras/equipments aren't useful in multiples
if (attachSource.hasSVar("NonStackingAttachEffect")) { if (attachSource.hasSVar("NonStackingAttachEffect")) {
prefList = CardLists.filter(prefList, CardPredicates.isEquippedBy(attachSource.getName()) prefList = CardLists.filter(prefList, CardPredicates.isEquippedBy(attachSource.getName())
.or(CardPredicates.isEnchantedBy(attachSource.getName()) .or(CardPredicates.isEnchantedBy(attachSource.getName())).negate()
).negate()); );
} }
// Don't pump cards that will die. // Don't pump cards that will die.

View File

@@ -614,8 +614,8 @@ public class ChangeZoneAi extends SpellAbilityAi {
} }
// pick dual lands if available // pick dual lands if available
if (Iterables.any(result, Presets.BASIC_LANDS.negate())) { if (Iterables.any(result, Presets.NONBASIC_LANDS)) {
result = CardLists.filter(result, Presets.BASIC_LANDS.negate()); result = CardLists.filter(result, Presets.NONBASIC_LANDS);
} }
return result.get(0); return result.get(0);
@@ -906,8 +906,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
} }
if (source.isInZone(ZoneType.Hand)) { if (source.isInZone(ZoneType.Hand)) {
Predicate<Card> nameEquals = CardPredicates.nameEquals(source.getName()); list = CardLists.filter(list, CardPredicates.nameNotEquals(source.getName())); // Don't get the same card back.
list = CardLists.filter(list, nameEquals.negate()); // Don't get the same card back.
} }
if (sa.isSpell()) { if (sa.isSpell()) {
list.remove(source); // spells can't target their own source, because it's actually in the stack zone list.remove(source); // spells can't target their own source, because it's actually in the stack zone
@@ -1014,7 +1013,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
boolean saheeliFelidarCombo = ComputerUtilAbility.getAbilitySourceName(sa).equals("Felidar Guardian") boolean saheeliFelidarCombo = ComputerUtilAbility.getAbilitySourceName(sa).equals("Felidar Guardian")
&& tobounce.getName().equals("Saheeli Rai") && tobounce.getName().equals("Saheeli Rai")
&& CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Felidar Guardian")).size() < && CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Felidar Guardian")).size() <
CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.isType("Creature")).size() + ai.getOpponentsGreatestLifeTotal() + 10; CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), Presets.CREATURES).size() + ai.getOpponentsGreatestLifeTotal() + 10;
// remember that the card was bounced already unless it's a special combo case // remember that the card was bounced already unless it's a special combo case
if (!saheeliFelidarCombo) { if (!saheeliFelidarCombo) {
@@ -1630,8 +1629,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
} }
} else { } else {
// Don't fetch another tutor with the same name // Don't fetch another tutor with the same name
Predicate<Card> nameEquals = CardPredicates.nameEquals(ComputerUtilAbility.getAbilitySourceName(sa)); CardCollection sameNamed = CardLists.filter(fetchList, CardPredicates.nameNotEquals(ComputerUtilAbility.getAbilitySourceName(sa)));
CardCollection sameNamed = CardLists.filter(fetchList, nameEquals.negate());
if (origin.contains(ZoneType.Library) && !sameNamed.isEmpty()) { if (origin.contains(ZoneType.Library) && !sameNamed.isEmpty()) {
fetchList = sameNamed; fetchList = sameNamed;
} }
@@ -1963,7 +1961,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
} }
if (logic.contains("NonLand")) { if (logic.contains("NonLand")) {
scanList = CardLists.filter(scanList, Presets.LANDS.negate()); scanList = CardLists.filter(scanList, Presets.NON_LANDS);
} }
if (logic.contains("NonExiled")) { if (logic.contains("NonExiled")) {

View File

@@ -270,7 +270,7 @@ public class ChooseCardAi extends SpellAbilityAi {
} else if (logic.equals("Phylactery")) { } else if (logic.equals("Phylactery")) {
CardCollection aiArtifacts = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), Presets.ARTIFACTS); CardCollection aiArtifacts = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), Presets.ARTIFACTS);
CardCollection indestructibles = CardLists.filter(aiArtifacts, CardPredicates.hasKeyword(Keyword.INDESTRUCTIBLE)); CardCollection indestructibles = CardLists.filter(aiArtifacts, CardPredicates.hasKeyword(Keyword.INDESTRUCTIBLE));
CardCollection nonCreatures = CardLists.filter(aiArtifacts, Presets.CREATURES.negate()); CardCollection nonCreatures = CardLists.filter(aiArtifacts, Presets.NON_CREATURES);
CardCollection creatures = CardLists.filter(aiArtifacts, Presets.CREATURES); CardCollection creatures = CardLists.filter(aiArtifacts, Presets.CREATURES);
if (!indestructibles.isEmpty()) { if (!indestructibles.isEmpty()) {
// Choose the worst (smallest) indestructible artifact so that the opponent would have to waste // Choose the worst (smallest) indestructible artifact so that the opponent would have to waste

View File

@@ -136,7 +136,7 @@ public class ChooseSourceAi extends SpellAbilityAi {
List<Card> oppCreatures = CardLists.filter(options, List<Card> oppCreatures = CardLists.filter(options,
CardPredicates.Presets.CREATURES.and(CardPredicates.isOwner(aiChoser).negate())); CardPredicates.Presets.CREATURES.and(CardPredicates.isOwner(aiChoser).negate()));
List<Card> aiNonCreatures = CardLists.filter(options, List<Card> aiNonCreatures = CardLists.filter(options,
CardPredicates.Presets.CREATURES.negate() CardPredicates.Presets.NON_CREATURES
.and(CardPredicates.Presets.PERMANENTS) .and(CardPredicates.Presets.PERMANENTS)
.and(CardPredicates.isOwner(aiChoser)) .and(CardPredicates.isOwner(aiChoser))
); );

View File

@@ -1193,7 +1193,7 @@ public class CountersPutAi extends CountersAi {
private boolean doChargeToCMCLogic(Player ai, SpellAbility sa) { private boolean doChargeToCMCLogic(Player ai, SpellAbility sa) {
Card source = sa.getHostCard(); Card source = sa.getHostCard();
CardCollectionView ownLib = CardLists.filter(ai.getCardsIn(ZoneType.Library), CardPredicates.isType("Creature")); CardCollectionView ownLib = CardLists.filter(ai.getCardsIn(ZoneType.Library), CardPredicates.Presets.CREATURES);
int numCtrs = source.getCounters(CounterEnumType.CHARGE); int numCtrs = source.getCounters(CounterEnumType.CHARGE);
int maxCMC = Aggregates.max(ownLib, Card::getCMC); int maxCMC = Aggregates.max(ownLib, Card::getCMC);
int optimalCMC = 0; int optimalCMC = 0;

View File

@@ -140,10 +140,10 @@ public class PermanentAi extends SpellAbilityAi {
&& card.getState(CardStateName.Original).getManaCost() != null && card.getState(CardStateName.Original).getManaCost() != null
&& card.getState(CardStateName.Original).getManaCost().getCMC() == manaValue); && card.getState(CardStateName.Original).getManaCost().getCMC() == manaValue);
if (manaValue == 0) { if (manaValue == 0) {
aiCards = CardLists.filter(aiCards, CardPredicates.isType("Land").negate()); aiCards = CardLists.filter(aiCards, CardPredicates.Presets.NON_LANDS);
oppCards = CardLists.filter(oppCards, CardPredicates.isType("Land").negate()); oppCards = CardLists.filter(oppCards, CardPredicates.Presets.NON_LANDS);
// also filter out other Chalices in our own deck // also filter out other Chalices in our own deck
aiCards = CardLists.filter(aiCards, CardPredicates.nameEquals("Chalice of the Void").negate()); aiCards = CardLists.filter(aiCards, CardPredicates.nameNotEquals("Chalice of the Void"));
} }
if (oppCards.size() > 3 && oppCards.size() >= aiCards.size() * 2) { if (oppCards.size() > 3 && oppCards.size() >= aiCards.size() * 2) {
sa.setXManaCostPaid(manaValue); sa.setXManaCostPaid(manaValue);

View File

@@ -99,7 +99,7 @@ public class ScryAi extends SpellAbilityAi {
private boolean doBestOpportunityLogic(Player ai, SpellAbility sa, PhaseHandler ph) { private boolean doBestOpportunityLogic(Player ai, SpellAbility sa, PhaseHandler ph) {
// Check to see if there are any cards in hand that may be worth casting // Check to see if there are any cards in hand that may be worth casting
boolean hasSomethingElse = false; boolean hasSomethingElse = false;
for (Card c : CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.LANDS.negate())) { for (Card c : CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.NON_LANDS)) {
for (SpellAbility ab : c.getAllSpellAbilities()) { for (SpellAbility ab : c.getAllSpellAbilities()) {
if (ab.getPayCosts().hasManaCost() if (ab.getPayCosts().hasManaCost()
&& ComputerUtilMana.hasEnoughManaSourcesToCast(ab, ai)) { && ComputerUtilMana.hasEnoughManaSourcesToCast(ab, ai)) {

View File

@@ -400,7 +400,7 @@ public class UntapAi extends SpellAbilityAi {
} }
// Check if something is playable if we untap for an additional mana with this, then proceed // Check if something is playable if we untap for an additional mana with this, then proceed
CardCollection inHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), Presets.LANDS.negate()); CardCollection inHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), Presets.NON_LANDS);
// The AI is not very good at timing non-permanent spells this way, so filter them out // The AI is not very good at timing non-permanent spells this way, so filter them out
// (it may actually be possible to enable this for sorceries, but that'll need some canPlay shenanigans) // (it may actually be possible to enable this for sorceries, but that'll need some canPlay shenanigans)
CardCollection playable = CardLists.filter(inHand, Presets.PERMANENTS); CardCollection playable = CardLists.filter(inHand, Presets.PERMANENTS);

View File

@@ -549,9 +549,12 @@ public final class CardRulesPredicates {
/** The Constant isBasicLand. */ /** The Constant isBasicLand. */
public static final Predicate<CardRules> IS_BASIC_LAND = subject -> subject.getType().isBasicLand(); public static final Predicate<CardRules> IS_BASIC_LAND = subject -> subject.getType().isBasicLand();
public static final Predicate<CardRules> NOT_BASIC_LAND = subject -> !subject.getType().isBasicLand();
/** The Constant isBasicLandNotWastes. */ /** Matches only Plains, Island, Swamp, Mountain, or Forest. */
public static final Predicate<CardRules> IS_BASIC_LAND_NOT_WASTES = subject -> !subject.getName().equals("Wastes")&&subject.getType().isBasicLand(); public static final Predicate<CardRules> IS_BASIC_LAND_NOT_WASTES = subject -> !subject.getName().equals("Wastes")&&subject.getType().isBasicLand();
/** Matches any card except Plains, Island, Swamp, Mountain, or Forest. */
public static final Predicate<CardRules> NOT_TRUE_BASIC_LAND = subject -> !subject.getType().isBasicLand() || subject.getName().equals("Wastes");
/** The Constant isNonBasicLand. */ /** The Constant isNonBasicLand. */
public static final Predicate<CardRules> IS_NONBASIC_LAND = subject -> subject.getType().isLand() && !subject.getType().isBasicLand(); public static final Predicate<CardRules> IS_NONBASIC_LAND = subject -> subject.getType().isLand() && !subject.getType().isBasicLand();

View File

@@ -234,7 +234,7 @@ public abstract class DeckGeneratorBase {
addSome(targetSize - actualSize, tDeck.toFlatList()); addSome(targetSize - actualSize, tDeck.toFlatList());
} }
else if (actualSize > targetSize) { else if (actualSize > targetSize) {
Predicate<PaperCard> exceptBasicLand = Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard::getRules).negate(); Predicate<PaperCard> exceptBasicLand = Predicates.compose(CardRulesPredicates.Presets.NOT_BASIC_LAND, PaperCard::getRules);
for (int i = 0; i < 3 && actualSize > targetSize; i++) { for (int i = 0; i < 3 && actualSize > targetSize; i++) {
Iterable<PaperCard> matchingCards = Iterables.filter(tDeck.toFlatList(), exceptBasicLand); Iterable<PaperCard> matchingCards = Iterables.filter(tDeck.toFlatList(), exceptBasicLand);
@@ -388,7 +388,7 @@ public abstract class DeckGeneratorBase {
//filter to provide all dual lands from pool matching 2 or 3 colors from current deck //filter to provide all dual lands from pool matching 2 or 3 colors from current deck
Predicate<CardRules> dualLandFilter = CardRulesPredicates.coreType(true, CardType.CoreType.Land); Predicate<CardRules> dualLandFilter = CardRulesPredicates.coreType(true, CardType.CoreType.Land);
Predicate<CardRules> exceptBasicLand = CardRulesPredicates.Presets.IS_BASIC_LAND.negate(); Predicate<CardRules> exceptBasicLand = CardRulesPredicates.Presets.NOT_BASIC_LAND;
Iterable<PaperCard> landCards = pool.getAllCards(Predicates.compose(dualLandFilter.and(exceptBasicLand).and(canPlay), PaperCard::getRules)); Iterable<PaperCard> landCards = pool.getAllCards(Predicates.compose(dualLandFilter.and(exceptBasicLand).and(canPlay), PaperCard::getRules));
Iterable<String> dualLandPatterns = Arrays.asList("Add \\{([WUBRG])\\} or \\{([WUBRG])\\}", Iterable<String> dualLandPatterns = Arrays.asList("Add \\{([WUBRG])\\} or \\{([WUBRG])\\}",

View File

@@ -29,7 +29,7 @@ public class InternalRadiationEffect extends SpellAbilityEffect {
final CardCollectionView milled = game.getAction().mill(new PlayerCollection(p), numRad, ZoneType.Graveyard, sa, moveParams); final CardCollectionView milled = game.getAction().mill(new PlayerCollection(p), numRad, ZoneType.Graveyard, sa, moveParams);
table.triggerChangesZoneAll(game, sa); table.triggerChangesZoneAll(game, sa);
int n = CardLists.count(milled, CardPredicates.Presets.LANDS.negate()); int n = CardLists.count(milled, CardPredicates.Presets.NON_LANDS);
if (StaticAbilityGainLifeRadiation.gainLifeRadiation(p)) { if (StaticAbilityGainLifeRadiation.gainLifeRadiation(p)) {
p.gainLife(n, sa.getHostCard(), sa); p.gainLife(n, sa.getHostCard(), sa);

View File

@@ -5532,6 +5532,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
public final boolean isKindred() { return getType().isKindred(); } public final boolean isKindred() { return getType().isKindred(); }
public final boolean isSorcery() { return getType().isSorcery(); } public final boolean isSorcery() { return getType().isSorcery(); }
public final boolean isInstant() { return getType().isInstant(); } public final boolean isInstant() { return getType().isInstant(); }
public final boolean isInstantOrSorcery() {return getType().isInstant() || getType().isSorcery();}
public final boolean isCreature() { return getType().isCreature(); } public final boolean isCreature() { return getType().isCreature(); }
public final boolean isArtifact() { return getType().isArtifact(); } public final boolean isArtifact() { return getType().isArtifact(); }

View File

@@ -92,6 +92,9 @@ public final class CardPredicates {
public static Predicate<Card> nameEquals(final String name) { public static Predicate<Card> nameEquals(final String name) {
return c -> c.getName().equals(name); return c -> c.getName().equals(name);
} }
public static Predicate<Card> nameNotEquals(final String name) {
return c -> !c.getName().equals(name);
}
public static Predicate<Card> sharesNameWith(final Card name) { public static Predicate<Card> sharesNameWith(final Card name) {
return c -> c.sharesNameWith(name); return c -> c.sharesNameWith(name);
@@ -320,6 +323,7 @@ public final class CardPredicates {
* a Predicate<Card> to get all creatures. * a Predicate<Card> to get all creatures.
*/ */
public static final Predicate<Card> CREATURES = Card::isCreature; public static final Predicate<Card> CREATURES = Card::isCreature;
public static final Predicate<Card> NON_CREATURES = c -> !c.isCreature();
/** /**
* a Predicate<Card> to get all enchantments. * a Predicate<Card> to get all enchantments.
@@ -366,6 +370,7 @@ public final class CardPredicates {
// the isBasicLand() check here may be sufficient... // the isBasicLand() check here may be sufficient...
return c.isLand() && c.isBasicLand(); return c.isLand() && c.isBasicLand();
}; };
public static final Predicate<Card> NONBASIC_LANDS = c -> c.isLand() && !c.isBasicLand();
/** /**
* a Predicate<Card> to get all artifacts. * a Predicate<Card> to get all artifacts.
*/ */
@@ -374,10 +379,12 @@ public final class CardPredicates {
* a Predicate<Card> to get all nonartifacts. * a Predicate<Card> to get all nonartifacts.
*/ */
public static final Predicate<Card> NON_ARTIFACTS = c -> !c.isArtifact(); public static final Predicate<Card> NON_ARTIFACTS = c -> !c.isArtifact();
public static final Predicate<Card> INSTANTS_AND_SORCERIES = Card::isInstantOrSorcery;
/** /**
* a Predicate<Card> to get all lands. * a Predicate<Card> to get all lands.
*/ */
public static final Predicate<Card> LANDS = c -> c.isLand(); public static final Predicate<Card> LANDS = Card::isLand;
public static final Predicate<Card> NON_LANDS = c -> !c.isLand();
/** /**
* a Predicate<Card> to get all mana-producing lands. * a Predicate<Card> to get all mana-producing lands.
*/ */

View File

@@ -222,11 +222,11 @@ public class Combat {
} }
public final CardCollection getDefendingPlaneswalkers() { public final CardCollection getDefendingPlaneswalkers() {
return CardLists.filter(Iterables.filter(attackableEntries, Card.class), CardPredicates.isType("Planeswalker")); return CardLists.filter(Iterables.filter(attackableEntries, Card.class), CardPredicates.Presets.PLANESWALKERS);
} }
public final CardCollection getDefendingBattles() { public final CardCollection getDefendingBattles() {
return CardLists.filter(Iterables.filter(attackableEntries, Card.class), CardPredicates.isType("Battle")); return CardLists.filter(Iterables.filter(attackableEntries, Card.class), CardPredicates.Presets.BATTLES);
} }
public final Map<Card, GameEntity> getAttackersAndDefenders() { public final Map<Card, GameEntity> getAttackersAndDefenders() {

View File

@@ -70,7 +70,7 @@ public enum CDeckgen implements ICDoc {
final Deck randomDeck = new Deck(); final Deck randomDeck = new Deck();
final Predicate<PaperCard> notBasicLand = Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard::getRules).negate(); final Predicate<PaperCard> notBasicLand = Predicates.compose(CardRulesPredicates.Presets.NOT_BASIC_LAND, PaperCard::getRules);
final Iterable<PaperCard> source = Iterables.filter(FModel.getMagicDb().getCommonCards().getUniqueCards(), notBasicLand); final Iterable<PaperCard> source = Iterables.filter(FModel.getMagicDb().getCommonCards().getUniqueCards(), notBasicLand);
randomDeck.getMain().addAllFlat(Aggregates.random(source, 15 * 5)); randomDeck.getMain().addAllFlat(Aggregates.random(source, 15 * 5));

View File

@@ -481,7 +481,7 @@ public class EnemySprite extends CharacterSprite implements Steerable<Vector2> {
if(data.rewards != null) { //Collect standard rewards. if(data.rewards != null) { //Collect standard rewards.
Deck enemyDeck = Current.latestDeck(); Deck enemyDeck = Current.latestDeck();
// By popular demand, remove basic lands from the reward pool. // By popular demand, remove basic lands from the reward pool.
CardPool deckNoBasicLands = enemyDeck.getMain().getFilteredPool(Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND.negate(), PaperCard::getRules)); CardPool deckNoBasicLands = enemyDeck.getMain().getFilteredPool(Predicates.compose(CardRulesPredicates.Presets.NOT_BASIC_LAND, PaperCard::getRules));
for (RewardData rdata : data.rewards) { for (RewardData rdata : data.rewards) {
ret.addAll(rdata.generate(false, enemyDeck == null ? null : deckNoBasicLands.toFlatList(),true )); ret.addAll(rdata.generate(false, enemyDeck == null ? null : deckNoBasicLands.toFlatList(),true ));

View File

@@ -74,7 +74,7 @@ public final class CardRelationMatrixGenerator {
true); true);
final Iterable<PaperCard> cards = Iterables.filter(format.getAllCards() final Iterable<PaperCard> cards = Iterables.filter(format.getAllCards()
, Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES.negate(), PaperCard::getRules)); , Predicates.compose(CardRulesPredicates.Presets.NOT_TRUE_BASIC_LAND, PaperCard::getRules));
List<PaperCard> cardList = Lists.newArrayList(cards); List<PaperCard> cardList = Lists.newArrayList(cards);
cardList.add(FModel.getMagicDb().getCommonCards().getCard("Wastes")); cardList.add(FModel.getMagicDb().getCommonCards().getCard("Wastes"));
Map<String, Integer> cardIntegerMap = new HashMap<>(); Map<String, Integer> cardIntegerMap = new HashMap<>();
@@ -90,7 +90,7 @@ public final class CardRelationMatrixGenerator {
for (Deck deck:decks){ for (Deck deck:decks){
if (deck.getMain().contains(card)){ if (deck.getMain().contains(card)){
for (PaperCard pairCard:Iterables.filter(deck.getMain().toFlatList(), for (PaperCard pairCard:Iterables.filter(deck.getMain().toFlatList(),
Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES.negate(), PaperCard::getRules))){ Predicates.compose(CardRulesPredicates.Presets.NOT_TRUE_BASIC_LAND, PaperCard::getRules))){
if (!pairCard.getName().equals(card.getName())){ if (!pairCard.getName().equals(card.getName())){
try { try {
int old = matrix[cardIntegerMap.get(card.getName())][cardIntegerMap.get(pairCard.getName())]; int old = matrix[cardIntegerMap.get(card.getName())][cardIntegerMap.get(pairCard.getName())];
@@ -143,7 +143,7 @@ public final class CardRelationMatrixGenerator {
//get all cards //get all cards
final Iterable<PaperCard> cards = Iterables.filter(FModel.getMagicDb().getCommonCards().getUniqueCards() final Iterable<PaperCard> cards = Iterables.filter(FModel.getMagicDb().getCommonCards().getUniqueCards()
, Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES.negate(), PaperCard::getRules)); , Predicates.compose(CardRulesPredicates.Presets.NOT_TRUE_BASIC_LAND, PaperCard::getRules));
List<PaperCard> cardList = Lists.newArrayList(cards); List<PaperCard> cardList = Lists.newArrayList(cards);
cardList.add(FModel.getMagicDb().getCommonCards().getCard("Wastes")); cardList.add(FModel.getMagicDb().getCommonCards().getCard("Wastes"));
Map<String, Integer> cardIntegerMap = new HashMap<>(); Map<String, Integer> cardIntegerMap = new HashMap<>();
@@ -200,7 +200,7 @@ public final class CardRelationMatrixGenerator {
public static void updateLegendMatrix(Deck deck, PaperCard legend, Map<String, Integer> cardIntegerMap, public static void updateLegendMatrix(Deck deck, PaperCard legend, Map<String, Integer> cardIntegerMap,
Map<String, Integer> legendIntegerMap, int[][] matrix){ Map<String, Integer> legendIntegerMap, int[][] matrix){
for (PaperCard pairCard:Iterables.filter(deck.getMain().toFlatList(), for (PaperCard pairCard:Iterables.filter(deck.getMain().toFlatList(),
Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES.negate(), PaperCard::getRules))){ Predicates.compose(CardRulesPredicates.Presets.NOT_TRUE_BASIC_LAND, PaperCard::getRules))){
if (!pairCard.getName().equals(legend.getName())){ if (!pairCard.getName().equals(legend.getName())){
try { try {
int old = matrix[legendIntegerMap.get(legend.getName())][cardIntegerMap.get(pairCard.getName())]; int old = matrix[legendIntegerMap.get(legend.getName())][cardIntegerMap.get(pairCard.getName())];

View File

@@ -291,7 +291,7 @@ public final class LDAModelGenetrator {
//get all cards //get all cards
final Iterable<PaperCard> cards = Iterables.filter(FModel.getMagicDb().getCommonCards().getUniqueCards() final Iterable<PaperCard> cards = Iterables.filter(FModel.getMagicDb().getCommonCards().getUniqueCards()
, Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES.negate(), PaperCard::getRules)); , Predicates.compose(CardRulesPredicates.Presets.NOT_TRUE_BASIC_LAND, PaperCard::getRules));
List<PaperCard> cardList = Lists.newArrayList(cards); List<PaperCard> cardList = Lists.newArrayList(cards);
cardList.add(FModel.getMagicDb().getCommonCards().getCard("Wastes")); cardList.add(FModel.getMagicDb().getCommonCards().getCard("Wastes"));
Map<String, Integer> cardIntegerMap = new HashMap<>(); Map<String, Integer> cardIntegerMap = new HashMap<>();
@@ -350,7 +350,7 @@ public final class LDAModelGenetrator {
public static void updateLegendMatrix(Deck deck, PaperCard legend, Map<String, Integer> cardIntegerMap, public static void updateLegendMatrix(Deck deck, PaperCard legend, Map<String, Integer> cardIntegerMap,
Map<String, Integer> legendIntegerMap, int[][] matrix){ Map<String, Integer> legendIntegerMap, int[][] matrix){
for (PaperCard pairCard:Iterables.filter(deck.getMain().toFlatList(), for (PaperCard pairCard:Iterables.filter(deck.getMain().toFlatList(),
Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES.negate(), PaperCard::getRules))){ Predicates.compose(CardRulesPredicates.Presets.NOT_TRUE_BASIC_LAND, PaperCard::getRules))){
if (!pairCard.getName().equals(legend.getName())){ if (!pairCard.getName().equals(legend.getName())){
try { try {
int old = matrix[legendIntegerMap.get(legend.getName())][cardIntegerMap.get(pairCard.getName())]; int old = matrix[legendIntegerMap.get(legend.getName())][cardIntegerMap.get(pairCard.getName())];