mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-14 09:48:02 +00:00
Guava migration - Explode Predicate "Presets" subclasses
This commit is contained in:
@@ -611,9 +611,9 @@ public class AiAttackController {
|
|||||||
// TODO: the AI should ideally predict how many times it can activate
|
// TODO: the AI should ideally predict how many times it can activate
|
||||||
// for now, unless the opponent is tapped out, break at this point
|
// for now, unless the opponent is tapped out, break at this point
|
||||||
// and do not predict the blocker limit (which is safer)
|
// and do not predict the blocker limit (which is safer)
|
||||||
if (Iterables.any(defendingOpponent.getLandsInPlay(), CardPredicates.Presets.UNTAPPED)) {
|
if (Iterables.any(defendingOpponent.getLandsInPlay(), CardPredicates.UNTAPPED)) {
|
||||||
maxBlockersAfterCrew += CardLists.count(CardLists.getNotType(defendingOpponent.getCardsIn(ZoneType.Battlefield), "Creature"),
|
maxBlockersAfterCrew += CardLists.count(CardLists.getNotType(defendingOpponent.getCardsIn(ZoneType.Battlefield), "Creature"),
|
||||||
CardPredicates.isType("Vehicle").and(CardPredicates.Presets.UNTAPPED));
|
CardPredicates.isType("Vehicle").and(CardPredicates.UNTAPPED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1343,7 +1343,7 @@ public class AiBlockController {
|
|||||||
boolean creatureParityOrAllowedDiff = aiCreatureCount
|
boolean creatureParityOrAllowedDiff = aiCreatureCount
|
||||||
+ (randomTradeIfBehindOnBoard ? maxCreatDiff : 0) >= oppCreatureCount;
|
+ (randomTradeIfBehindOnBoard ? maxCreatDiff : 0) >= oppCreatureCount;
|
||||||
boolean wantToTradeWithCreatInHand = !checkingOther && randomTradeIfCreatInHand
|
boolean wantToTradeWithCreatInHand = !checkingOther && randomTradeIfCreatInHand
|
||||||
&& ai.getZone(ZoneType.Hand).contains(CardPredicates.Presets.CREATURES)
|
&& ai.getZone(ZoneType.Hand).contains(CardPredicates.CREATURES)
|
||||||
&& aiCreatureCount + maxCreatDiffWithRepl >= oppCreatureCount;
|
&& aiCreatureCount + maxCreatDiffWithRepl >= oppCreatureCount;
|
||||||
boolean wantToSavePlaneswalker = MyRandom.percentTrue(chanceToSavePW)
|
boolean wantToSavePlaneswalker = MyRandom.percentTrue(chanceToSavePW)
|
||||||
&& combat.getDefenderByAttacker(attacker) instanceof Card
|
&& combat.getDefenderByAttacker(attacker) instanceof Card
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import forge.game.ability.AbilityUtils;
|
|||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.ability.SpellApiBased;
|
import forge.game.ability.SpellApiBased;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.combat.CombatUtil;
|
import forge.game.combat.CombatUtil;
|
||||||
import forge.game.cost.*;
|
import forge.game.cost.*;
|
||||||
@@ -404,10 +403,10 @@ 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.NON_LANDS);
|
CardCollection nonLandList = CardLists.filter(hand, CardPredicates.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, CardPredicates.LANDS);
|
||||||
CardCollection allCards = new CardCollection(player.getCardsIn(ZoneType.Graveyard));
|
CardCollection allCards = new CardCollection(player.getCardsIn(ZoneType.Graveyard));
|
||||||
allCards.addAll(player.getCardsIn(ZoneType.Command));
|
allCards.addAll(player.getCardsIn(ZoneType.Command));
|
||||||
allCards.addAll(cardsInPlay);
|
allCards.addAll(cardsInPlay);
|
||||||
@@ -445,7 +444,7 @@ public class AiController {
|
|||||||
final CardCollectionView hand1 = player.getCardsIn(ZoneType.Hand);
|
final CardCollectionView hand1 = player.getCardsIn(ZoneType.Hand);
|
||||||
CardCollection lands = new CardCollection(battlefield);
|
CardCollection lands = new CardCollection(battlefield);
|
||||||
lands.addAll(hand1);
|
lands.addAll(hand1);
|
||||||
lands = CardLists.filter(lands, Presets.LANDS);
|
lands = CardLists.filter(lands, CardPredicates.LANDS);
|
||||||
int maxCmcInHand = Aggregates.max(hand1, Card::getCMC);
|
int maxCmcInHand = Aggregates.max(hand1, Card::getCMC);
|
||||||
|
|
||||||
if (lands.size() >= Math.max(maxCmcInHand, 6)) {
|
if (lands.size() >= Math.max(maxCmcInHand, 6)) {
|
||||||
@@ -469,7 +468,7 @@ public class AiController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
CardCollection nonLandsInHand = CardLists.filter(player.getCardsIn(ZoneType.Hand), Presets.NON_LANDS);
|
CardCollection nonLandsInHand = CardLists.filter(player.getCardsIn(ZoneType.Hand), CardPredicates.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 +597,8 @@ public class AiController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pick dual lands if available
|
// pick dual lands if available
|
||||||
if (Iterables.any(landList, Presets.NONBASIC_LANDS)) {
|
if (Iterables.any(landList, CardPredicates.NONBASIC_LANDS)) {
|
||||||
landList = CardLists.filter(landList, Presets.NONBASIC_LANDS);
|
landList = CardLists.filter(landList, CardPredicates.NONBASIC_LANDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ComputerUtilCard.getBestLandToPlayAI(landList);
|
return ComputerUtilCard.getBestLandToPlayAI(landList);
|
||||||
@@ -1061,7 +1060,7 @@ public class AiController {
|
|||||||
if ("DiscardUncastableAndExcess".equals(sa.getParam("AILogic"))) {
|
if ("DiscardUncastableAndExcess".equals(sa.getParam("AILogic"))) {
|
||||||
CardCollection discards = new CardCollection();
|
CardCollection discards = new CardCollection();
|
||||||
final CardCollectionView inHand = player.getCardsIn(ZoneType.Hand);
|
final CardCollectionView inHand = player.getCardsIn(ZoneType.Hand);
|
||||||
final int numLandsOTB = CardLists.count(inHand, CardPredicates.Presets.LANDS);
|
final int numLandsOTB = CardLists.count(inHand, CardPredicates.LANDS);
|
||||||
int numOppInHand = 0;
|
int numOppInHand = 0;
|
||||||
for (Player p : player.getGame().getPlayers()) {
|
for (Player p : player.getGame().getPlayers()) {
|
||||||
if (p.getCardsIn(ZoneType.Hand).size() > numOppInHand) {
|
if (p.getCardsIn(ZoneType.Hand).size() > numOppInHand) {
|
||||||
@@ -1119,8 +1118,8 @@ public class AiController {
|
|||||||
if (validCards.isEmpty()) {
|
if (validCards.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final int numLandsInPlay = CardLists.count(player.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
final int numLandsInPlay = CardLists.count(player.getCardsIn(ZoneType.Battlefield), CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
final CardCollection landsInHand = CardLists.filter(validCards, CardPredicates.Presets.LANDS);
|
final CardCollection landsInHand = CardLists.filter(validCards, CardPredicates.LANDS);
|
||||||
final int numLandsInHand = landsInHand.size();
|
final int numLandsInHand = landsInHand.size();
|
||||||
|
|
||||||
// Discard a land
|
// Discard a land
|
||||||
@@ -1397,11 +1396,11 @@ public class AiController {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CardCollection inHand = CardLists.filter(player.getCardsIn(ZoneType.Hand), Presets.NON_LANDS);
|
CardCollection inHand = CardLists.filter(player.getCardsIn(ZoneType.Hand), CardPredicates.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.NON_LANDS)) {
|
if (!Iterables.any(otb, CardPredicates.NON_LANDS)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1578,7 +1577,7 @@ public class AiController {
|
|||||||
if (sa.getHostCard().hasKeyword(Keyword.STORM)
|
if (sa.getHostCard().hasKeyword(Keyword.STORM)
|
||||||
&& sa.getApi() != ApiType.Counter // AI would suck at trying to deliberately proc a Storm counterspell
|
&& sa.getApi() != ApiType.Counter // AI would suck at trying to deliberately proc a Storm counterspell
|
||||||
&& player.getZone(ZoneType.Hand).contains(
|
&& player.getZone(ZoneType.Hand).contains(
|
||||||
Presets.LANDS.or(CardPredicates.hasKeyword("Storm")).negate())) {
|
CardPredicates.LANDS.or(CardPredicates.hasKeyword("Storm")).negate())) {
|
||||||
if (game.getView().getStormCount() < this.getIntProperty(AiProps.MIN_COUNT_FOR_STORM_SPELLS)) {
|
if (game.getView().getStormCount() < this.getIntProperty(AiProps.MIN_COUNT_FOR_STORM_SPELLS)) {
|
||||||
// skip evaluating Storm unless we reached the minimum Storm count
|
// skip evaluating Storm unless we reached the minimum Storm count
|
||||||
continue;
|
continue;
|
||||||
@@ -1601,7 +1600,7 @@ public class AiController {
|
|||||||
} else if (sa.getHostCard().hasKeyword(Keyword.CASCADE)) {
|
} else if (sa.getHostCard().hasKeyword(Keyword.CASCADE)) {
|
||||||
if (isLifeInDanger) { //needs more tune up for certain conditions
|
if (isLifeInDanger) { //needs more tune up for certain conditions
|
||||||
aiPlayDecision = player.getCreaturesInPlay().size() >= 4 ? AiPlayDecision.CantPlaySa : AiPlayDecision.WillPlay;
|
aiPlayDecision = player.getCreaturesInPlay().size() >= 4 ? AiPlayDecision.CantPlaySa : AiPlayDecision.WillPlay;
|
||||||
} else if (CardLists.filter(player.getZone(ZoneType.Graveyard).getCards(), CardPredicates.Presets.CREATURES).size() > 4) {
|
} else if (CardLists.filter(player.getZone(ZoneType.Graveyard).getCards(), CardPredicates.CREATURES).size() > 4) {
|
||||||
if (player.getCreaturesInPlay().size() >= 4) // it's good minimum
|
if (player.getCreaturesInPlay().size() >= 4) // it's good minimum
|
||||||
continue;
|
continue;
|
||||||
else if (!sa.getHostCard().isPermanent() && sa.canCastTiming(player) && ComputerUtilCost.canPayCost(sa, player, sa.isTrigger()))
|
else if (!sa.getHostCard().isPermanent() && sa.canCastTiming(player) && ComputerUtilCost.canPayCost(sa, player, sa.isTrigger()))
|
||||||
@@ -1971,7 +1970,7 @@ public class AiController {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CardCollectionView viableOptions = CardLists.filter(pool, CardPredicates.isControlledByAnyOf(sa.getActivatingPlayer().getOpponents()), CardPredicates.Presets.CAN_BE_DESTROYED);
|
CardCollectionView viableOptions = CardLists.filter(pool, CardPredicates.isControlledByAnyOf(sa.getActivatingPlayer().getOpponents()), CardPredicates.CAN_BE_DESTROYED);
|
||||||
Card best = ComputerUtilCard.getBestAI(viableOptions);
|
Card best = ComputerUtilCard.getBestAI(viableOptions);
|
||||||
if (best != null) {
|
if (best != null) {
|
||||||
result.add(best);
|
result.add(best);
|
||||||
@@ -2047,7 +2046,7 @@ public class AiController {
|
|||||||
CardLists.shuffle(library);
|
CardLists.shuffle(library);
|
||||||
|
|
||||||
// remove all land, keep non-basicland in there, shuffled
|
// remove all land, keep non-basicland in there, shuffled
|
||||||
CardCollection land = CardLists.filter(library, CardPredicates.Presets.LANDS);
|
CardCollection land = CardLists.filter(library, CardPredicates.LANDS);
|
||||||
for (Card c : land) {
|
for (Card c : land) {
|
||||||
if (c.isLand()) {
|
if (c.isLand()) {
|
||||||
library.remove(c);
|
library.remove(c);
|
||||||
@@ -2097,7 +2096,7 @@ public class AiController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ("Aminatou".equals(sa.getParam("AILogic")) && game.getPlayers().size() > 2) {
|
if ("Aminatou".equals(sa.getParam("AILogic")) && game.getPlayers().size() > 2) {
|
||||||
CardCollection all = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), Presets.NONLAND_PERMANENTS);
|
CardCollection all = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.NONLAND_PERMANENTS);
|
||||||
CardCollection left = CardLists.filterControlledBy(all, game.getNextPlayerAfter(player, Direction.Left));
|
CardCollection left = CardLists.filterControlledBy(all, game.getNextPlayerAfter(player, Direction.Left));
|
||||||
CardCollection right = CardLists.filterControlledBy(all, game.getNextPlayerAfter(player, Direction.Right));
|
CardCollection right = CardLists.filterControlledBy(all, game.getNextPlayerAfter(player, Direction.Right));
|
||||||
return Aggregates.sum(left, Card::getCMC) > Aggregates.sum(right, Card::getCMC);
|
return Aggregates.sum(left, Card::getCMC) > Aggregates.sum(right, Card::getCMC);
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ import forge.game.ability.AbilityKey;
|
|||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.ability.effects.CharmEffect;
|
import forge.game.ability.effects.CharmEffect;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.combat.CombatUtil;
|
import forge.game.combat.CombatUtil;
|
||||||
import forge.game.keyword.Keyword;
|
import forge.game.keyword.Keyword;
|
||||||
@@ -528,7 +527,7 @@ public class ComputerUtil {
|
|||||||
// Discard lands
|
// Discard lands
|
||||||
final CardCollection landsInHand = CardLists.getType(typeList, "Land");
|
final CardCollection landsInHand = CardLists.getType(typeList, "Land");
|
||||||
if (!landsInHand.isEmpty()) {
|
if (!landsInHand.isEmpty()) {
|
||||||
final int numLandsInPlay = CardLists.count(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
final int numLandsInPlay = CardLists.count(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
final CardCollection nonLandsInHand = CardLists.getNotType(ai.getCardsIn(ZoneType.Hand), "Land");
|
final CardCollection nonLandsInHand = CardLists.getNotType(ai.getCardsIn(ZoneType.Hand), "Land");
|
||||||
final int highestCMC = Math.max(6, Aggregates.max(nonLandsInHand, Card::getCMC));
|
final int highestCMC = Math.max(6, Aggregates.max(nonLandsInHand, Card::getCMC));
|
||||||
if (numLandsInPlay >= highestCMC
|
if (numLandsInPlay >= highestCMC
|
||||||
@@ -769,7 +768,7 @@ public class ComputerUtil {
|
|||||||
all.removeAll(exclude);
|
all.removeAll(exclude);
|
||||||
CardCollection typeList = CardLists.getValidCards(all, type.split(";"), activate.getController(), activate, sa);
|
CardCollection typeList = CardLists.getValidCards(all, type.split(";"), activate.getController(), activate, sa);
|
||||||
|
|
||||||
typeList = CardLists.filter(typeList, Presets.CAN_TAP);
|
typeList = CardLists.filter(typeList, CardPredicates.CAN_TAP);
|
||||||
|
|
||||||
if (tap) {
|
if (tap) {
|
||||||
typeList.remove(activate);
|
typeList.remove(activate);
|
||||||
@@ -799,7 +798,7 @@ public class ComputerUtil {
|
|||||||
all.removeAll(exclude);
|
all.removeAll(exclude);
|
||||||
CardCollection typeList = CardLists.getValidCards(all, type.split(";"), activate.getController(), activate, sa);
|
CardCollection typeList = CardLists.getValidCards(all, type.split(";"), activate.getController(), activate, sa);
|
||||||
|
|
||||||
typeList = CardLists.filter(typeList, sa.isCrew() ? Presets.CAN_CREW : Presets.CAN_TAP);
|
typeList = CardLists.filter(typeList, sa.isCrew() ? CardPredicates.CAN_CREW : CardPredicates.CAN_TAP);
|
||||||
|
|
||||||
if (tap) {
|
if (tap) {
|
||||||
typeList.remove(activate);
|
typeList.remove(activate);
|
||||||
@@ -837,7 +836,7 @@ public class ComputerUtil {
|
|||||||
CardCollection typeList =
|
CardCollection typeList =
|
||||||
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), activate.getController(), activate, sa);
|
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), activate.getController(), activate, sa);
|
||||||
|
|
||||||
typeList = CardLists.filter(typeList, Presets.TAPPED);
|
typeList = CardLists.filter(typeList, CardPredicates.TAPPED);
|
||||||
|
|
||||||
if (untap) {
|
if (untap) {
|
||||||
typeList.remove(activate);
|
typeList.remove(activate);
|
||||||
@@ -1035,7 +1034,7 @@ public class ComputerUtil {
|
|||||||
c = ComputerUtilCard.getWorstCreatureAI(remaining);
|
c = ComputerUtilCard.getWorstCreatureAI(remaining);
|
||||||
}
|
}
|
||||||
else if (CardLists.getNotType(remaining, "Land").isEmpty()) {
|
else if (CardLists.getNotType(remaining, "Land").isEmpty()) {
|
||||||
c = ComputerUtilCard.getWorstLand(CardLists.filter(remaining, CardPredicates.Presets.LANDS));
|
c = ComputerUtilCard.getWorstLand(CardLists.filter(remaining, CardPredicates.LANDS));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
c = ComputerUtilCard.getWorstPermanentAI(remaining, false, false, false, false);
|
c = ComputerUtilCard.getWorstPermanentAI(remaining, false, false, false, false);
|
||||||
@@ -1344,8 +1343,8 @@ public class ComputerUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final Game game = ai.getGame();
|
final Game game = ai.getGame();
|
||||||
final CardCollection landsInPlay = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
final CardCollection landsInPlay = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
final CardCollection landsInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.LANDS);
|
final CardCollection landsInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.LANDS);
|
||||||
final CardCollection nonLandsInHand = CardLists.getNotType(ai.getCardsIn(ZoneType.Hand), "Land");
|
final CardCollection nonLandsInHand = CardLists.getNotType(ai.getCardsIn(ZoneType.Hand), "Land");
|
||||||
final int highestCMC = Math.max(6, Aggregates.max(nonLandsInHand, Card::getCMC));
|
final int highestCMC = Math.max(6, Aggregates.max(nonLandsInHand, Card::getCMC));
|
||||||
final int discardCMC = discard.getCMC();
|
final int discardCMC = discard.getCMC();
|
||||||
@@ -1664,7 +1663,7 @@ public class ComputerUtil {
|
|||||||
int damage = 0;
|
int damage = 0;
|
||||||
final CardCollection all = new CardCollection(ai.getCardsIn(ZoneType.Battlefield));
|
final CardCollection all = new CardCollection(ai.getCardsIn(ZoneType.Battlefield));
|
||||||
all.addAll(ai.getCardsActivatableInExternalZones(true));
|
all.addAll(ai.getCardsActivatableInExternalZones(true));
|
||||||
all.addAll(CardLists.filter(ai.getCardsIn(ZoneType.Hand), Presets.PERMANENTS.negate()));
|
all.addAll(CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.PERMANENTS.negate()));
|
||||||
|
|
||||||
for (final Card c : all) {
|
for (final Card c : all) {
|
||||||
if (c.getZone().getPlayer() != null && c.getZone().getPlayer() != ai && c.mayPlay(ai).isEmpty()) {
|
if (c.getZone().getPlayer() != null && c.getZone().getPlayer() != ai && c.mayPlay(ai).isEmpty()) {
|
||||||
@@ -2218,7 +2217,7 @@ public class ComputerUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CardCollectionView library = ai.getCardsIn(ZoneType.Library);
|
CardCollectionView library = ai.getCardsIn(ZoneType.Library);
|
||||||
int landsInDeck = CardLists.count(library, Presets.LANDS);
|
int landsInDeck = CardLists.count(library, CardPredicates.LANDS);
|
||||||
|
|
||||||
// no land deck, can't do anything better
|
// no land deck, can't do anything better
|
||||||
if (landsInDeck == 0) {
|
if (landsInDeck == 0) {
|
||||||
@@ -2363,14 +2362,14 @@ public class ComputerUtil {
|
|||||||
CardCollectionView cardsInHand = player.getCardsIn(ZoneType.Hand);
|
CardCollectionView cardsInHand = player.getCardsIn(ZoneType.Hand);
|
||||||
CardCollectionView cardsOTB = player.getCardsIn(ZoneType.Battlefield);
|
CardCollectionView cardsOTB = player.getCardsIn(ZoneType.Battlefield);
|
||||||
|
|
||||||
CardCollection landsOTB = CardLists.filter(cardsOTB, CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
CardCollection landsOTB = CardLists.filter(cardsOTB, CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
CardCollection thisLandOTB = CardLists.filter(cardsOTB, CardPredicates.nameEquals(c.getName()));
|
CardCollection thisLandOTB = CardLists.filter(cardsOTB, CardPredicates.nameEquals(c.getName()));
|
||||||
CardCollection landsInHand = CardLists.filter(cardsInHand, CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
CardCollection landsInHand = CardLists.filter(cardsInHand, CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
// valuable mana-producing artifacts that may be equated to a land
|
// valuable mana-producing artifacts that may be equated to a land
|
||||||
List<String> manaArts = Arrays.asList("Mox Pearl", "Mox Sapphire", "Mox Jet", "Mox Ruby", "Mox Emerald");
|
List<String> manaArts = Arrays.asList("Mox Pearl", "Mox Sapphire", "Mox Jet", "Mox Ruby", "Mox Emerald");
|
||||||
|
|
||||||
// evaluate creatures available in deck
|
// evaluate creatures available in deck
|
||||||
CardCollectionView allCreatures = CardLists.filter(allCards, CardPredicates.Presets.CREATURES, CardPredicates.isOwner(player));
|
CardCollectionView allCreatures = CardLists.filter(allCards, CardPredicates.CREATURES, CardPredicates.isOwner(player));
|
||||||
int numCards = allCreatures.size();
|
int numCards = allCreatures.size();
|
||||||
|
|
||||||
if (landsOTB.size() < maxLandsToScryLandsToTop && landsInHand.isEmpty()) {
|
if (landsOTB.size() < maxLandsToScryLandsToTop && landsInHand.isEmpty()) {
|
||||||
@@ -2399,7 +2398,7 @@ public class ComputerUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (c.isCreature()) {
|
} else if (c.isCreature()) {
|
||||||
CardCollection creaturesOTB = CardLists.filter(cardsOTB, CardPredicates.Presets.CREATURES);
|
CardCollection creaturesOTB = CardLists.filter(cardsOTB, CardPredicates.CREATURES);
|
||||||
int avgCreatureValue = numCards != 0 ? ComputerUtilCard.evaluateCreatureList(allCreatures) / numCards : 0;
|
int avgCreatureValue = numCards != 0 ? ComputerUtilCard.evaluateCreatureList(allCreatures) / numCards : 0;
|
||||||
int maxControlledCMC = Aggregates.max(creaturesOTB, Card::getCMC);
|
int maxControlledCMC = Aggregates.max(creaturesOTB, Card::getCMC);
|
||||||
|
|
||||||
@@ -2490,7 +2489,7 @@ public class ComputerUtil {
|
|||||||
double amount = 0;
|
double amount = 0;
|
||||||
for (String type : CardType.getAllCardTypes()) {
|
for (String type : CardType.getAllCardTypes()) {
|
||||||
if (!invalidTypes.contains(type)) {
|
if (!invalidTypes.contains(type)) {
|
||||||
CardCollection list = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.isType(type), Presets.TAPPED);
|
CardCollection list = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.isType(type), CardPredicates.TAPPED);
|
||||||
double i = type.equals("Creature") ? list.size() * 1.5 : list.size();
|
double i = type.equals("Creature") ? list.size() * 1.5 : list.size();
|
||||||
if (i > amount) {
|
if (i > amount) {
|
||||||
amount = i;
|
amount = i;
|
||||||
@@ -2801,7 +2800,7 @@ public class ComputerUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// has cards with SacMe or Token
|
// has cards with SacMe or Token
|
||||||
if (CardLists.count(aiCreatures, CardPredicates.hasSVar("SacMe").or(Presets.TOKEN)) >= numDeath) {
|
if (CardLists.count(aiCreatures, CardPredicates.hasSVar("SacMe").or(CardPredicates.TOKEN)) >= numDeath) {
|
||||||
return "Death";
|
return "Death";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public class ComputerUtilCard {
|
|||||||
* @return a {@link forge.game.card.Card} object.
|
* @return a {@link forge.game.card.Card} object.
|
||||||
*/
|
*/
|
||||||
public static Card getBestArtifactAI(final List<Card> list) {
|
public static Card getBestArtifactAI(final List<Card> list) {
|
||||||
List<Card> all = CardLists.filter(list, CardPredicates.Presets.ARTIFACTS);
|
List<Card> all = CardLists.filter(list, CardPredicates.ARTIFACTS);
|
||||||
if (all.size() == 0) {
|
if (all.size() == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ public class ComputerUtilCard {
|
|||||||
* @return best Planeswalker
|
* @return best Planeswalker
|
||||||
*/
|
*/
|
||||||
public static Card getBestPlaneswalkerAI(final List<Card> list) {
|
public static Card getBestPlaneswalkerAI(final List<Card> list) {
|
||||||
List<Card> all = CardLists.filter(list, CardPredicates.Presets.PLANESWALKERS);
|
List<Card> all = CardLists.filter(list, CardPredicates.PLANESWALKERS);
|
||||||
if (all.isEmpty()) {
|
if (all.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -111,7 +111,7 @@ public class ComputerUtilCard {
|
|||||||
* @return best Planeswalker
|
* @return best Planeswalker
|
||||||
*/
|
*/
|
||||||
public static Card getWorstPlaneswalkerAI(final List<Card> list) {
|
public static Card getWorstPlaneswalkerAI(final List<Card> list) {
|
||||||
List<Card> all = CardLists.filter(list, CardPredicates.Presets.PLANESWALKERS);
|
List<Card> all = CardLists.filter(list, CardPredicates.PLANESWALKERS);
|
||||||
if (all.isEmpty()) {
|
if (all.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -182,7 +182,7 @@ public class ComputerUtilCard {
|
|||||||
* @return a {@link forge.game.card.Card} object.
|
* @return a {@link forge.game.card.Card} object.
|
||||||
*/
|
*/
|
||||||
public static Card getBestEnchantmentAI(final List<Card> list, final SpellAbility spell, final boolean targeted) {
|
public static Card getBestEnchantmentAI(final List<Card> list, final SpellAbility spell, final boolean targeted) {
|
||||||
List<Card> all = CardLists.filter(list, CardPredicates.Presets.ENCHANTMENTS);
|
List<Card> all = CardLists.filter(list, CardPredicates.ENCHANTMENTS);
|
||||||
if (targeted) {
|
if (targeted) {
|
||||||
all = CardLists.filter(all, c -> c.canBeTargetedBy(spell));
|
all = CardLists.filter(all, c -> c.canBeTargetedBy(spell));
|
||||||
}
|
}
|
||||||
@@ -200,13 +200,13 @@ public class ComputerUtilCard {
|
|||||||
* @return a {@link forge.game.card.Card} object.
|
* @return a {@link forge.game.card.Card} object.
|
||||||
*/
|
*/
|
||||||
public static Card getBestLandAI(final Iterable<Card> list) {
|
public static Card getBestLandAI(final Iterable<Card> list) {
|
||||||
final List<Card> land = CardLists.filter(list, CardPredicates.Presets.LANDS);
|
final List<Card> land = CardLists.filter(list, CardPredicates.LANDS);
|
||||||
if (land.isEmpty()) {
|
if (land.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prefer to target non basic lands
|
// prefer to target non basic lands
|
||||||
final List<Card> nbLand = CardLists.filter(land, CardPredicates.Presets.NONBASIC_LANDS);
|
final List<Card> nbLand = CardLists.filter(land, CardPredicates.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
|
||||||
@@ -245,12 +245,12 @@ public class ComputerUtilCard {
|
|||||||
}
|
}
|
||||||
if (iminBL == Integer.MAX_VALUE) {
|
if (iminBL == Integer.MAX_VALUE) {
|
||||||
// All basic lands have no basic land type. Just return something
|
// All basic lands have no basic land type. Just return something
|
||||||
return Iterables.find(land, CardPredicates.Presets.UNTAPPED, land.get(0));
|
return Iterables.find(land, CardPredicates.UNTAPPED, land.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<Card> bLand = CardLists.getType(land, sminBL);
|
final List<Card> bLand = CardLists.getType(land, sminBL);
|
||||||
|
|
||||||
for (Card ut : Iterables.filter(bLand, CardPredicates.Presets.UNTAPPED)) {
|
for (Card ut : Iterables.filter(bLand, CardPredicates.UNTAPPED)) {
|
||||||
return ut;
|
return ut;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,10 +357,10 @@ public class ComputerUtilCard {
|
|||||||
*/
|
*/
|
||||||
public static Card getBestAI(final Iterable<Card> list) {
|
public static Card getBestAI(final Iterable<Card> list) {
|
||||||
// Get Best will filter by appropriate getBest list if ALL of the list is of that type
|
// Get Best will filter by appropriate getBest list if ALL of the list is of that type
|
||||||
if (Iterables.all(list, CardPredicates.Presets.CREATURES)) {
|
if (Iterables.all(list, CardPredicates.CREATURES)) {
|
||||||
return getBestCreatureAI(list);
|
return getBestCreatureAI(list);
|
||||||
}
|
}
|
||||||
if (Iterables.all(list, CardPredicates.Presets.LANDS)) {
|
if (Iterables.all(list, CardPredicates.LANDS)) {
|
||||||
return getBestLandAI(list);
|
return getBestLandAI(list);
|
||||||
}
|
}
|
||||||
// TODO - Once we get an EvaluatePermanent this should call getBestPermanent()
|
// TODO - Once we get an EvaluatePermanent this should call getBestPermanent()
|
||||||
@@ -377,7 +377,7 @@ public class ComputerUtilCard {
|
|||||||
if (Iterables.size(list) == 1) {
|
if (Iterables.size(list) == 1) {
|
||||||
return Iterables.get(list, 0);
|
return Iterables.get(list, 0);
|
||||||
}
|
}
|
||||||
return Aggregates.itemWithMax(Iterables.filter(list, CardPredicates.Presets.CREATURES), ComputerUtilCard.creatureEvaluator);
|
return Aggregates.itemWithMax(Iterables.filter(list, CardPredicates.CREATURES), ComputerUtilCard.creatureEvaluator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -390,7 +390,7 @@ public class ComputerUtilCard {
|
|||||||
if (Iterables.size(list) == 1) {
|
if (Iterables.size(list) == 1) {
|
||||||
return Iterables.get(list, 0);
|
return Iterables.get(list, 0);
|
||||||
}
|
}
|
||||||
return Aggregates.itemWithMax(Iterables.filter(list, CardPredicates.Presets.LANDS), ComputerUtilCard.landEvaluator);
|
return Aggregates.itemWithMax(Iterables.filter(list, CardPredicates.LANDS), ComputerUtilCard.landEvaluator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -405,7 +405,7 @@ public class ComputerUtilCard {
|
|||||||
if (Iterables.size(list) == 1) {
|
if (Iterables.size(list) == 1) {
|
||||||
return Iterables.get(list, 0);
|
return Iterables.get(list, 0);
|
||||||
}
|
}
|
||||||
return Aggregates.itemWithMin(Iterables.filter(list, CardPredicates.Presets.CREATURES), ComputerUtilCard.creatureEvaluator);
|
return Aggregates.itemWithMin(Iterables.filter(list, CardPredicates.CREATURES), ComputerUtilCard.creatureEvaluator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This selection rates tokens higher
|
// This selection rates tokens higher
|
||||||
@@ -426,7 +426,7 @@ public class ComputerUtilCard {
|
|||||||
Card biggest = null;
|
Card biggest = null;
|
||||||
int biggestvalue = -1;
|
int biggestvalue = -1;
|
||||||
|
|
||||||
for (Card card : CardLists.filter(list, CardPredicates.Presets.CREATURES)) {
|
for (Card card : CardLists.filter(list, CardPredicates.CREATURES)) {
|
||||||
int newvalue = evaluateCreature(card);
|
int newvalue = evaluateCreature(card);
|
||||||
newvalue += card.isToken() ? tokenBonus : 0; // raise the value of tokens
|
newvalue += card.isToken() ? tokenBonus : 0; // raise the value of tokens
|
||||||
|
|
||||||
@@ -479,40 +479,40 @@ public class ComputerUtilCard {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean hasEnchantmants = Iterables.any(list, CardPredicates.Presets.ENCHANTMENTS);
|
final boolean hasEnchantmants = Iterables.any(list, CardPredicates.ENCHANTMENTS);
|
||||||
if (biasEnch && hasEnchantmants) {
|
if (biasEnch && hasEnchantmants) {
|
||||||
return getCheapestPermanentAI(CardLists.filter(list, CardPredicates.Presets.ENCHANTMENTS), null, false);
|
return getCheapestPermanentAI(CardLists.filter(list, CardPredicates.ENCHANTMENTS), null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean hasArtifacts = Iterables.any(list, CardPredicates.Presets.ARTIFACTS);
|
final boolean hasArtifacts = Iterables.any(list, CardPredicates.ARTIFACTS);
|
||||||
if (biasArt && hasArtifacts) {
|
if (biasArt && hasArtifacts) {
|
||||||
return getCheapestPermanentAI(CardLists.filter(list, CardPredicates.Presets.ARTIFACTS), null, false);
|
return getCheapestPermanentAI(CardLists.filter(list, CardPredicates.ARTIFACTS), null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (biasLand && Iterables.any(list, CardPredicates.Presets.LANDS)) {
|
if (biasLand && Iterables.any(list, CardPredicates.LANDS)) {
|
||||||
return getWorstLand(CardLists.filter(list, CardPredicates.Presets.LANDS));
|
return getWorstLand(CardLists.filter(list, CardPredicates.LANDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean hasCreatures = Iterables.any(list, CardPredicates.Presets.CREATURES);
|
final boolean hasCreatures = Iterables.any(list, CardPredicates.CREATURES);
|
||||||
if (biasCreature && hasCreatures) {
|
if (biasCreature && hasCreatures) {
|
||||||
return getWorstCreatureAI(CardLists.filter(list, CardPredicates.Presets.CREATURES));
|
return getWorstCreatureAI(CardLists.filter(list, CardPredicates.CREATURES));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Card> lands = CardLists.filter(list, CardPredicates.Presets.LANDS);
|
List<Card> lands = CardLists.filter(list, CardPredicates.LANDS);
|
||||||
if (lands.size() > 6) {
|
if (lands.size() > 6) {
|
||||||
return getWorstLand(lands);
|
return getWorstLand(lands);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasEnchantmants || hasArtifacts) {
|
if (hasEnchantmants || hasArtifacts) {
|
||||||
final List<Card> ae = CardLists.filter(list,
|
final List<Card> ae = CardLists.filter(list,
|
||||||
(CardPredicates.Presets.ARTIFACTS.or(CardPredicates.Presets.ENCHANTMENTS))
|
(CardPredicates.ARTIFACTS.or(CardPredicates.ENCHANTMENTS))
|
||||||
.and(card -> !card.hasSVar("DoNotDiscardIfAble"))
|
.and(card -> !card.hasSVar("DoNotDiscardIfAble"))
|
||||||
);
|
);
|
||||||
return getCheapestPermanentAI(ae, null, false);
|
return getCheapestPermanentAI(ae, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasCreatures) {
|
if (hasCreatures) {
|
||||||
return getWorstCreatureAI(CardLists.filter(list, CardPredicates.Presets.CREATURES));
|
return getWorstCreatureAI(CardLists.filter(list, CardPredicates.CREATURES));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Planeswalkers fall through to here, lands will fall through if there aren't very many
|
// Planeswalkers fall through to here, lands will fall through if there aren't very many
|
||||||
@@ -521,7 +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, CardPredicates.Presets.INSTANTS_AND_SORCERIES);
|
CardCollection cc = CardLists.filter(list, CardPredicates.INSTANTS_AND_SORCERIES);
|
||||||
|
|
||||||
if (cc.isEmpty()) {
|
if (cc.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
@@ -1001,7 +1001,7 @@ public class ComputerUtilCard {
|
|||||||
} else if (logic.equals("MostProminentHumanCreatures")) {
|
} else if (logic.equals("MostProminentHumanCreatures")) {
|
||||||
CardCollectionView list = opp.getCreaturesInPlay();
|
CardCollectionView list = opp.getCreaturesInPlay();
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
list = CardLists.filter(CardLists.filterControlledBy(game.getCardsInGame(), opp), CardPredicates.Presets.CREATURES);
|
list = CardLists.filter(CardLists.filterControlledBy(game.getCardsInGame(), opp), CardPredicates.CREATURES);
|
||||||
}
|
}
|
||||||
chosen.add(getMostProminentColor(list, colorChoices));
|
chosen.add(getMostProminentColor(list, colorChoices));
|
||||||
} else if (logic.equals("MostProminentComputerControls")) {
|
} else if (logic.equals("MostProminentComputerControls")) {
|
||||||
@@ -1943,7 +1943,7 @@ public class ComputerUtilCard {
|
|||||||
CardCollection aiCreats = ai.getCreaturesInPlay();
|
CardCollection aiCreats = ai.getCreaturesInPlay();
|
||||||
if (temporary) {
|
if (temporary) {
|
||||||
// Pump effects that add "CARDNAME can't attack" and similar things. Only do it if something is untapped.
|
// Pump effects that add "CARDNAME can't attack" and similar things. Only do it if something is untapped.
|
||||||
oppCards = CardLists.filter(oppCards, CardPredicates.Presets.UNTAPPED);
|
oppCards = CardLists.filter(oppCards, CardPredicates.UNTAPPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
CardCollection priorityCards = new CardCollection();
|
CardCollection priorityCards = new CardCollection();
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import forge.game.Game;
|
|||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.combat.CombatUtil;
|
import forge.game.combat.CombatUtil;
|
||||||
import forge.game.cost.*;
|
import forge.game.cost.*;
|
||||||
@@ -745,7 +744,7 @@ public class ComputerUtilCost {
|
|||||||
|
|
||||||
// Special Card logic, this one try to median its power with the number of artifacts
|
// Special Card logic, this one try to median its power with the number of artifacts
|
||||||
if ("Marionette Master".equals(source.getName())) {
|
if ("Marionette Master".equals(source.getName())) {
|
||||||
CardCollection list = CardLists.filter(payer.getCardsIn(ZoneType.Battlefield), Presets.ARTIFACTS);
|
CardCollection list = CardLists.filter(payer.getCardsIn(ZoneType.Battlefield), CardPredicates.ARTIFACTS);
|
||||||
return list.size() >= copy.getNetPower();
|
return list.size() >= copy.getNetPower();
|
||||||
} else if ("Cultivator of Blades".equals(source.getName())) {
|
} else if ("Cultivator of Blades".equals(source.getName())) {
|
||||||
// Cultivator does try to median with number of Creatures
|
// Cultivator does try to median with number of Creatures
|
||||||
@@ -832,7 +831,7 @@ public class ComputerUtilCost {
|
|||||||
return getAvailableManaColors(ai, Lists.newArrayList(additionalLand));
|
return getAvailableManaColors(ai, Lists.newArrayList(additionalLand));
|
||||||
}
|
}
|
||||||
public static Set<String> getAvailableManaColors(Player ai, List<Card> additionalLands) {
|
public static Set<String> getAvailableManaColors(Player ai, List<Card> additionalLands) {
|
||||||
CardCollection cardsToConsider = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), Presets.UNTAPPED);
|
CardCollection cardsToConsider = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.UNTAPPED);
|
||||||
Set<String> colorsAvailable = Sets.newHashSet();
|
Set<String> colorsAvailable = Sets.newHashSet();
|
||||||
|
|
||||||
if (additionalLands != null) {
|
if (additionalLands != null) {
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ public class ComputerUtilMana {
|
|||||||
// For cards like Genju of the Cedars, make sure we're not attaching to the same land that will
|
// For cards like Genju of the Cedars, make sure we're not attaching to the same land that will
|
||||||
// be tapped to pay its own cost if there's another untapped land like that available
|
// be tapped to pay its own cost if there's another untapped land like that available
|
||||||
if (ma.getHostCard().equals(sa.getTargetCard())) {
|
if (ma.getHostCard().equals(sa.getTargetCard())) {
|
||||||
if (CardLists.count(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals(ma.getHostCard().getName()).and(CardPredicates.Presets.UNTAPPED)) > 1) {
|
if (CardLists.count(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals(ma.getHostCard().getName()).and(CardPredicates.UNTAPPED)) > 1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import forge.game.ability.AbilityUtils;
|
|||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.ability.effects.CharmEffect;
|
import forge.game.ability.effects.CharmEffect;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.cost.CostEnlist;
|
import forge.game.cost.CostEnlist;
|
||||||
@@ -614,7 +613,7 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int landsOTB = CardLists.count(p.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
int landsOTB = CardLists.count(p.getCardsIn(ZoneType.Battlefield), CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
|
|
||||||
if (!p.isOpponentOf(player)) {
|
if (!p.isOpponentOf(player)) {
|
||||||
if (landsOTB <= 2) {
|
if (landsOTB <= 2) {
|
||||||
@@ -758,13 +757,13 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
for (int i = 0; i < cardsToReturn; i++) {
|
for (int i = 0; i < cardsToReturn; i++) {
|
||||||
hand.removeAll(toReturn);
|
hand.removeAll(toReturn);
|
||||||
|
|
||||||
CardCollection landsInHand = CardLists.filter(hand, Presets.LANDS);
|
CardCollection landsInHand = CardLists.filter(hand, CardPredicates.LANDS);
|
||||||
int numLandsInHand = landsInHand.size() - CardLists.count(toReturn, Presets.LANDS);
|
int numLandsInHand = landsInHand.size() - CardLists.count(toReturn, CardPredicates.LANDS);
|
||||||
|
|
||||||
// If we're flooding with lands, get rid of the worst land we have
|
// If we're flooding with lands, get rid of the worst land we have
|
||||||
if (numLandsInHand > 0 && numLandsInHand > numLandsDesired) {
|
if (numLandsInHand > 0 && numLandsInHand > numLandsDesired) {
|
||||||
CardCollection producingLands = CardLists.filter(landsInHand, Presets.LANDS_PRODUCING_MANA);
|
CardCollection producingLands = CardLists.filter(landsInHand, CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
CardCollection nonProducingLands = CardLists.filter(landsInHand, Presets.LANDS_PRODUCING_MANA.negate());
|
CardCollection nonProducingLands = CardLists.filter(landsInHand, CardPredicates.LANDS_PRODUCING_MANA.negate());
|
||||||
Card worstLand = nonProducingLands.isEmpty() ? ComputerUtilCard.getWorstLand(producingLands)
|
Card worstLand = nonProducingLands.isEmpty() ? ComputerUtilCard.getWorstLand(producingLands)
|
||||||
: ComputerUtilCard.getWorstLand(nonProducingLands);
|
: ComputerUtilCard.getWorstLand(nonProducingLands);
|
||||||
toReturn.add(worstLand);
|
toReturn.add(worstLand);
|
||||||
@@ -1074,7 +1073,7 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
return Iterables.getFirst(options, null);
|
return Iterables.getFirst(options, null);
|
||||||
}
|
}
|
||||||
List<String> possible = Lists.newArrayList();
|
List<String> possible = Lists.newArrayList();
|
||||||
CardCollection oppUntappedCreatures = CardLists.filter(player.getOpponents().getCreaturesInPlay(), CardPredicates.Presets.UNTAPPED);
|
CardCollection oppUntappedCreatures = CardLists.filter(player.getOpponents().getCreaturesInPlay(), CardPredicates.UNTAPPED);
|
||||||
if (tgtCard != null) {
|
if (tgtCard != null) {
|
||||||
for (String kw : options) {
|
for (String kw : options) {
|
||||||
if (tgtCard.hasKeyword(kw)) {
|
if (tgtCard.hasKeyword(kw)) {
|
||||||
@@ -1336,7 +1335,7 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
// Probably want to see if the face up pile has anything "worth it", then potentially take face down pile
|
// Probably want to see if the face up pile has anything "worth it", then potentially take face down pile
|
||||||
return pile1.size() >= pile2.size();
|
return pile1.size() >= pile2.size();
|
||||||
} else {
|
} else {
|
||||||
boolean allCreatures = Iterables.all(Iterables.concat(pile1, pile2), CardPredicates.Presets.CREATURES);
|
boolean allCreatures = Iterables.all(Iterables.concat(pile1, pile2), CardPredicates.CREATURES);
|
||||||
int cmc1 = allCreatures ? ComputerUtilCard.evaluateCreatureList(pile1) : ComputerUtilCard.evaluatePermanentList(pile1);
|
int cmc1 = allCreatures ? ComputerUtilCard.evaluateCreatureList(pile1) : ComputerUtilCard.evaluatePermanentList(pile1);
|
||||||
int cmc2 = allCreatures ? ComputerUtilCard.evaluateCreatureList(pile2) : ComputerUtilCard.evaluatePermanentList(pile2);
|
int cmc2 = allCreatures ? ComputerUtilCard.evaluateCreatureList(pile2) : ComputerUtilCard.evaluatePermanentList(pile2);
|
||||||
|
|
||||||
@@ -1469,7 +1468,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.NON_LANDS);
|
list = CardLists.filter(list, CardPredicates.NON_LANDS);
|
||||||
if (!list.isEmpty()) {
|
if (!list.isEmpty()) {
|
||||||
return list.get(0).getName();
|
return list.get(0).getName();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,8 +124,8 @@ public class SpecialCardAi {
|
|||||||
CardCollection manaSources = ComputerUtilMana.getAvailableManaSources(ai, true);
|
CardCollection manaSources = ComputerUtilMana.getAvailableManaSources(ai, true);
|
||||||
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.NON_TOKEN,
|
||||||
CardPredicates.Presets.NON_LANDS, CardPredicates.isOwner(ai)));
|
CardPredicates.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.Presets.INSTANTS_AND_SORCERIES);
|
CardPredicates.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.Presets.INSTANTS_AND_SORCERIES);
|
CardPredicates.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;
|
||||||
@@ -204,9 +204,9 @@ public class SpecialCardAi {
|
|||||||
public static class ChainOfAcid {
|
public static class ChainOfAcid {
|
||||||
public static boolean consider(final Player ai, final SpellAbility sa) {
|
public static boolean consider(final Player ai, final SpellAbility sa) {
|
||||||
List<Card> AiLandsOnly = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield),
|
List<Card> AiLandsOnly = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield),
|
||||||
CardPredicates.Presets.LANDS);
|
CardPredicates.LANDS);
|
||||||
List<Card> OppPerms = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield),
|
List<Card> OppPerms = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield),
|
||||||
CardPredicates.Presets.NON_CREATURES);
|
CardPredicates.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).
|
||||||
@@ -330,13 +330,13 @@ public class SpecialCardAi {
|
|||||||
// Deathgorge Scavenger
|
// Deathgorge Scavenger
|
||||||
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.CREATURES));
|
||||||
Card worstNonCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.NON_CREATURES));
|
Card worstNonCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Graveyard), CardPredicates.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.CREATURES));
|
||||||
}
|
}
|
||||||
if (worstNonCreat == null) {
|
if (worstNonCreat == null) {
|
||||||
worstNonCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.NON_CREATURES));
|
worstNonCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.NON_CREATURES));
|
||||||
}
|
}
|
||||||
|
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
@@ -359,7 +359,7 @@ public class SpecialCardAi {
|
|||||||
|
|
||||||
public static boolean considerSacrificingCreature(final Player ai, final SpellAbility sa) {
|
public static boolean considerSacrificingCreature(final Player ai, final SpellAbility sa) {
|
||||||
CardCollection flyingCreatures = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield),
|
CardCollection flyingCreatures = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield),
|
||||||
CardPredicates.Presets.UNTAPPED.and(
|
CardPredicates.UNTAPPED.and(
|
||||||
CardPredicates.hasKeyword(Keyword.FLYING).or(CardPredicates.hasKeyword(Keyword.REACH))));
|
CardPredicates.hasKeyword(Keyword.FLYING).or(CardPredicates.hasKeyword(Keyword.REACH))));
|
||||||
boolean hasUsefulBlocker = false;
|
boolean hasUsefulBlocker = false;
|
||||||
|
|
||||||
@@ -402,7 +402,7 @@ public class SpecialCardAi {
|
|||||||
|
|
||||||
// select player with less lands on the field (helpful for Illusions of Grandeur and probably Pacts too)
|
// select player with less lands on the field (helpful for Illusions of Grandeur and probably Pacts too)
|
||||||
Player opp = Collections.min(Lists.newArrayList(oppTarget),
|
Player opp = Collections.min(Lists.newArrayList(oppTarget),
|
||||||
PlayerPredicates.compareByZoneSize(ZoneType.Battlefield, CardPredicates.Presets.LANDS));
|
PlayerPredicates.compareByZoneSize(ZoneType.Battlefield, CardPredicates.LANDS));
|
||||||
|
|
||||||
if (opp != null) {
|
if (opp != null) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
@@ -581,9 +581,9 @@ public class SpecialCardAi {
|
|||||||
Card bestBasic = null;
|
Card bestBasic = null;
|
||||||
Card bestBasicSelfOnly = null;
|
Card bestBasicSelfOnly = null;
|
||||||
|
|
||||||
CardCollection aiLands = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
CardCollection aiLands = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
CardCollection oppLands = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield),
|
CardCollection oppLands = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield),
|
||||||
CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
|
|
||||||
int bestCount = 0;
|
int bestCount = 0;
|
||||||
int bestSelfOnlyCount = 0;
|
int bestSelfOnlyCount = 0;
|
||||||
@@ -629,7 +629,7 @@ public class SpecialCardAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CardCollection oppList = CardLists.filter(ai.getGame().getCardsIn(ZoneType.Battlefield),
|
CardCollection oppList = CardLists.filter(ai.getGame().getCardsIn(ZoneType.Battlefield),
|
||||||
CardPredicates.Presets.CREATURES, CardPredicates.isControlledByAnyOf(ai.getOpponents()));
|
CardPredicates.CREATURES, CardPredicates.isControlledByAnyOf(ai.getOpponents()));
|
||||||
|
|
||||||
oppList = CardLists.filterPower(oppList, lowest.getNetPower() + 1);
|
oppList = CardLists.filterPower(oppList, lowest.getNetPower() + 1);
|
||||||
if (ComputerUtilCard.evaluateCreatureList(oppList) > 200) {
|
if (ComputerUtilCard.evaluateCreatureList(oppList) > 200) {
|
||||||
@@ -685,7 +685,7 @@ public class SpecialCardAi {
|
|||||||
// Goblin Polka Band
|
// Goblin Polka Band
|
||||||
public static class GoblinPolkaBand {
|
public static class GoblinPolkaBand {
|
||||||
public static boolean consider(final Player ai, final SpellAbility sa) {
|
public static boolean consider(final Player ai, final SpellAbility sa) {
|
||||||
int maxPotentialTgts = Lists.newArrayList(Iterables.filter(ai.getOpponents().getCreaturesInPlay(), CardPredicates.Presets.UNTAPPED)).size();
|
int maxPotentialTgts = Lists.newArrayList(Iterables.filter(ai.getOpponents().getCreaturesInPlay(), CardPredicates.UNTAPPED)).size();
|
||||||
int maxPotentialPayment = ComputerUtilMana.determineLeftoverMana(sa, ai, "R", false);
|
int maxPotentialPayment = ComputerUtilMana.determineLeftoverMana(sa, ai, "R", false);
|
||||||
|
|
||||||
int numTgts = Math.min(maxPotentialPayment, maxPotentialTgts);
|
int numTgts = Math.min(maxPotentialPayment, maxPotentialTgts);
|
||||||
@@ -921,7 +921,7 @@ public class SpecialCardAi {
|
|||||||
int aiBattlefieldPower = 0, aiGraveyardPower = 0;
|
int aiBattlefieldPower = 0, aiGraveyardPower = 0;
|
||||||
int threshold = 320; // approximately a 4/4 Flying creature worth of extra value
|
int threshold = 320; // approximately a 4/4 Flying creature worth of extra value
|
||||||
|
|
||||||
CardCollection aiCreaturesInGY = CardLists.filter(ai.getZone(ZoneType.Graveyard).getCards(), CardPredicates.Presets.CREATURES);
|
CardCollection aiCreaturesInGY = CardLists.filter(ai.getZone(ZoneType.Graveyard).getCards(), CardPredicates.CREATURES);
|
||||||
|
|
||||||
if (aiCreaturesInGY.isEmpty()) {
|
if (aiCreaturesInGY.isEmpty()) {
|
||||||
// nothing in graveyard, so cut short
|
// nothing in graveyard, so cut short
|
||||||
@@ -945,7 +945,7 @@ public class SpecialCardAi {
|
|||||||
for (Card c : p.getCreaturesInPlay()) {
|
for (Card c : p.getCreaturesInPlay()) {
|
||||||
playerPower += ComputerUtilCard.evaluateCreature(c);
|
playerPower += ComputerUtilCard.evaluateCreature(c);
|
||||||
}
|
}
|
||||||
for (Card c : CardLists.filter(p.getZone(ZoneType.Graveyard).getCards(), CardPredicates.Presets.CREATURES)) {
|
for (Card c : CardLists.filter(p.getZone(ZoneType.Graveyard).getCards(), CardPredicates.CREATURES)) {
|
||||||
tempGraveyardPower += ComputerUtilCard.evaluateCreature(c);
|
tempGraveyardPower += ComputerUtilCard.evaluateCreature(c);
|
||||||
}
|
}
|
||||||
if (playerPower > oppBattlefieldPower) {
|
if (playerPower > oppBattlefieldPower) {
|
||||||
@@ -997,7 +997,7 @@ public class SpecialCardAi {
|
|||||||
// Scan the fetch list for a card with at least one activated ability.
|
// Scan the fetch list for a card with at least one activated ability.
|
||||||
// TODO: can be improved to a full consider(sa, ai) logic which would scan the graveyard first and hand last
|
// TODO: can be improved to a full consider(sa, ai) logic which would scan the graveyard first and hand last
|
||||||
public static Card considerCardFromList(final CardCollection fetchList) {
|
public static Card considerCardFromList(final CardCollection fetchList) {
|
||||||
for (Card c : CardLists.filter(fetchList, CardPredicates.Presets.ARTIFACTS.or(CardPredicates.Presets.CREATURES))) {
|
for (Card c : CardLists.filter(fetchList, CardPredicates.ARTIFACTS.or(CardPredicates.CREATURES))) {
|
||||||
for (SpellAbility ab : c.getSpellAbilities()) {
|
for (SpellAbility ab : c.getSpellAbilities()) {
|
||||||
if (ab.isActivatedAbility()) {
|
if (ab.isActivatedAbility()) {
|
||||||
Player controller = c.getController();
|
Player controller = c.getController();
|
||||||
@@ -1058,7 +1058,7 @@ public class SpecialCardAi {
|
|||||||
|
|
||||||
// In MoJhoSto, prefer Jhoira sorcery ability from time to time
|
// In MoJhoSto, prefer Jhoira sorcery ability from time to time
|
||||||
if (source.getGame().getRules().hasAppliedVariant(GameType.MoJhoSto)
|
if (source.getGame().getRules().hasAppliedVariant(GameType.MoJhoSto)
|
||||||
&& CardLists.filter(ai.getLandsInPlay(), CardPredicates.Presets.UNTAPPED).size() >= 3) {
|
&& CardLists.filter(ai.getLandsInPlay(), CardPredicates.UNTAPPED).size() >= 3) {
|
||||||
AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
|
AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
|
||||||
int chanceToPrefJhoira = aic.getIntProperty(AiProps.MOJHOSTO_CHANCE_TO_PREFER_JHOIRA_OVER_MOMIR);
|
int chanceToPrefJhoira = aic.getIntProperty(AiProps.MOJHOSTO_CHANCE_TO_PREFER_JHOIRA_OVER_MOMIR);
|
||||||
int numLandsForJhoira = aic.getIntProperty(AiProps.MOJHOSTO_NUM_LANDS_TO_ACTIVATE_JHOIRA);
|
int numLandsForJhoira = aic.getIntProperty(AiProps.MOJHOSTO_NUM_LANDS_TO_ACTIVATE_JHOIRA);
|
||||||
@@ -1219,7 +1219,7 @@ public class SpecialCardAi {
|
|||||||
final CardCollectionView cards = ai.getCardsIn(Arrays.asList(ZoneType.Hand, ZoneType.Battlefield, ZoneType.Command));
|
final CardCollectionView cards = ai.getCardsIn(Arrays.asList(ZoneType.Hand, ZoneType.Battlefield, ZoneType.Command));
|
||||||
List<SpellAbility> all = ComputerUtilAbility.getSpellAbilities(cards, ai);
|
List<SpellAbility> all = ComputerUtilAbility.getSpellAbilities(cards, ai);
|
||||||
|
|
||||||
int numManaSrcs = CardLists.filter(ComputerUtilMana.getAvailableManaSources(ai, true), CardPredicates.Presets.UNTAPPED).size();
|
int numManaSrcs = CardLists.filter(ComputerUtilMana.getAvailableManaSources(ai, true), CardPredicates.UNTAPPED).size();
|
||||||
|
|
||||||
for (final SpellAbility testSa : ComputerUtilAbility.getOriginalAndAltCostAbilities(all, ai)) {
|
for (final SpellAbility testSa : ComputerUtilAbility.getOriginalAndAltCostAbilities(all, ai)) {
|
||||||
ManaCost cost = testSa.getPayCosts().getTotalMana();
|
ManaCost cost = testSa.getPayCosts().getTotalMana();
|
||||||
@@ -1316,7 +1316,7 @@ public class SpecialCardAi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int aiLands = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.NONBASIC_LANDS).size();
|
int aiLands = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.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.NONBASIC_LANDS).size();
|
int oppLands = CardLists.filter(opp.getCardsIn(ZoneType.Battlefield), CardPredicates.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
|
||||||
@@ -1402,7 +1402,7 @@ public class SpecialCardAi {
|
|||||||
public static boolean consider(final Player ai, final SpellAbility sa) {
|
public static boolean consider(final Player ai, final SpellAbility sa) {
|
||||||
CardCollection oppTargetables = CardLists.getTargetableCards(ai.getOpponents().getCreaturesInPlay(), sa);
|
CardCollection oppTargetables = CardLists.getTargetableCards(ai.getOpponents().getCreaturesInPlay(), sa);
|
||||||
CardCollection threats = CardLists.filter(oppTargetables, card -> !ComputerUtilCard.isUselessCreature(card.getController(), card));
|
CardCollection threats = CardLists.filter(oppTargetables, card -> !ComputerUtilCard.isUselessCreature(card.getController(), card));
|
||||||
CardCollection ownTgts = CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.CREATURES);
|
CardCollection ownTgts = CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.CREATURES);
|
||||||
|
|
||||||
// TODO: improve the conditions for when the AI is considered threatened (check the possibility of being attacked?)
|
// TODO: improve the conditions for when the AI is considered threatened (check the possibility of being attacked?)
|
||||||
int lifeInDanger = (((PlayerControllerAi) ai.getController()).getAi().getIntProperty(AiProps.AI_IN_DANGER_THRESHOLD));
|
int lifeInDanger = (((PlayerControllerAi) ai.getController()).getAi().getIntProperty(AiProps.AI_IN_DANGER_THRESHOLD));
|
||||||
@@ -1442,7 +1442,7 @@ public class SpecialCardAi {
|
|||||||
public static boolean consider(final Player ai, final SpellAbility sa) {
|
public static boolean consider(final Player ai, final SpellAbility sa) {
|
||||||
int loyalty = sa.getHostCard().getCounters(CounterEnumType.LOYALTY);
|
int loyalty = sa.getHostCard().getCounters(CounterEnumType.LOYALTY);
|
||||||
CardCollection creaturesToGet = CardLists.filter(ai.getCardsIn(ZoneType.Graveyard),
|
CardCollection creaturesToGet = CardLists.filter(ai.getCardsIn(ZoneType.Graveyard),
|
||||||
CardPredicates.Presets.CREATURES
|
CardPredicates.CREATURES
|
||||||
.and(CardPredicates.lessCMC(loyalty - 1))
|
.and(CardPredicates.lessCMC(loyalty - 1))
|
||||||
.and(card -> {
|
.and(card -> {
|
||||||
final Card copy = CardCopyService.getLKICopy(card);
|
final Card copy = CardCopyService.getLKICopy(card);
|
||||||
@@ -1484,9 +1484,9 @@ public class SpecialCardAi {
|
|||||||
// face down (on the battlefield or in exile). Might need some kind of an update to consider hidden information
|
// face down (on the battlefield or in exile). Might need some kind of an update to consider hidden information
|
||||||
// like that properly (probably by adding all those cards to the evaluation mix so the AI doesn't "know" which
|
// like that properly (probably by adding all those cards to the evaluation mix so the AI doesn't "know" which
|
||||||
// ones are already face down in play and which are still in the library)
|
// ones are already face down in play and which are still in the library)
|
||||||
CardCollectionView creatsInLib = CardLists.filter(ai.getCardsIn(ZoneType.Library), CardPredicates.Presets.CREATURES);
|
CardCollectionView creatsInLib = CardLists.filter(ai.getCardsIn(ZoneType.Library), CardPredicates.CREATURES);
|
||||||
CardCollectionView creatsInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.CREATURES);
|
CardCollectionView creatsInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.CREATURES);
|
||||||
CardCollectionView manaSrcsInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
CardCollectionView manaSrcsInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
|
|
||||||
if (creatsInHand.isEmpty() || creatsInLib.isEmpty()) { return null; }
|
if (creatsInHand.isEmpty() || creatsInLib.isEmpty()) { return null; }
|
||||||
|
|
||||||
@@ -1555,10 +1555,10 @@ public class SpecialCardAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Card considerCardToGet(final Player ai, final SpellAbility sa) {
|
public static Card considerCardToGet(final Player ai, final SpellAbility sa) {
|
||||||
CardCollectionView creatsInLib = CardLists.filter(ai.getCardsIn(ZoneType.Library), CardPredicates.Presets.CREATURES);
|
CardCollectionView creatsInLib = CardLists.filter(ai.getCardsIn(ZoneType.Library), CardPredicates.CREATURES);
|
||||||
if (creatsInLib.isEmpty()) { return null; }
|
if (creatsInLib.isEmpty()) { return null; }
|
||||||
|
|
||||||
CardCollectionView manaSrcsInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
CardCollectionView manaSrcsInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
int numManaSrcs = ComputerUtilMana.getAvailableManaEstimate(ai, false)
|
int numManaSrcs = ComputerUtilMana.getAvailableManaEstimate(ai, false)
|
||||||
+ Math.min(1, manaSrcsInHand.size());
|
+ Math.min(1, manaSrcsInHand.size());
|
||||||
|
|
||||||
@@ -1602,8 +1602,8 @@ public class SpecialCardAi {
|
|||||||
// The Scarab God
|
// The Scarab God
|
||||||
public static class TheScarabGod {
|
public static class TheScarabGod {
|
||||||
public static boolean consider(final Player ai, final SpellAbility sa) {
|
public static boolean consider(final Player ai, final SpellAbility sa) {
|
||||||
Card bestOppCreat = ComputerUtilCard.getBestAI(CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.CREATURES));
|
Card bestOppCreat = ComputerUtilCard.getBestAI(CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Graveyard), CardPredicates.CREATURES));
|
||||||
Card worstOwnCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.CREATURES));
|
Card worstOwnCreat = ComputerUtilCard.getWorstAI(CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.CREATURES));
|
||||||
|
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
if (bestOppCreat != null) {
|
if (bestOppCreat != null) {
|
||||||
@@ -1704,7 +1704,7 @@ public class SpecialCardAi {
|
|||||||
CardCollectionView aiGY = ai.getCardsIn(ZoneType.Graveyard);
|
CardCollectionView aiGY = ai.getCardsIn(ZoneType.Graveyard);
|
||||||
Card topGY = null;
|
Card topGY = null;
|
||||||
Card creatHand = ComputerUtilCard.getBestCreatureAI(ai.getCardsIn(ZoneType.Hand));
|
Card creatHand = ComputerUtilCard.getBestCreatureAI(ai.getCardsIn(ZoneType.Hand));
|
||||||
int numCreatsInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.CREATURES).size();
|
int numCreatsInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.CREATURES).size();
|
||||||
|
|
||||||
if (!aiGY.isEmpty()) {
|
if (!aiGY.isEmpty()) {
|
||||||
topGY = ai.getCardsIn(ZoneType.Graveyard).get(0);
|
topGY = ai.getCardsIn(ZoneType.Graveyard).get(0);
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ public class AnimateAi extends SpellAbilityAi {
|
|||||||
&& game.getPhaseHandler().getNextTurn() != ai
|
&& game.getPhaseHandler().getNextTurn() != ai
|
||||||
&& source.isPermanent();
|
&& source.isPermanent();
|
||||||
if (ph.isPlayerTurn(ai) && ai.getLife() < 6 && opponent.getLife() > 6
|
if (ph.isPlayerTurn(ai) && ai.getLife() < 6 && opponent.getLife() > 6
|
||||||
&& opponent.getZone(ZoneType.Battlefield).contains(CardPredicates.Presets.CREATURES)
|
&& opponent.getZone(ZoneType.Battlefield).contains(CardPredicates.CREATURES)
|
||||||
&& !sa.hasParam("AILogic") && !"Permanent".equals(sa.getParam("Duration")) && !activateAsPotentialBlocker) {
|
&& !sa.hasParam("AILogic") && !"Permanent".equals(sa.getParam("Duration")) && !activateAsPotentialBlocker) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -509,7 +509,7 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
if (!evenBetterList.isEmpty()) {
|
if (!evenBetterList.isEmpty()) {
|
||||||
betterList = evenBetterList;
|
betterList = evenBetterList;
|
||||||
}
|
}
|
||||||
evenBetterList = CardLists.filter(betterList, CardPredicates.Presets.UNTAPPED);
|
evenBetterList = CardLists.filter(betterList, CardPredicates.UNTAPPED);
|
||||||
if (!evenBetterList.isEmpty()) {
|
if (!evenBetterList.isEmpty()) {
|
||||||
betterList = evenBetterList;
|
betterList = evenBetterList;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ public class BalanceAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
if ("BalanceCreaturesAndLands".equals(logic)) {
|
if ("BalanceCreaturesAndLands".equals(logic)) {
|
||||||
// TODO Copied over from hardcoded Balance. We should be checking value of the lands/creatures for each opponent, not just counting
|
// TODO Copied over from hardcoded Balance. We should be checking value of the lands/creatures for each opponent, not just counting
|
||||||
diff += CardLists.filter(humPerms, CardPredicates.Presets.LANDS).size() -
|
diff += CardLists.filter(humPerms, CardPredicates.LANDS).size() -
|
||||||
CardLists.filter(compPerms, CardPredicates.Presets.LANDS).size();
|
CardLists.filter(compPerms, CardPredicates.LANDS).size();
|
||||||
diff += 1.5 * (CardLists.filter(humPerms, CardPredicates.Presets.CREATURES).size() -
|
diff += 1.5 * (CardLists.filter(humPerms, CardPredicates.CREATURES).size() -
|
||||||
CardLists.filter(compPerms, CardPredicates.Presets.CREATURES).size());
|
CardLists.filter(compPerms, CardPredicates.CREATURES).size());
|
||||||
}
|
}
|
||||||
else if ("BalancePermanents".equals(logic)) {
|
else if ("BalancePermanents".equals(logic)) {
|
||||||
// Don't cast if you have to sacrifice permanents
|
// Don't cast if you have to sacrifice permanents
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import forge.game.ability.AbilityKey;
|
|||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.cost.*;
|
import forge.game.cost.*;
|
||||||
import forge.game.keyword.Keyword;
|
import forge.game.keyword.Keyword;
|
||||||
@@ -32,7 +31,6 @@ import forge.util.MyRandom;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
public class ChangeZoneAi extends SpellAbilityAi {
|
public class ChangeZoneAi extends SpellAbilityAi {
|
||||||
/*
|
/*
|
||||||
@@ -614,8 +612,8 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pick dual lands if available
|
// pick dual lands if available
|
||||||
if (Iterables.any(result, Presets.NONBASIC_LANDS)) {
|
if (Iterables.any(result, CardPredicates.NONBASIC_LANDS)) {
|
||||||
result = CardLists.filter(result, Presets.NONBASIC_LANDS);
|
result = CardLists.filter(result, CardPredicates.NONBASIC_LANDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.get(0);
|
return result.get(0);
|
||||||
@@ -1013,7 +1011,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), Presets.CREATURES).size() + ai.getOpponentsGreatestLifeTotal() + 10;
|
CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.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) {
|
||||||
@@ -1197,7 +1195,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
} else if (destination.equals(ZoneType.Hand) || destination.equals(ZoneType.Library)) {
|
} else if (destination.equals(ZoneType.Hand) || destination.equals(ZoneType.Library)) {
|
||||||
List<Card> nonLands = CardLists.getNotType(list, "Land");
|
List<Card> nonLands = CardLists.getNotType(list, "Land");
|
||||||
// Prefer to pull a creature, generally more useful for AI.
|
// Prefer to pull a creature, generally more useful for AI.
|
||||||
choice = chooseCreature(ai, CardLists.filter(nonLands, CardPredicates.Presets.CREATURES));
|
choice = chooseCreature(ai, CardLists.filter(nonLands, CardPredicates.CREATURES));
|
||||||
if (choice == null) { // Could not find a creature.
|
if (choice == null) { // Could not find a creature.
|
||||||
if (ai.getLife() <= 5) { // Desperate?
|
if (ai.getLife() <= 5) { // Desperate?
|
||||||
// Get something AI can cast soon.
|
// Get something AI can cast soon.
|
||||||
@@ -1309,7 +1307,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
Game game = ai.getGame();
|
Game game = ai.getGame();
|
||||||
// filter out untargetables
|
// filter out untargetables
|
||||||
CardCollectionView aiPermanents = CardLists.filterControlledBy(list, ai);
|
CardCollectionView aiPermanents = CardLists.filterControlledBy(list, ai);
|
||||||
CardCollection aiPlaneswalkers = CardLists.filter(aiPermanents, Presets.PLANESWALKERS);
|
CardCollection aiPlaneswalkers = CardLists.filter(aiPermanents, CardPredicates.PLANESWALKERS);
|
||||||
|
|
||||||
// Felidar Guardian + Saheeli Rai combo support
|
// Felidar Guardian + Saheeli Rai combo support
|
||||||
if (sa.getHostCard().getName().equals("Felidar Guardian")) {
|
if (sa.getHostCard().getName().equals("Felidar Guardian")) {
|
||||||
@@ -1335,7 +1333,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
else if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
|
else if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
|
||||||
Combat combat = game.getCombat();
|
Combat combat = game.getCombat();
|
||||||
final CardCollection combatants = CardLists.filter(aiPermanents,
|
final CardCollection combatants = CardLists.filter(aiPermanents,
|
||||||
CardPredicates.Presets.CREATURES);
|
CardPredicates.CREATURES);
|
||||||
ComputerUtilCard.sortByEvaluateCreature(combatants);
|
ComputerUtilCard.sortByEvaluateCreature(combatants);
|
||||||
|
|
||||||
for (final Card c : combatants) {
|
for (final Card c : combatants) {
|
||||||
@@ -1455,7 +1453,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
} else if (destination.equals(ZoneType.Hand) || destination.equals(ZoneType.Library)) {
|
} else if (destination.equals(ZoneType.Hand) || destination.equals(ZoneType.Library)) {
|
||||||
List<Card> nonLands = CardLists.getNotType(list, "Land");
|
List<Card> nonLands = CardLists.getNotType(list, "Land");
|
||||||
// Prefer to pull a creature, generally more useful for AI.
|
// Prefer to pull a creature, generally more useful for AI.
|
||||||
choice = chooseCreature(ai, CardLists.filter(nonLands, CardPredicates.Presets.CREATURES));
|
choice = chooseCreature(ai, CardLists.filter(nonLands, CardPredicates.CREATURES));
|
||||||
if (choice == null) { // Could not find a creature.
|
if (choice == null) { // Could not find a creature.
|
||||||
if (ai.getLife() <= 5) { // Desperate?
|
if (ai.getLife() <= 5) { // Desperate?
|
||||||
// Get something AI can cast soon.
|
// Get something AI can cast soon.
|
||||||
@@ -1636,7 +1634,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
// Does AI need a land?
|
// Does AI need a land?
|
||||||
CardCollectionView hand = decider.getCardsIn(ZoneType.Hand);
|
CardCollectionView hand = decider.getCardsIn(ZoneType.Hand);
|
||||||
if (!Iterables.any(hand, Presets.LANDS) && CardLists.count(decider.getCardsIn(ZoneType.Battlefield), Presets.LANDS) < 4) {
|
if (!Iterables.any(hand, CardPredicates.LANDS) && CardLists.count(decider.getCardsIn(ZoneType.Battlefield), CardPredicates.LANDS) < 4) {
|
||||||
boolean canCastSomething = false;
|
boolean canCastSomething = false;
|
||||||
for (Card cardInHand : hand) {
|
for (Card cardInHand : hand) {
|
||||||
canCastSomething = canCastSomething || ComputerUtilMana.hasEnoughManaSourcesToCast(cardInHand.getFirstSpellAbility(), decider);
|
canCastSomething = canCastSomething || ComputerUtilMana.hasEnoughManaSourcesToCast(cardInHand.getFirstSpellAbility(), decider);
|
||||||
@@ -1646,13 +1644,13 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
if (Iterables.all(fetchList, Presets.LANDS)) {
|
if (Iterables.all(fetchList, CardPredicates.LANDS)) {
|
||||||
// we're only choosing from lands, so get the best land
|
// we're only choosing from lands, so get the best land
|
||||||
c = ComputerUtilCard.getBestLandAI(fetchList);
|
c = ComputerUtilCard.getBestLandAI(fetchList);
|
||||||
} else {
|
} else {
|
||||||
fetchList = CardLists.getNotType(fetchList, "Land");
|
fetchList = CardLists.getNotType(fetchList, "Land");
|
||||||
// Prefer to pull a creature, generally more useful for AI.
|
// Prefer to pull a creature, generally more useful for AI.
|
||||||
c = chooseCreature(decider, CardLists.filter(fetchList, CardPredicates.Presets.CREATURES));
|
c = chooseCreature(decider, CardLists.filter(fetchList, CardPredicates.CREATURES));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c == null) { // Could not find a creature.
|
if (c == null) { // Could not find a creature.
|
||||||
@@ -1770,7 +1768,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
CardCollection listToSac = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), definedSac, ai, source, sa);
|
CardCollection listToSac = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), definedSac, ai, source, sa);
|
||||||
listToSac.sort(Collections.reverseOrder(CardLists.CmcComparatorInv));
|
listToSac.sort(Collections.reverseOrder(CardLists.CmcComparatorInv));
|
||||||
|
|
||||||
CardCollection listToRet = CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), Presets.CREATURES);
|
CardCollection listToRet = CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.CREATURES);
|
||||||
listToRet.sort(CardLists.CmcComparatorInv);
|
listToRet.sort(CardLists.CmcComparatorInv);
|
||||||
|
|
||||||
if (!listToSac.isEmpty() && !listToRet.isEmpty()) {
|
if (!listToSac.isEmpty() && !listToRet.isEmpty()) {
|
||||||
@@ -1961,7 +1959,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (logic.contains("NonLand")) {
|
if (logic.contains("NonLand")) {
|
||||||
scanList = CardLists.filter(scanList, Presets.NON_LANDS);
|
scanList = CardLists.filter(scanList, CardPredicates.NON_LANDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logic.contains("NonExiled")) {
|
if (logic.contains("NonExiled")) {
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
} else if ("ExileGraveyards".equals(aiLogic)) {
|
} else if ("ExileGraveyards".equals(aiLogic)) {
|
||||||
for (Player opp : ai.getOpponents()) {
|
for (Player opp : ai.getOpponents()) {
|
||||||
CardCollectionView cardsGY = opp.getCardsIn(ZoneType.Graveyard);
|
CardCollectionView cardsGY = opp.getCardsIn(ZoneType.Graveyard);
|
||||||
CardCollection creats = CardLists.filter(cardsGY, CardPredicates.Presets.CREATURES);
|
CardCollection creats = CardLists.filter(cardsGY, CardPredicates.CREATURES);
|
||||||
|
|
||||||
if (opp.hasDelirium() || opp.hasThreshold() || creats.size() >= 5) {
|
if (opp.hasDelirium() || opp.hasThreshold() || creats.size() >= 5) {
|
||||||
return true;
|
return true;
|
||||||
@@ -107,7 +107,7 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
Player bestTgt = null;
|
Player bestTgt = null;
|
||||||
if (player.canBeTargetedBy(sa)) {
|
if (player.canBeTargetedBy(sa)) {
|
||||||
int numGY = CardLists.count(player.getCardsIn(ZoneType.Graveyard),
|
int numGY = CardLists.count(player.getCardsIn(ZoneType.Graveyard),
|
||||||
CardPredicates.Presets.CREATURES);
|
CardPredicates.CREATURES);
|
||||||
if (numGY > maxSize) {
|
if (numGY > maxSize) {
|
||||||
maxSize = numGY;
|
maxSize = numGY;
|
||||||
bestTgt = player;
|
bestTgt = player;
|
||||||
@@ -353,7 +353,7 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
// TODO: this is a stub to prevent the AI from crashing the game when, for instance, playing the opponent's
|
// TODO: this is a stub to prevent the AI from crashing the game when, for instance, playing the opponent's
|
||||||
// Profaner from exile without paying its mana cost. Otherwise the card is marked AI:RemoveDeck:All and
|
// Profaner from exile without paying its mana cost. Otherwise the card is marked AI:RemoveDeck:All and
|
||||||
// there is no specific AI to support playing it in a smarter way. Feel free to expand.
|
// there is no specific AI to support playing it in a smarter way. Feel free to expand.
|
||||||
return Iterables.any(ai.getOpponents().getCardsIn(origin), CardPredicates.Presets.CREATURES);
|
return Iterables.any(ai.getOpponents().getCardsIn(origin), CardPredicates.CREATURES);
|
||||||
}
|
}
|
||||||
|
|
||||||
CardCollectionView humanType = ai.getOpponents().getCardsIn(origin);
|
CardCollectionView humanType = ai.getOpponents().getCardsIn(origin);
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import forge.game.card.CardCollection;
|
|||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates;
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.card.CounterEnumType;
|
import forge.game.card.CounterEnumType;
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.keyword.Keyword;
|
import forge.game.keyword.Keyword;
|
||||||
@@ -178,8 +177,8 @@ public class ChooseCardAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
choice = ComputerUtilCard.getBestAI(ownChoices);
|
choice = ComputerUtilCard.getBestAI(ownChoices);
|
||||||
} else if (logic.equals("BestBlocker")) {
|
} else if (logic.equals("BestBlocker")) {
|
||||||
if (Iterables.any(options, Presets.UNTAPPED)) {
|
if (Iterables.any(options, CardPredicates.UNTAPPED)) {
|
||||||
options = CardLists.filter(options, Presets.UNTAPPED);
|
options = CardLists.filter(options, CardPredicates.UNTAPPED);
|
||||||
}
|
}
|
||||||
choice = ComputerUtilCard.getBestCreatureAI(options);
|
choice = ComputerUtilCard.getBestCreatureAI(options);
|
||||||
} else if (logic.equals("Clone")) {
|
} else if (logic.equals("Clone")) {
|
||||||
@@ -216,7 +215,7 @@ public class ChooseCardAi extends SpellAbilityAi {
|
|||||||
choice = ComputerUtilCard.getWorstAI(aiControlled);
|
choice = ComputerUtilCard.getWorstAI(aiControlled);
|
||||||
}
|
}
|
||||||
} else if ("LowestCMCCreature".equals(logic)) {
|
} else if ("LowestCMCCreature".equals(logic)) {
|
||||||
CardCollection creats = CardLists.filter(options, Presets.CREATURES);
|
CardCollection creats = CardLists.filter(options, CardPredicates.CREATURES);
|
||||||
creats = CardLists.filterToughness(creats, 1);
|
creats = CardLists.filterToughness(creats, 1);
|
||||||
if (creats.isEmpty()) {
|
if (creats.isEmpty()) {
|
||||||
choice = ComputerUtilCard.getWorstAI(options);
|
choice = ComputerUtilCard.getWorstAI(options);
|
||||||
@@ -268,10 +267,10 @@ public class ChooseCardAi extends SpellAbilityAi {
|
|||||||
// – might also be good to do a separate AI for Noble Heritage
|
// – might also be good to do a separate AI for Noble Heritage
|
||||||
}
|
}
|
||||||
} 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), CardPredicates.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.NON_CREATURES);
|
CardCollection nonCreatures = CardLists.filter(aiArtifacts, CardPredicates.NON_CREATURES);
|
||||||
CardCollection creatures = CardLists.filter(aiArtifacts, Presets.CREATURES);
|
CardCollection creatures = CardLists.filter(aiArtifacts, CardPredicates.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
|
||||||
// removal on something unpreferred
|
// removal on something unpreferred
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class ChooseColorAi extends SpellAbilityAi {
|
|||||||
// activate in Main 2 hoping that the extra mana surplus will make a difference
|
// activate in Main 2 hoping that the extra mana surplus will make a difference
|
||||||
// if there are some nonland permanents in hand
|
// if there are some nonland permanents in hand
|
||||||
CardCollectionView permanents = CardLists.filter(ai.getCardsIn(ZoneType.Hand),
|
CardCollectionView permanents = CardLists.filter(ai.getCardsIn(ZoneType.Hand),
|
||||||
CardPredicates.Presets.NONLAND_PERMANENTS);
|
CardPredicates.NONLAND_PERMANENTS);
|
||||||
|
|
||||||
return permanents.size() > 0 && ph.is(PhaseType.MAIN2, ai);
|
return permanents.size() > 0 && ph.is(PhaseType.MAIN2, ai);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import forge.game.Game;
|
|||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -25,7 +25,7 @@ public class ChooseDirectionAi extends SpellAbilityAi {
|
|||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
if ("Aminatou".equals(logic)) {
|
if ("Aminatou".equals(logic)) {
|
||||||
CardCollection all = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), Presets.NONLAND_PERMANENTS);
|
CardCollection all = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.NONLAND_PERMANENTS);
|
||||||
CardCollection aiPermanent = CardLists.filterControlledBy(all, ai);
|
CardCollection aiPermanent = CardLists.filterControlledBy(all, ai);
|
||||||
aiPermanent.remove(sa.getHostCard());
|
aiPermanent.remove(sa.getHostCard());
|
||||||
int aiValue = Aggregates.sum(aiPermanent, Card::getCMC);
|
int aiValue = Aggregates.sum(aiPermanent, Card::getCMC);
|
||||||
|
|||||||
@@ -134,10 +134,10 @@ public class ChooseSourceAi extends SpellAbilityAi {
|
|||||||
// No optimal creature was found above, so try to broaden the choice.
|
// No optimal creature was found above, so try to broaden the choice.
|
||||||
if (!Iterables.isEmpty(options)) {
|
if (!Iterables.isEmpty(options)) {
|
||||||
List<Card> oppCreatures = CardLists.filter(options,
|
List<Card> oppCreatures = CardLists.filter(options,
|
||||||
CardPredicates.Presets.CREATURES.and(CardPredicates.isOwner(aiChoser).negate()));
|
CardPredicates.CREATURES.and(CardPredicates.isOwner(aiChoser).negate()));
|
||||||
List<Card> aiNonCreatures = CardLists.filter(options,
|
List<Card> aiNonCreatures = CardLists.filter(options,
|
||||||
CardPredicates.Presets.NON_CREATURES
|
CardPredicates.NON_CREATURES
|
||||||
.and(CardPredicates.Presets.PERMANENTS)
|
.and(CardPredicates.PERMANENTS)
|
||||||
.and(CardPredicates.isOwner(aiChoser))
|
.and(CardPredicates.isOwner(aiChoser))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class ChooseTypeAi extends SpellAbilityAi {
|
|||||||
int avgPower = 0;
|
int avgPower = 0;
|
||||||
|
|
||||||
// predict the opposition
|
// predict the opposition
|
||||||
CardCollection oppCreatures = CardLists.filter(aiPlayer.getOpponents().getCreaturesInPlay(), CardPredicates.Presets.UNTAPPED);
|
CardCollection oppCreatures = CardLists.filter(aiPlayer.getOpponents().getCreaturesInPlay(), CardPredicates.UNTAPPED);
|
||||||
int maxOppPower = 0;
|
int maxOppPower = 0;
|
||||||
int maxOppToughness = 0;
|
int maxOppToughness = 0;
|
||||||
int oppUsefulCreatures = 0;
|
int oppUsefulCreatures = 0;
|
||||||
@@ -85,7 +85,7 @@ public class ChooseTypeAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
if (maxX > 1) {
|
if (maxX > 1) {
|
||||||
CardCollection cre = CardLists.filter(aiPlayer.getCardsIn(ZoneType.Battlefield),
|
CardCollection cre = CardLists.filter(aiPlayer.getCardsIn(ZoneType.Battlefield),
|
||||||
CardPredicates.isType(chosenType), CardPredicates.Presets.UNTAPPED);
|
CardPredicates.isType(chosenType), CardPredicates.UNTAPPED);
|
||||||
if (!cre.isEmpty()) {
|
if (!cre.isEmpty()) {
|
||||||
for (Card c: cre) {
|
for (Card c: cre) {
|
||||||
avgPower += c.getNetPower();
|
avgPower += c.getNetPower();
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ public class ClashAi extends SpellAbilityAi {
|
|||||||
// Springjack Knight
|
// Springjack Knight
|
||||||
// TODO: Whirlpool Whelm also uses creature targeting but it's trickier to support
|
// TODO: Whirlpool Whelm also uses creature targeting but it's trickier to support
|
||||||
CardCollectionView aiCreats = ai.getCreaturesInPlay();
|
CardCollectionView aiCreats = ai.getCreaturesInPlay();
|
||||||
CardCollectionView oppCreats = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
|
CardCollectionView oppCreats = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.CREATURES);
|
||||||
|
|
||||||
Card tgt = aiCreats.isEmpty() ? ComputerUtilCard.getWorstCreatureAI(oppCreats) : ComputerUtilCard.getBestCreatureAI(aiCreats);
|
Card tgt = aiCreats.isEmpty() ? ComputerUtilCard.getWorstCreatureAI(oppCreats) : ComputerUtilCard.getBestCreatureAI(aiCreats);
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import forge.game.card.CardCollection;
|
|||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates;
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.card.CardUtil;
|
import forge.game.card.CardUtil;
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
@@ -177,7 +176,7 @@ public class CopyPermanentAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
list = CardLists.filter(list, c -> (!c.getType().isLegendary() || canCopyLegendary) || !c.getController().equals(aiPlayer));
|
list = CardLists.filter(list, c -> (!c.getType().isLegendary() || canCopyLegendary) || !c.getController().equals(aiPlayer));
|
||||||
Card choice;
|
Card choice;
|
||||||
if (Iterables.any(list, Presets.CREATURES)) {
|
if (Iterables.any(list, CardPredicates.CREATURES)) {
|
||||||
if (sa.hasParam("TargetingPlayer")) {
|
if (sa.hasParam("TargetingPlayer")) {
|
||||||
choice = ComputerUtilCard.getWorstCreatureAI(list);
|
choice = ComputerUtilCard.getWorstCreatureAI(list);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -380,7 +380,7 @@ public class CountersPutAi extends CountersAi {
|
|||||||
sa.setXManaCostPaid(amount);
|
sa.setXManaCostPaid(amount);
|
||||||
} else if ("ExiledCreatureFromGraveCMC".equals(logic)) {
|
} else if ("ExiledCreatureFromGraveCMC".equals(logic)) {
|
||||||
// e.g. Necropolis
|
// e.g. Necropolis
|
||||||
amount = Aggregates.max(CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.CREATURES), Card::getCMC);
|
amount = Aggregates.max(CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.CREATURES), Card::getCMC);
|
||||||
if (amount > 0 && ai.getGame().getPhaseHandler().is(PhaseType.END_OF_TURN)) {
|
if (amount > 0 && ai.getGame().getPhaseHandler().is(PhaseType.END_OF_TURN)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -703,7 +703,7 @@ public class CountersPutAi extends CountersAi {
|
|||||||
if (sa.isCurse()) {
|
if (sa.isCurse()) {
|
||||||
choice = chooseCursedTarget(list, type, amount, ai);
|
choice = chooseCursedTarget(list, type, amount, ai);
|
||||||
} else {
|
} else {
|
||||||
CardCollection lands = CardLists.filter(list, CardPredicates.Presets.LANDS);
|
CardCollection lands = CardLists.filter(list, CardPredicates.LANDS);
|
||||||
SpellAbility animate = sa.findSubAbilityByType(ApiType.Animate);
|
SpellAbility animate = sa.findSubAbilityByType(ApiType.Animate);
|
||||||
if (!lands.isEmpty() && animate != null) {
|
if (!lands.isEmpty() && animate != null) {
|
||||||
choice = ComputerUtilCard.getWorstLand(lands);
|
choice = ComputerUtilCard.getWorstLand(lands);
|
||||||
@@ -796,7 +796,7 @@ public class CountersPutAi extends CountersAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to choose player with less creatures
|
// try to choose player with less creatures
|
||||||
Player choice = playerList.min(PlayerPredicates.compareByZoneSize(ZoneType.Battlefield, CardPredicates.Presets.CREATURES));
|
Player choice = playerList.min(PlayerPredicates.compareByZoneSize(ZoneType.Battlefield, CardPredicates.CREATURES));
|
||||||
|
|
||||||
if (choice != null) {
|
if (choice != null) {
|
||||||
sa.getTargets().add(choice);
|
sa.getTargets().add(choice);
|
||||||
@@ -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.Presets.CREATURES);
|
CardCollectionView ownLib = CardLists.filter(ai.getCardsIn(ZoneType.Library), CardPredicates.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;
|
||||||
@@ -1211,7 +1211,7 @@ public class CountersPutAi extends CountersAi {
|
|||||||
|
|
||||||
private boolean doChargeToOppCtrlCMCLogic(Player ai, SpellAbility sa) {
|
private boolean doChargeToOppCtrlCMCLogic(Player ai, SpellAbility sa) {
|
||||||
Card source = sa.getHostCard();
|
Card source = sa.getHostCard();
|
||||||
CardCollectionView oppInPlay = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.NONLAND_PERMANENTS);
|
CardCollectionView oppInPlay = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.NONLAND_PERMANENTS);
|
||||||
int numCtrs = source.getCounters(CounterEnumType.CHARGE);
|
int numCtrs = source.getCounters(CounterEnumType.CHARGE);
|
||||||
int maxCMC = Aggregates.max(oppInPlay, Card::getCMC);
|
int maxCMC = Aggregates.max(oppInPlay, Card::getCMC);
|
||||||
int optimalCMC = 0;
|
int optimalCMC = 0;
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ public class CountersPutOrRemoveAi extends SpellAbilityAi {
|
|||||||
// with one touch
|
// with one touch
|
||||||
CardCollection planeswalkerList = CardLists.filter(
|
CardCollection planeswalkerList = CardLists.filter(
|
||||||
CardLists.filterControlledBy(countersList, ai.getOpponents()),
|
CardLists.filterControlledBy(countersList, ai.getOpponents()),
|
||||||
CardPredicates.Presets.PLANESWALKERS,
|
CardPredicates.PLANESWALKERS,
|
||||||
CardPredicates.hasLessCounter(CounterEnumType.LOYALTY, amount));
|
CardPredicates.hasLessCounter(CounterEnumType.LOYALTY, amount));
|
||||||
|
|
||||||
if (!planeswalkerList.isEmpty()) {
|
if (!planeswalkerList.isEmpty()) {
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public class CountersRemoveAi extends SpellAbilityAi {
|
|||||||
list = ai.getOpponents().getCardsIn(ZoneType.Battlefield);
|
list = ai.getOpponents().getCardsIn(ZoneType.Battlefield);
|
||||||
list = CardLists.filter(list, CardPredicates.isTargetableBy(sa));
|
list = CardLists.filter(list, CardPredicates.isTargetableBy(sa));
|
||||||
|
|
||||||
CardCollection planeswalkerList = CardLists.filter(list, CardPredicates.Presets.PLANESWALKERS,
|
CardCollection planeswalkerList = CardLists.filter(list, CardPredicates.PLANESWALKERS,
|
||||||
CardPredicates.hasCounter(CounterEnumType.LOYALTY, 5));
|
CardPredicates.hasCounter(CounterEnumType.LOYALTY, 5));
|
||||||
|
|
||||||
if (!planeswalkerList.isEmpty()) {
|
if (!planeswalkerList.isEmpty()) {
|
||||||
@@ -182,7 +182,7 @@ public class CountersRemoveAi extends SpellAbilityAi {
|
|||||||
list = CardLists.filter(list, CardPredicates.isTargetableBy(sa));
|
list = CardLists.filter(list, CardPredicates.isTargetableBy(sa));
|
||||||
|
|
||||||
CardCollection planeswalkerList = CardLists.filter(list,
|
CardCollection planeswalkerList = CardLists.filter(list,
|
||||||
CardPredicates.Presets.PLANESWALKERS.and(CardPredicates.isControlledByAnyOf(ai.getOpponents())),
|
CardPredicates.PLANESWALKERS.and(CardPredicates.isControlledByAnyOf(ai.getOpponents())),
|
||||||
CardPredicates.hasLessCounter(CounterEnumType.LOYALTY, amount));
|
CardPredicates.hasLessCounter(CounterEnumType.LOYALTY, amount));
|
||||||
|
|
||||||
if (!planeswalkerList.isEmpty()) {
|
if (!planeswalkerList.isEmpty()) {
|
||||||
@@ -222,7 +222,7 @@ public class CountersRemoveAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
// remove P1P1 counters from opposing creatures
|
// remove P1P1 counters from opposing creatures
|
||||||
CardCollection oppP1P1List = CardLists.filter(list,
|
CardCollection oppP1P1List = CardLists.filter(list,
|
||||||
CardPredicates.Presets.CREATURES.and(CardPredicates.isControlledByAnyOf(ai.getOpponents())),
|
CardPredicates.CREATURES.and(CardPredicates.isControlledByAnyOf(ai.getOpponents())),
|
||||||
CardPredicates.hasCounter(CounterEnumType.P1P1));
|
CardPredicates.hasCounter(CounterEnumType.P1P1));
|
||||||
if (!oppP1P1List.isEmpty()) {
|
if (!oppP1P1List.isEmpty()) {
|
||||||
sa.getTargets().add(ComputerUtilCard.getBestCreatureAI(oppP1P1List));
|
sa.getTargets().add(ComputerUtilCard.getBestCreatureAI(oppP1P1List));
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import forge.game.staticability.StaticAbilityMustTarget;
|
|||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
import forge.util.Predicates;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
@@ -408,7 +407,7 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
final Player activator = sa.getActivatingPlayer();
|
final Player activator = sa.getActivatingPlayer();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final Game game = source.getGame();
|
final Game game = source.getGame();
|
||||||
List<Card> hPlay = CardLists.filter(getTargetableCards(ai, sa, pl, tgt, activator, source, game), CardPredicates.Presets.PLANESWALKERS);
|
List<Card> hPlay = CardLists.filter(getTargetableCards(ai, sa, pl, tgt, activator, source, game), CardPredicates.PLANESWALKERS);
|
||||||
|
|
||||||
CardCollection killables = CardLists.filter(hPlay, c -> c.getSVar("Targeting").equals("Dies")
|
CardCollection killables = CardLists.filter(hPlay, c -> c.getSVar("Targeting").equals("Dies")
|
||||||
|| (ComputerUtilCombat.getEnoughDamageToKill(c, d, source, false, noPrevention) <= d)
|
|| (ComputerUtilCombat.getEnoughDamageToKill(c, d, source, false, noPrevention) <= d)
|
||||||
@@ -892,8 +891,8 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
|
|
||||||
// See if there's an indestructible target that can be used
|
// See if there's an indestructible target that can be used
|
||||||
CardCollection indestructible = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield),
|
CardCollection indestructible = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield),
|
||||||
CardPredicates.Presets.CREATURES
|
CardPredicates.CREATURES
|
||||||
.and(CardPredicates.Presets.PLANESWALKERS) //TODO: Should this be "or" Planeswalkers?
|
.and(CardPredicates.PLANESWALKERS) //TODO: Should this be "or" Planeswalkers?
|
||||||
.and(CardPredicates.hasKeyword(Keyword.INDESTRUCTIBLE))
|
.and(CardPredicates.hasKeyword(Keyword.INDESTRUCTIBLE))
|
||||||
.and(CardPredicates.isTargetableBy(sa))
|
.and(CardPredicates.isTargetableBy(sa))
|
||||||
);
|
);
|
||||||
@@ -909,7 +908,7 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
}
|
}
|
||||||
else if (tgt.canTgtPlaneswalker()) {
|
else if (tgt.canTgtPlaneswalker()) {
|
||||||
// Second pass for planeswalkers: choose AI's worst planeswalker
|
// Second pass for planeswalkers: choose AI's worst planeswalker
|
||||||
final Card c = ComputerUtilCard.getWorstPlaneswalkerToDamage(CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.PLANESWALKERS, CardPredicates.isTargetableBy(sa)));
|
final Card c = ComputerUtilCard.getWorstPlaneswalkerToDamage(CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.PLANESWALKERS, CardPredicates.isTargetableBy(sa)));
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
sa.getTargets().add(c);
|
sa.getTargets().add(c);
|
||||||
if (divided) {
|
if (divided) {
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ public class DamagePreventAi extends SpellAbilityAi {
|
|||||||
if (targetables.isEmpty()) {
|
if (targetables.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final CardCollection combatants = CardLists.filter(targetables, CardPredicates.Presets.CREATURES);
|
final CardCollection combatants = CardLists.filter(targetables, CardPredicates.CREATURES);
|
||||||
ComputerUtilCard.sortByEvaluateCreature(combatants);
|
ComputerUtilCard.sortByEvaluateCreature(combatants);
|
||||||
|
|
||||||
for (final Card c : combatants) {
|
for (final Card c : combatants) {
|
||||||
@@ -187,7 +187,7 @@ public class DamagePreventAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!compTargetables.isEmpty()) {
|
if (!compTargetables.isEmpty()) {
|
||||||
final CardCollection combatants = CardLists.filter(compTargetables, CardPredicates.Presets.CREATURES);
|
final CardCollection combatants = CardLists.filter(compTargetables, CardPredicates.CREATURES);
|
||||||
ComputerUtilCard.sortByEvaluateCreature(combatants);
|
ComputerUtilCard.sortByEvaluateCreature(combatants);
|
||||||
if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
|
if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
|
||||||
Combat combat = game.getCombat();
|
Combat combat = game.getCombat();
|
||||||
|
|||||||
@@ -425,8 +425,8 @@ public class DestroyAi extends SpellAbilityAi {
|
|||||||
boolean nonBasicTgt = !tgtLand.isBasicLand();
|
boolean nonBasicTgt = !tgtLand.isBasicLand();
|
||||||
|
|
||||||
// Try not to lose tempo too much and not to mana-screw yourself when considering this logic
|
// Try not to lose tempo too much and not to mana-screw yourself when considering this logic
|
||||||
int numLandsInHand = CardLists.count(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
int numLandsInHand = CardLists.count(ai.getCardsIn(ZoneType.Hand), CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
int numLandsOTB = CardLists.count(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
int numLandsOTB = CardLists.count(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
|
|
||||||
// If the opponent skipped a land drop, consider not looking at having the extra land in hand if the profile allows it
|
// If the opponent skipped a land drop, consider not looking at having the extra land in hand if the profile allows it
|
||||||
boolean isHighPriority = highPriorityIfNoLandDrop && oppSkippedLandDrop;
|
boolean isHighPriority = highPriorityIfNoLandDrop && oppSkippedLandDrop;
|
||||||
|
|||||||
@@ -109,8 +109,8 @@ public class DestroyAllAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
// Special handling for Raiding Party
|
// Special handling for Raiding Party
|
||||||
if (logic.equals("RaidingParty")) {
|
if (logic.equals("RaidingParty")) {
|
||||||
int numAiCanSave = Math.min(CardLists.count(ai.getCreaturesInPlay(), CardPredicates.isColor(MagicColor.WHITE).and(CardPredicates.Presets.UNTAPPED)) * 2, ailist.size());
|
int numAiCanSave = Math.min(CardLists.count(ai.getCreaturesInPlay(), CardPredicates.isColor(MagicColor.WHITE).and(CardPredicates.UNTAPPED)) * 2, ailist.size());
|
||||||
int numOppsCanSave = Math.min(CardLists.count(ai.getOpponents().getCreaturesInPlay(), CardPredicates.isColor(MagicColor.WHITE).and(CardPredicates.Presets.UNTAPPED)) * 2, opplist.size());
|
int numOppsCanSave = Math.min(CardLists.count(ai.getOpponents().getCreaturesInPlay(), CardPredicates.isColor(MagicColor.WHITE).and(CardPredicates.UNTAPPED)) * 2, opplist.size());
|
||||||
|
|
||||||
return numOppsCanSave < opplist.size() && (ailist.size() - numAiCanSave < opplist.size() - numOppsCanSave);
|
return numOppsCanSave < opplist.size() && (ailist.size() - numAiCanSave < opplist.size() - numOppsCanSave);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class DigUntilAi extends SpellAbilityAi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ("Land.Basic".equals(sa.getParam("Valid"))
|
if ("Land.Basic".equals(sa.getParam("Valid"))
|
||||||
&& ai.getZone(ZoneType.Hand).contains(CardPredicates.Presets.LANDS_PRODUCING_MANA)) {
|
&& ai.getZone(ZoneType.Hand).contains(CardPredicates.LANDS_PRODUCING_MANA)) {
|
||||||
// We already have a mana-producing land in hand, so bail
|
// We already have a mana-producing land in hand, so bail
|
||||||
// until opponent's end of turn phase!
|
// until opponent's end of turn phase!
|
||||||
// But we still want more (and want to fill grave) if nothing better to do then
|
// But we still want more (and want to fill grave) if nothing better to do then
|
||||||
@@ -128,7 +128,7 @@ public class DigUntilAi extends SpellAbilityAi {
|
|||||||
final String logic = sa.getParam("AILogic");
|
final String logic = sa.getParam("AILogic");
|
||||||
if ("OathOfDruids".equals(logic)) {
|
if ("OathOfDruids".equals(logic)) {
|
||||||
final List<Card> creaturesInLibrary =
|
final List<Card> creaturesInLibrary =
|
||||||
CardLists.filter(player.getCardsIn(ZoneType.Library), CardPredicates.Presets.CREATURES);
|
CardLists.filter(player.getCardsIn(ZoneType.Library), CardPredicates.CREATURES);
|
||||||
final List<Card> creaturesInBattlefield = player.getCreaturesInPlay();
|
final List<Card> creaturesInBattlefield = player.getCreaturesInPlay();
|
||||||
// if there are at least 3 creatures in library,
|
// if there are at least 3 creatures in library,
|
||||||
// or none in play with one in library, oath
|
// or none in play with one in library, oath
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public class DiscardAi extends SpellAbilityAi {
|
|||||||
if (sa.hasParam("AnyNumber")) {
|
if (sa.hasParam("AnyNumber")) {
|
||||||
if ("DiscardUncastableAndExcess".equals(aiLogic)) {
|
if ("DiscardUncastableAndExcess".equals(aiLogic)) {
|
||||||
final CardCollectionView inHand = ai.getCardsIn(ZoneType.Hand);
|
final CardCollectionView inHand = ai.getCardsIn(ZoneType.Hand);
|
||||||
final int numLandsOTB = CardLists.count(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.LANDS);
|
final int numLandsOTB = CardLists.count(ai.getCardsIn(ZoneType.Hand), CardPredicates.LANDS);
|
||||||
int numDiscard = 0;
|
int numDiscard = 0;
|
||||||
int numOppInHand = 0;
|
int numOppInHand = 0;
|
||||||
for (Player p : ai.getGame().getPlayers()) {
|
for (Player p : ai.getGame().getPlayers()) {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import forge.game.ability.AbilityKey;
|
|||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.combat.CombatUtil;
|
import forge.game.combat.CombatUtil;
|
||||||
import forge.game.keyword.Keyword;
|
import forge.game.keyword.Keyword;
|
||||||
@@ -56,8 +55,8 @@ public class EffectAi extends SpellAbilityAi {
|
|||||||
for (Player opp : ai.getOpponents()) {
|
for (Player opp : ai.getOpponents()) {
|
||||||
boolean worthHolding = false;
|
boolean worthHolding = false;
|
||||||
CardCollectionView oppCreatsLands = CardLists.filter(opp.getCardsIn(ZoneType.Battlefield),
|
CardCollectionView oppCreatsLands = CardLists.filter(opp.getCardsIn(ZoneType.Battlefield),
|
||||||
Presets.LANDS.or(Presets.CREATURES));
|
CardPredicates.LANDS.or(CardPredicates.CREATURES));
|
||||||
CardCollectionView oppCreatsLandsTapped = CardLists.filter(oppCreatsLands, CardPredicates.Presets.TAPPED);
|
CardCollectionView oppCreatsLandsTapped = CardLists.filter(oppCreatsLands, CardPredicates.TAPPED);
|
||||||
|
|
||||||
if (oppCreatsLandsTapped.size() >= 3 || oppCreatsLands.size() == oppCreatsLandsTapped.size()) {
|
if (oppCreatsLandsTapped.size() >= 3 || oppCreatsLands.size() == oppCreatsLandsTapped.size()) {
|
||||||
worthHolding = true;
|
worthHolding = true;
|
||||||
@@ -83,7 +82,7 @@ public class EffectAi extends SpellAbilityAi {
|
|||||||
Player opp = ai.getStrongestOpponent();
|
Player opp = ai.getStrongestOpponent();
|
||||||
List<Card> possibleAttackers = ai.getCreaturesInPlay();
|
List<Card> possibleAttackers = ai.getCreaturesInPlay();
|
||||||
List<Card> possibleBlockers = opp.getCreaturesInPlay();
|
List<Card> possibleBlockers = opp.getCreaturesInPlay();
|
||||||
possibleBlockers = CardLists.filter(possibleBlockers, Presets.UNTAPPED);
|
possibleBlockers = CardLists.filter(possibleBlockers, CardPredicates.UNTAPPED);
|
||||||
final Combat combat = game.getCombat();
|
final Combat combat = game.getCombat();
|
||||||
int oppLife = opp.getLife();
|
int oppLife = opp.getLife();
|
||||||
int potentialDmg = 0;
|
int potentialDmg = 0;
|
||||||
@@ -332,7 +331,7 @@ public class EffectAi extends SpellAbilityAi {
|
|||||||
} else if (logic.equals("CantRegenerate")) {
|
} else if (logic.equals("CantRegenerate")) {
|
||||||
if (sa.usesTargeting()) {
|
if (sa.usesTargeting()) {
|
||||||
CardCollection list = CardLists.getTargetableCards(ai.getOpponents().getCardsIn(ZoneType.Battlefield), sa);
|
CardCollection list = CardLists.getTargetableCards(ai.getOpponents().getCardsIn(ZoneType.Battlefield), sa);
|
||||||
list = CardLists.filter(list, CardPredicates.Presets.CAN_BE_DESTROYED, input -> {
|
list = CardLists.filter(list, CardPredicates.CAN_BE_DESTROYED, input -> {
|
||||||
Map<AbilityKey, Object> runParams = AbilityKey.mapFromAffected(input);
|
Map<AbilityKey, Object> runParams = AbilityKey.mapFromAffected(input);
|
||||||
runParams.put(AbilityKey.Regeneration, true);
|
runParams.put(AbilityKey.Regeneration, true);
|
||||||
List<ReplacementEffect> repDestoryList = game.getReplacementHandler().getReplacementList(ReplacementType.Destroy, runParams, ReplacementLayer.Other);
|
List<ReplacementEffect> repDestoryList = game.getReplacementHandler().getReplacementList(ReplacementType.Destroy, runParams, ReplacementLayer.Other);
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ public class ExploreAi extends SpellAbilityAi {
|
|||||||
int predictedMana = ComputerUtilMana.getAvailableManaSources(ai, false).size();
|
int predictedMana = ComputerUtilMana.getAvailableManaSources(ai, false).size();
|
||||||
CardCollectionView cardsOTB = ai.getCardsIn(ZoneType.Battlefield);
|
CardCollectionView cardsOTB = ai.getCardsIn(ZoneType.Battlefield);
|
||||||
CardCollectionView cardsInHand = ai.getCardsIn(ZoneType.Hand);
|
CardCollectionView cardsInHand = ai.getCardsIn(ZoneType.Hand);
|
||||||
CardCollection landsOTB = CardLists.filter(cardsOTB, CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
CardCollection landsOTB = CardLists.filter(cardsOTB, CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
CardCollection landsInHand = CardLists.filter(cardsInHand, CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
CardCollection landsInHand = CardLists.filter(cardsInHand, CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
|
|
||||||
int maxCMCDiff = 1;
|
int maxCMCDiff = 1;
|
||||||
int numLandsToStillNeedMore = 2;
|
int numLandsToStillNeedMore = 2;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class HauntAi extends SpellAbilityAi {
|
|||||||
final Game game = ai.getGame();
|
final Game game = ai.getGame();
|
||||||
if (sa.usesTargeting() && !card.isToken()) {
|
if (sa.usesTargeting() && !card.isToken()) {
|
||||||
final List<Card> creats = CardLists.filter(game.getCardsIn(ZoneType.Battlefield),
|
final List<Card> creats = CardLists.filter(game.getCardsIn(ZoneType.Battlefield),
|
||||||
CardPredicates.Presets.CREATURES);
|
CardPredicates.CREATURES);
|
||||||
|
|
||||||
// nothing to haunt
|
// nothing to haunt
|
||||||
if (creats.isEmpty()) {
|
if (creats.isEmpty()) {
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class MillAi extends SpellAbilityAi {
|
|||||||
return ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn().equals(ai);
|
return ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn().equals(ai);
|
||||||
} else if (aiLogic.equals("LilianaMill")) {
|
} else if (aiLogic.equals("LilianaMill")) {
|
||||||
// Only mill if a "Raise Dead" target is available, in case of control decks with few creatures
|
// Only mill if a "Raise Dead" target is available, in case of control decks with few creatures
|
||||||
return CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.CREATURES).size() >= 1;
|
return CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), CardPredicates.CREATURES).size() >= 1;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,8 +140,8 @@ 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.Presets.NON_LANDS);
|
aiCards = CardLists.filter(aiCards, CardPredicates.NON_LANDS);
|
||||||
oppCards = CardLists.filter(oppCards, CardPredicates.Presets.NON_LANDS);
|
oppCards = CardLists.filter(oppCards, CardPredicates.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.nameNotEquals("Chalice of the Void"));
|
aiCards = CardLists.filter(aiCards, CardPredicates.nameNotEquals("Chalice of the Void"));
|
||||||
}
|
}
|
||||||
@@ -257,7 +257,7 @@ public class PermanentAi extends SpellAbilityAi {
|
|||||||
// Only cast if there are X or more mana sources controlled by the AI *or*
|
// Only cast if there are X or more mana sources controlled by the AI *or*
|
||||||
// if there are X-1 mana sources in play but the AI has an extra land in hand
|
// if there are X-1 mana sources in play but the AI has an extra land in hand
|
||||||
CardCollection m = ComputerUtilMana.getAvailableManaSources(ai, true);
|
CardCollection m = ComputerUtilMana.getAvailableManaSources(ai, true);
|
||||||
int extraMana = CardLists.count(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.LANDS) > 0 ? 1 : 0;
|
int extraMana = CardLists.count(ai.getCardsIn(ZoneType.Hand), CardPredicates.LANDS) > 0 ? 1 : 0;
|
||||||
if (source.getName().equals("Illusions of Grandeur")) {
|
if (source.getName().equals("Illusions of Grandeur")) {
|
||||||
// TODO: this is currently hardcoded for specific Illusions-Donate cost reduction spells, need to make this generic.
|
// TODO: this is currently hardcoded for specific Illusions-Donate cost reduction spells, need to make this generic.
|
||||||
extraMana += Math.min(3, CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Sapphire Medallion").or(CardPredicates.nameEquals("Helm of Awakening"))).size()) * 2; // each cost-reduction spell accounts for {1} in both Illusions and Donate
|
extraMana += Math.min(3, CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Sapphire Medallion").or(CardPredicates.nameEquals("Helm of Awakening"))).size()) * 2; // each cost-reduction spell accounts for {1} in both Illusions and Donate
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import forge.game.Game;
|
|||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.cost.CostTapType;
|
import forge.game.cost.CostTapType;
|
||||||
import forge.game.keyword.Keyword;
|
import forge.game.keyword.Keyword;
|
||||||
@@ -402,7 +401,7 @@ public class PumpAi extends PumpAiBase {
|
|||||||
CardCollection list;
|
CardCollection list;
|
||||||
if (sa.hasParam("AILogic")) {
|
if (sa.hasParam("AILogic")) {
|
||||||
if (sa.getParam("AILogic").equals("HighestPower") || sa.getParam("AILogic").equals("ContinuousBonus")) {
|
if (sa.getParam("AILogic").equals("HighestPower") || sa.getParam("AILogic").equals("ContinuousBonus")) {
|
||||||
list = CardLists.getValidCards(CardLists.filter(game.getCardsIn(ZoneType.Battlefield), Presets.CREATURES), tgt.getValidTgts(), ai, source, sa);
|
list = CardLists.getValidCards(CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.CREATURES), tgt.getValidTgts(), ai, source, sa);
|
||||||
list = CardLists.getTargetableCards(list, sa);
|
list = CardLists.getTargetableCards(list, sa);
|
||||||
CardLists.sortByPowerDesc(list);
|
CardLists.sortByPowerDesc(list);
|
||||||
|
|
||||||
@@ -511,7 +510,7 @@ public class PumpAi extends PumpAiBase {
|
|||||||
// Detain target nonland permanent: don't target noncreature permanents that don't have
|
// Detain target nonland permanent: don't target noncreature permanents that don't have
|
||||||
// any activated abilities.
|
// any activated abilities.
|
||||||
if ("DetainNonLand".equals(sa.getParam("AILogic"))) {
|
if ("DetainNonLand".equals(sa.getParam("AILogic"))) {
|
||||||
list = CardLists.filter(list, Presets.CREATURES.or(card -> {
|
list = CardLists.filter(list, CardPredicates.CREATURES.or(card -> {
|
||||||
for (SpellAbility sa1 : card.getSpellAbilities()) {
|
for (SpellAbility sa1 : card.getSpellAbilities()) {
|
||||||
if (sa1.isActivatedAbility()) {
|
if (sa1.isActivatedAbility()) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ public class RearrangeTopOfLibraryAi extends SpellAbilityAi {
|
|||||||
uncastableCMCThreshold = aic.getIntProperty(AiProps.SCRY_IMMEDIATELY_UNCASTABLE_CMC_DIFF);
|
uncastableCMCThreshold = aic.getIntProperty(AiProps.SCRY_IMMEDIATELY_UNCASTABLE_CMC_DIFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
int landsOTB = CardLists.count(p.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.LANDS_PRODUCING_MANA);
|
int landsOTB = CardLists.count(p.getCardsIn(ZoneType.Battlefield), CardPredicates.LANDS_PRODUCING_MANA);
|
||||||
int cmc = top.isSplitCard() ? Math.min(top.getCMC(Card.SplitCMCMode.LeftSplitCMC), top.getCMC(Card.SplitCMCMode.RightSplitCMC))
|
int cmc = top.isSplitCard() ? Math.min(top.getCMC(Card.SplitCMCMode.LeftSplitCMC), top.getCMC(Card.SplitCMCMode.RightSplitCMC))
|
||||||
: top.getCMC();
|
: top.getCMC();
|
||||||
int maxCastable = ComputerUtilMana.getAvailableManaEstimate(p, false);
|
int maxCastable = ComputerUtilMana.getAvailableManaEstimate(p, false);
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ public class RegenerateAi extends SpellAbilityAi {
|
|||||||
chance = true;
|
chance = true;
|
||||||
}
|
}
|
||||||
} else if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
|
} else if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
|
||||||
final CardCollection combatants = CardLists.filter(targetables, CardPredicates.Presets.CREATURES);
|
final CardCollection combatants = CardLists.filter(targetables, CardPredicates.CREATURES);
|
||||||
ComputerUtilCard.sortByEvaluateCreature(combatants);
|
ComputerUtilCard.sortByEvaluateCreature(combatants);
|
||||||
|
|
||||||
for (final Card c : combatants) {
|
for (final Card c : combatants) {
|
||||||
@@ -156,7 +156,7 @@ public class RegenerateAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (compTargetables.size() > 0) {
|
if (compTargetables.size() > 0) {
|
||||||
final CardCollection combatants = CardLists.filter(compTargetables, CardPredicates.Presets.CREATURES);
|
final CardCollection combatants = CardLists.filter(compTargetables, CardPredicates.CREATURES);
|
||||||
ComputerUtilCard.sortByEvaluateCreature(combatants);
|
ComputerUtilCard.sortByEvaluateCreature(combatants);
|
||||||
if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
|
if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
|
||||||
Combat combat = game.getCombat();
|
Combat combat = game.getCombat();
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import forge.ai.SpecialCardAi;
|
|||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@@ -30,7 +29,7 @@ public class RepeatEachAi extends SpellAbilityAi {
|
|||||||
} else if ("Never".equals(logic)) {
|
} else if ("Never".equals(logic)) {
|
||||||
return false;
|
return false;
|
||||||
} else if ("CloneAllTokens".equals(logic)) {
|
} else if ("CloneAllTokens".equals(logic)) {
|
||||||
List<Card> humTokenCreats = CardLists.filter(aiPlayer.getOpponents().getCreaturesInPlay(), Presets.TOKEN);
|
List<Card> humTokenCreats = CardLists.filter(aiPlayer.getOpponents().getCreaturesInPlay(), CardPredicates.TOKEN);
|
||||||
List<Card> compTokenCreats = aiPlayer.getTokensInPlay();
|
List<Card> compTokenCreats = aiPlayer.getTokensInPlay();
|
||||||
|
|
||||||
return compTokenCreats.size() > humTokenCreats.size();
|
return compTokenCreats.size() > humTokenCreats.size();
|
||||||
|
|||||||
@@ -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.NON_LANDS)) {
|
for (Card c : CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.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)) {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public class SetStateAi extends SpellAbilityAi {
|
|||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
|
|
||||||
// select only the ones that can transform
|
// select only the ones that can transform
|
||||||
CardCollection list = CardLists.filter(CardUtil.getValidCardsToTarget(sa), CardPredicates.Presets.CREATURES, c -> c.canTransform(sa));
|
CardCollection list = CardLists.filter(CardUtil.getValidCardsToTarget(sa), CardPredicates.CREATURES, c -> c.canTransform(sa));
|
||||||
|
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import forge.game.card.Card;
|
|||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates;
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.combat.CombatUtil;
|
import forge.game.combat.CombatUtil;
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
@@ -107,7 +106,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
|||||||
protected boolean tapPrefTargeting(final Player ai, final Card source, final SpellAbility sa, final boolean mandatory) {
|
protected boolean tapPrefTargeting(final Player ai, final Card source, final SpellAbility sa, final boolean mandatory) {
|
||||||
final Game game = ai.getGame();
|
final Game game = ai.getGame();
|
||||||
CardCollection tapList = CardLists.getTargetableCards(ai.getOpponents().getCardsIn(ZoneType.Battlefield), sa);
|
CardCollection tapList = CardLists.getTargetableCards(ai.getOpponents().getCardsIn(ZoneType.Battlefield), sa);
|
||||||
tapList = CardLists.filter(tapList, Presets.CAN_TAP);
|
tapList = CardLists.filter(tapList, CardPredicates.CAN_TAP);
|
||||||
tapList = CardLists.filter(tapList, c -> {
|
tapList = CardLists.filter(tapList, c -> {
|
||||||
if (c.isCreature()) {
|
if (c.isCreature()) {
|
||||||
return true;
|
return true;
|
||||||
@@ -196,7 +195,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
|||||||
} else if (phase.isPlayerTurn(opp)
|
} else if (phase.isPlayerTurn(opp)
|
||||||
&& phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
|
&& phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
|
||||||
// Tap creatures possible blockers before combat during AI's turn.
|
// Tap creatures possible blockers before combat during AI's turn.
|
||||||
if (Iterables.any(tapList, CardPredicates.Presets.CREATURES)) {
|
if (Iterables.any(tapList, CardPredicates.CREATURES)) {
|
||||||
List<Card> creatureList = CardLists.filter(tapList, c -> c.isCreature() && CombatUtil.canAttack(c, opp));
|
List<Card> creatureList = CardLists.filter(tapList, c -> c.isCreature() && CombatUtil.canAttack(c, opp));
|
||||||
choice = ComputerUtilCard.getBestCreatureAI(creatureList);
|
choice = ComputerUtilCard.getBestCreatureAI(creatureList);
|
||||||
} else { // no creatures available
|
} else { // no creatures available
|
||||||
@@ -264,7 +263,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to just tap already tapped things
|
// try to just tap already tapped things
|
||||||
tapList = CardLists.filter(list, Presets.TAPPED);
|
tapList = CardLists.filter(list, CardPredicates.TAPPED);
|
||||||
|
|
||||||
if (tapTargetList(ai, sa, tapList, mandatory)) {
|
if (tapTargetList(ai, sa, tapList, mandatory)) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class TapAllAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
validTappables = CardLists.getValidCards(validTappables, valid, source.getController(), source, sa);
|
validTappables = CardLists.getValidCards(validTappables, valid, source.getController(), source, sa);
|
||||||
validTappables = CardLists.filter(validTappables, CardPredicates.Presets.UNTAPPED);
|
validTappables = CardLists.filter(validTappables, CardPredicates.UNTAPPED);
|
||||||
|
|
||||||
if (sa.hasParam("AILogic")) {
|
if (sa.hasParam("AILogic")) {
|
||||||
String logic = sa.getParam("AILogic");
|
String logic = sa.getParam("AILogic");
|
||||||
@@ -83,7 +83,7 @@ public class TapAllAi extends SpellAbilityAi {
|
|||||||
final Game game = source.getGame();
|
final Game game = source.getGame();
|
||||||
CardCollectionView tmpList = game.getCardsIn(ZoneType.Battlefield);
|
CardCollectionView tmpList = game.getCardsIn(ZoneType.Battlefield);
|
||||||
tmpList = CardLists.getValidCards(tmpList, valid, source.getController(), source, sa);
|
tmpList = CardLists.getValidCards(tmpList, valid, source.getController(), source, sa);
|
||||||
tmpList = CardLists.filter(tmpList, CardPredicates.Presets.UNTAPPED);
|
tmpList = CardLists.filter(tmpList, CardPredicates.UNTAPPED);
|
||||||
return tmpList;
|
return tmpList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import forge.game.ability.ApiType;
|
|||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.cost.CostTap;
|
import forge.game.cost.CostTap;
|
||||||
@@ -155,7 +155,7 @@ public class UntapAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CardCollection untapList = targetUntapped ? list : CardLists.filter(list, Presets.TAPPED);
|
CardCollection untapList = targetUntapped ? list : CardLists.filter(list, CardPredicates.TAPPED);
|
||||||
// filter out enchantments and planeswalkers, their tapped state doesn't matter.
|
// filter out enchantments and planeswalkers, their tapped state doesn't matter.
|
||||||
final String[] tappablePermanents = {"Creature", "Land", "Artifact"};
|
final String[] tappablePermanents = {"Creature", "Land", "Artifact"};
|
||||||
untapList = CardLists.getValidCards(untapList, tappablePermanents, source.getController(), source, sa);
|
untapList = CardLists.getValidCards(untapList, tappablePermanents, source.getController(), source, sa);
|
||||||
@@ -260,7 +260,7 @@ public class UntapAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to just tap already tapped things
|
// try to just tap already tapped things
|
||||||
tapList = CardLists.filter(list, Presets.UNTAPPED);
|
tapList = CardLists.filter(list, CardPredicates.UNTAPPED);
|
||||||
|
|
||||||
if (untapTargetList(source, tgt, sa, mandatory, tapList)) {
|
if (untapTargetList(source, tgt, sa, mandatory, tapList)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -400,10 +400,10 @@ 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.NON_LANDS);
|
CardCollection inHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.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, CardPredicates.PERMANENTS);
|
||||||
|
|
||||||
CardCollection untappingCards = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), card -> {
|
CardCollection untappingCards = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), card -> {
|
||||||
boolean hasUntapLandLogic = false;
|
boolean hasUntapLandLogic = false;
|
||||||
@@ -427,7 +427,7 @@ public class UntapAi extends SpellAbilityAi {
|
|||||||
reduced.decreaseShard(ManaCostShard.GENERIC, untappingCards.size());
|
reduced.decreaseShard(ManaCostShard.GENERIC, untappingCards.size());
|
||||||
if (ComputerUtilMana.canPayManaCost(reduced, ab, ai, false)) {
|
if (ComputerUtilMana.canPayManaCost(reduced, ab, ai, false)) {
|
||||||
CardCollection manaLandsTapped = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield),
|
CardCollection manaLandsTapped = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield),
|
||||||
Presets.LANDS_PRODUCING_MANA, Presets.TAPPED);
|
CardPredicates.LANDS_PRODUCING_MANA, CardPredicates.TAPPED);
|
||||||
manaLandsTapped = CardLists.getValidCards(manaLandsTapped, sa.getParam("ValidTgts"), ai, source, null);
|
manaLandsTapped = CardLists.getValidCards(manaLandsTapped, sa.getParam("ValidTgts"), ai, source, null);
|
||||||
|
|
||||||
if (!manaLandsTapped.isEmpty()) {
|
if (!manaLandsTapped.isEmpty()) {
|
||||||
@@ -437,7 +437,7 @@ public class UntapAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
// pool one additional mana by tapping a land to try to ramp to something
|
// pool one additional mana by tapping a land to try to ramp to something
|
||||||
CardCollection manaLands = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield),
|
CardCollection manaLands = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield),
|
||||||
Presets.LANDS_PRODUCING_MANA, Presets.CAN_TAP);
|
CardPredicates.LANDS_PRODUCING_MANA, CardPredicates.CAN_TAP);
|
||||||
manaLands = CardLists.getValidCards(manaLands, sa.getParam("ValidTgts"), ai, source, null);
|
manaLands = CardLists.getValidCards(manaLands, sa.getParam("ValidTgts"), ai, source, null);
|
||||||
|
|
||||||
if (manaLands.isEmpty()) {
|
if (manaLands.isEmpty()) {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public class UntapAllAi extends SpellAbilityAi {
|
|||||||
&& source.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_END)) {
|
&& source.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_END)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
CardCollectionView list = CardLists.filter(aiPlayer.getGame().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.TAPPED);
|
CardCollectionView list = CardLists.filter(aiPlayer.getGame().getCardsIn(ZoneType.Battlefield), CardPredicates.TAPPED);
|
||||||
final String valid = sa.getParamOrDefault("ValidCards", "");
|
final String valid = sa.getParamOrDefault("ValidCards", "");
|
||||||
list = CardLists.getValidCards(list, valid, source.getController(), source, sa);
|
list = CardLists.getValidCards(list, valid, source.getController(), source, sa);
|
||||||
// don't untap if only opponent benefits
|
// don't untap if only opponent benefits
|
||||||
@@ -39,7 +39,7 @@ public class UntapAllAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
if (sa.hasParam("ValidCards")) {
|
if (sa.hasParam("ValidCards")) {
|
||||||
String valid = sa.getParam("ValidCards");
|
String valid = sa.getParam("ValidCards");
|
||||||
CardCollectionView list = CardLists.filter(aiPlayer.getGame().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.TAPPED);
|
CardCollectionView list = CardLists.filter(aiPlayer.getGame().getCardsIn(ZoneType.Battlefield), CardPredicates.TAPPED);
|
||||||
list = CardLists.getValidCards(list, valid, source.getController(), source, sa);
|
list = CardLists.getValidCards(list, valid, source.getController(), source, sa);
|
||||||
return mandatory || !list.isEmpty();
|
return mandatory || !list.isEmpty();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,21 +133,9 @@ public final class CardFacePredicates {
|
|||||||
return new ValidPredicate(val);
|
return new ValidPredicate(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Presets {
|
public static final Predicate<ICardFace> IS_BASIC_LAND = subject -> subject.getType().isBasicLand();
|
||||||
/** The Constant isBasicLand. */
|
public static final Predicate<ICardFace> IS_NONBASIC_LAND = subject -> subject.getType().isLand() && !subject.getType().isBasicLand();
|
||||||
public static final Predicate<ICardFace> IS_BASIC_LAND = subject -> subject.getType().isBasicLand();
|
public static final Predicate<ICardFace> IS_CREATURE = CardFacePredicates.coreType(true, CardType.CoreType.Creature);
|
||||||
|
public static final Predicate<ICardFace> IS_LEGENDARY = CardFacePredicates.superType(true, CardType.Supertype.Legendary);
|
||||||
/** The Constant isNonBasicLand. */
|
public static final Predicate<ICardFace> IS_NON_LAND = CardFacePredicates.coreType(false, CardType.CoreType.Land);
|
||||||
public static final Predicate<ICardFace> IS_NONBASIC_LAND = subject -> subject.getType().isLand() && !subject.getType().isBasicLand();
|
|
||||||
|
|
||||||
/** The Constant isCreature. */
|
|
||||||
public static final Predicate<ICardFace> IS_CREATURE = CardFacePredicates
|
|
||||||
.coreType(true, CardType.CoreType.Creature);
|
|
||||||
|
|
||||||
public static final Predicate<ICardFace> IS_LEGENDARY = CardFacePredicates
|
|
||||||
.superType(true, CardType.Supertype.Legendary);
|
|
||||||
|
|
||||||
public static final Predicate<ICardFace> IS_NON_LAND = CardFacePredicates
|
|
||||||
.coreType(false, CardType.CoreType.Land);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,13 +12,8 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
*/
|
*/
|
||||||
public final class CardRulesPredicates {
|
public final class CardRulesPredicates {
|
||||||
|
|
||||||
/** The Constant isKeptInAiDecks. */
|
|
||||||
public static final Predicate<CardRules> IS_KEPT_IN_AI_DECKS = card -> !card.getAiHints().getRemAIDecks();
|
public static final Predicate<CardRules> IS_KEPT_IN_AI_DECKS = card -> !card.getAiHints().getRemAIDecks();
|
||||||
|
|
||||||
/** The Constant isKeptInAiLimitedDecks. */
|
|
||||||
public static final Predicate<CardRules> IS_KEPT_IN_AI_LIMITED_DECKS = card -> !card.getAiHints().getRemAIDecks() && !card.getAiHints().getRemNonCommanderDecks();
|
public static final Predicate<CardRules> IS_KEPT_IN_AI_LIMITED_DECKS = card -> !card.getAiHints().getRemAIDecks() && !card.getAiHints().getRemNonCommanderDecks();
|
||||||
|
|
||||||
/** The Constant isKeptInRandomDecks. */
|
|
||||||
public static final Predicate<CardRules> IS_KEPT_IN_RANDOM_DECKS = card -> !card.getAiHints().getRemRandomDecks();
|
public static final Predicate<CardRules> IS_KEPT_IN_RANDOM_DECKS = card -> !card.getAiHints().getRemRandomDecks();
|
||||||
|
|
||||||
// Static builder methods - they choose concrete implementation by themselves
|
// Static builder methods - they choose concrete implementation by themselves
|
||||||
@@ -524,106 +519,50 @@ public final class CardRulesPredicates {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static final Predicate<CardRules> IS_CREATURE = CardRulesPredicates.coreType(true, CardType.CoreType.Creature);
|
||||||
* The Class Presets.
|
public static final Predicate<CardRules> IS_LEGENDARY = CardRulesPredicates.superType(true, CardType.Supertype.Legendary);
|
||||||
*/
|
public static final Predicate<CardRules> IS_ARTIFACT = CardRulesPredicates.coreType(true, CardType.CoreType.Artifact);
|
||||||
public static class Presets {
|
public static final Predicate<CardRules> IS_ATTRACTION = CardRulesPredicates.IS_ARTIFACT.and(CardRulesPredicates.subType("Attraction"));
|
||||||
|
public static final Predicate<CardRules> IS_EQUIPMENT = CardRulesPredicates.subType("Equipment");
|
||||||
/** The Constant isCreature. */
|
public static final Predicate<CardRules> IS_LAND = CardRulesPredicates.coreType(true, CardType.CoreType.Land);
|
||||||
public static final Predicate<CardRules> IS_CREATURE = CardRulesPredicates
|
public static final Predicate<CardRules> IS_BASIC_LAND = subject -> subject.getType().isBasicLand();
|
||||||
.coreType(true, CardType.CoreType.Creature);
|
public static final Predicate<CardRules> NOT_BASIC_LAND = subject -> !subject.getType().isBasicLand();
|
||||||
|
/** Matches only Plains, Island, Swamp, Mountain, or Forest. */
|
||||||
public static final Predicate<CardRules> IS_LEGENDARY = CardRulesPredicates
|
public static final Predicate<CardRules> IS_TRUE_BASIC_LAND = subject -> !subject.getName().equals("Wastes")&&subject.getType().isBasicLand();
|
||||||
.superType(true, CardType.Supertype.Legendary);
|
/** 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 isArtifact. */
|
public static final Predicate<CardRules> IS_NONBASIC_LAND = subject -> subject.getType().isLand() && !subject.getType().isBasicLand();
|
||||||
public static final Predicate<CardRules> IS_ARTIFACT = CardRulesPredicates
|
public static final Predicate<CardRules> CAN_BE_COMMANDER = CardRules::canBeCommander;
|
||||||
.coreType(true, CardType.CoreType.Artifact);
|
public static final Predicate<CardRules> CAN_BE_PARTNER_COMMANDER = CardRules::canBePartnerCommander;
|
||||||
|
public static final Predicate<CardRules> CAN_BE_OATHBREAKER = CardRules::canBeOathbreaker;
|
||||||
/** The Constant isEquipment. */
|
public static final Predicate<CardRules> CAN_BE_SIGNATURE_SPELL = CardRules::canBeSignatureSpell;
|
||||||
public static final Predicate<CardRules> IS_EQUIPMENT = CardRulesPredicates
|
public static final Predicate<CardRules> IS_PLANESWALKER = CardRulesPredicates.coreType(true, CardType.CoreType.Planeswalker);
|
||||||
.subType("Equipment");
|
public static final Predicate<CardRules> CAN_BE_TINY_LEADERS_COMMANDER = CardRulesPredicates.IS_LEGENDARY.and(CardRulesPredicates.IS_CREATURE.or(CardRulesPredicates.IS_PLANESWALKER));
|
||||||
|
public static final Predicate<CardRules> CAN_BE_BRAWL_COMMANDER = CardRulesPredicates.IS_LEGENDARY.and(CardRulesPredicates.IS_CREATURE.or(CardRulesPredicates.IS_PLANESWALKER));
|
||||||
/** The Constant isLand. */
|
public static final Predicate<CardRules> IS_BATTLE = CardRulesPredicates.coreType(true, CardType.CoreType.Battle);
|
||||||
public static final Predicate<CardRules> IS_LAND = CardRulesPredicates.coreType(true, CardType.CoreType.Land);
|
public static final Predicate<CardRules> IS_INSTANT = CardRulesPredicates.coreType(true, CardType.CoreType.Instant);
|
||||||
|
public static final Predicate<CardRules> IS_SORCERY = CardRulesPredicates.coreType(true, CardType.CoreType.Sorcery);
|
||||||
/** The Constant isBasicLand. */
|
public static final Predicate<CardRules> IS_ENCHANTMENT = CardRulesPredicates.coreType(true, CardType.CoreType.Enchantment);
|
||||||
public static final Predicate<CardRules> IS_BASIC_LAND = subject -> subject.getType().isBasicLand();
|
public static final Predicate<CardRules> IS_NON_CREATURE_SPELL =
|
||||||
public static final Predicate<CardRules> NOT_BASIC_LAND = subject -> !subject.getType().isBasicLand();
|
CardRulesPredicates.IS_SORCERY
|
||||||
|
.or(CardRulesPredicates.IS_INSTANT)
|
||||||
/** Matches only Plains, Island, Swamp, Mountain, or Forest. */
|
.or(CardRulesPredicates.IS_PLANESWALKER)
|
||||||
public static final Predicate<CardRules> IS_BASIC_LAND_NOT_WASTES = subject -> !subject.getName().equals("Wastes")&&subject.getType().isBasicLand();
|
.or(CardRulesPredicates.IS_ENCHANTMENT) //TODO: Battles? Is testing these one by one really the best way to check "non-creature"?
|
||||||
/** Matches any card except Plains, Island, Swamp, Mountain, or Forest. */
|
.or(CardRulesPredicates.IS_ARTIFACT.and(CardRulesPredicates.IS_CREATURE.negate()));
|
||||||
public static final Predicate<CardRules> NOT_TRUE_BASIC_LAND = subject -> !subject.getType().isBasicLand() || subject.getName().equals("Wastes");
|
public static final Predicate<CardRules> IS_PLANE = CardRulesPredicates.coreType(true, CardType.CoreType.Plane);
|
||||||
|
public static final Predicate<CardRules> IS_PHENOMENON = CardRulesPredicates.coreType(true, CardType.CoreType.Phenomenon);
|
||||||
/** The Constant isNonBasicLand. */
|
public static final Predicate<CardRules> IS_PLANE_OR_PHENOMENON = IS_PLANE.or(IS_PHENOMENON);
|
||||||
public static final Predicate<CardRules> IS_NONBASIC_LAND = subject -> subject.getType().isLand() && !subject.getType().isBasicLand();
|
public static final Predicate<CardRules> IS_SCHEME = CardRulesPredicates.coreType(true, CardType.CoreType.Scheme);
|
||||||
|
public static final Predicate<CardRules> IS_VANGUARD = CardRulesPredicates.coreType(true, CardType.CoreType.Vanguard);
|
||||||
public static final Predicate<CardRules> CAN_BE_COMMANDER = CardRules::canBeCommander;
|
public static final Predicate<CardRules> IS_CONSPIRACY = CardRulesPredicates.coreType(true, CardType.CoreType.Conspiracy);
|
||||||
public static final Predicate<CardRules> CAN_BE_PARTNER_COMMANDER = CardRules::canBePartnerCommander;
|
public static final Predicate<CardRules> IS_DUNGEON = CardRulesPredicates.coreType(true, CardType.CoreType.Dungeon);
|
||||||
|
public static final Predicate<CardRules> IS_NON_LAND = CardRulesPredicates.coreType(false, CardType.CoreType.Land);
|
||||||
public static final Predicate<CardRules> CAN_BE_OATHBREAKER = CardRules::canBeOathbreaker;
|
public static final Predicate<CardRules> IS_WHITE = CardRulesPredicates.isColor(MagicColor.WHITE);
|
||||||
public static final Predicate<CardRules> CAN_BE_SIGNATURE_SPELL = CardRules::canBeSignatureSpell;
|
public static final Predicate<CardRules> IS_BLUE = CardRulesPredicates.isColor(MagicColor.BLUE);
|
||||||
|
public static final Predicate<CardRules> IS_BLACK = CardRulesPredicates.isColor(MagicColor.BLACK);
|
||||||
public static final Predicate<CardRules> IS_PLANESWALKER = CardRulesPredicates.coreType(true, CardType.CoreType.Planeswalker);
|
public static final Predicate<CardRules> IS_RED = CardRulesPredicates.isColor(MagicColor.RED);
|
||||||
public static final Predicate<CardRules> IS_BATTLE = CardRulesPredicates.coreType(true, CardType.CoreType.Battle);
|
public static final Predicate<CardRules> IS_GREEN = CardRulesPredicates.isColor(MagicColor.GREEN);
|
||||||
public static final Predicate<CardRules> IS_INSTANT = CardRulesPredicates.coreType(true, CardType.CoreType.Instant);
|
public static final Predicate<CardRules> IS_COLORLESS = CardRulesPredicates.hasCntColors((byte) 0);
|
||||||
public static final Predicate<CardRules> IS_SORCERY = CardRulesPredicates.coreType(true, CardType.CoreType.Sorcery);
|
public static final Predicate<CardRules> IS_MULTICOLOR = CardRulesPredicates.hasAtLeastCntColors((byte) 2);
|
||||||
public static final Predicate<CardRules> IS_ENCHANTMENT = CardRulesPredicates.coreType(true, CardType.CoreType.Enchantment);
|
public static final Predicate<CardRules> IS_MONOCOLOR = CardRulesPredicates.hasCntColors((byte) 1);
|
||||||
public static final Predicate<CardRules> IS_PLANE = CardRulesPredicates.coreType(true, CardType.CoreType.Plane);
|
|
||||||
public static final Predicate<CardRules> IS_PHENOMENON = CardRulesPredicates.coreType(true, CardType.CoreType.Phenomenon);
|
|
||||||
public static final Predicate<CardRules> IS_PLANE_OR_PHENOMENON = IS_PLANE.or(IS_PHENOMENON);
|
|
||||||
public static final Predicate<CardRules> IS_SCHEME = CardRulesPredicates.coreType(true, CardType.CoreType.Scheme);
|
|
||||||
public static final Predicate<CardRules> IS_VANGUARD = CardRulesPredicates.coreType(true, CardType.CoreType.Vanguard);
|
|
||||||
public static final Predicate<CardRules> IS_CONSPIRACY = CardRulesPredicates.coreType(true, CardType.CoreType.Conspiracy);
|
|
||||||
public static final Predicate<CardRules> IS_DUNGEON = CardRulesPredicates.coreType(true, CardType.CoreType.Dungeon);
|
|
||||||
public static final Predicate<CardRules> IS_ATTRACTION = Presets.IS_ARTIFACT.and(CardRulesPredicates.subType("Attraction"));
|
|
||||||
|
|
||||||
public static final Predicate<CardRules> IS_NON_LAND = CardRulesPredicates.coreType(false, CardType.CoreType.Land);
|
|
||||||
public static final Predicate<CardRules> CAN_BE_BRAWL_COMMANDER = Presets.IS_LEGENDARY.and(Presets.IS_CREATURE.or(Presets.IS_PLANESWALKER));
|
|
||||||
public static final Predicate<CardRules> CAN_BE_TINY_LEADERS_COMMANDER = Presets.IS_LEGENDARY.and(Presets.IS_CREATURE.or(Presets.IS_PLANESWALKER));
|
|
||||||
|
|
||||||
/** The Constant IS_NON_CREATURE_SPELL. **/
|
|
||||||
public static final Predicate<CardRules> IS_NON_CREATURE_SPELL =
|
|
||||||
Presets.IS_SORCERY
|
|
||||||
.or(Presets.IS_INSTANT)
|
|
||||||
.or(Presets.IS_PLANESWALKER)
|
|
||||||
.or(Presets.IS_ENCHANTMENT) //TODO: Battles? Is testing these one by one really the best way to check "non-creature"?
|
|
||||||
.or(Presets.IS_ARTIFACT.and(Presets.IS_CREATURE.negate()));
|
|
||||||
|
|
||||||
/** The Constant isWhite. */
|
|
||||||
public static final Predicate<CardRules> IS_WHITE = CardRulesPredicates.isColor(MagicColor.WHITE);
|
|
||||||
|
|
||||||
/** The Constant isBlue. */
|
|
||||||
public static final Predicate<CardRules> IS_BLUE = CardRulesPredicates.isColor(MagicColor.BLUE);
|
|
||||||
|
|
||||||
/** The Constant isBlack. */
|
|
||||||
public static final Predicate<CardRules> IS_BLACK = CardRulesPredicates.isColor(MagicColor.BLACK);
|
|
||||||
|
|
||||||
/** The Constant isRed. */
|
|
||||||
public static final Predicate<CardRules> IS_RED = CardRulesPredicates.isColor(MagicColor.RED);
|
|
||||||
|
|
||||||
/** The Constant isGreen. */
|
|
||||||
public static final Predicate<CardRules> IS_GREEN = CardRulesPredicates.isColor(MagicColor.GREEN);
|
|
||||||
|
|
||||||
/** The Constant isColorless. */
|
|
||||||
public static final Predicate<CardRules> IS_COLORLESS = CardRulesPredicates.hasCntColors((byte) 0);
|
|
||||||
|
|
||||||
/** The Constant isMulticolor. */
|
|
||||||
public static final Predicate<CardRules> IS_MULTICOLOR = CardRulesPredicates.hasAtLeastCntColors((byte) 2);
|
|
||||||
|
|
||||||
/** The Constant isMonocolor. */
|
|
||||||
public static final Predicate<CardRules> IS_MONOCOLOR = CardRulesPredicates.hasCntColors((byte) 1);
|
|
||||||
|
|
||||||
/** The Constant colors. */
|
|
||||||
public static final List<Predicate<CardRules>> COLORS = new ArrayList<>();
|
|
||||||
static {
|
|
||||||
Presets.COLORS.add(Presets.IS_WHITE);
|
|
||||||
Presets.COLORS.add(Presets.IS_BLUE);
|
|
||||||
Presets.COLORS.add(Presets.IS_BLACK);
|
|
||||||
Presets.COLORS.add(Presets.IS_RED);
|
|
||||||
Presets.COLORS.add(Presets.IS_GREEN);
|
|
||||||
Presets.COLORS.add(Presets.IS_COLORLESS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ public class DeckHints {
|
|||||||
case COLOR:
|
case COLOR:
|
||||||
ColorSet cc = ColorSet.fromNames(p);
|
ColorSet cc = ColorSet.fromNames(p);
|
||||||
if (cc.isColorless()) {
|
if (cc.isColorless()) {
|
||||||
Iterables.addAll(cards, getMatchingItems(cardList, CardRulesPredicates.Presets.IS_COLORLESS, PaperCard::getRules));
|
Iterables.addAll(cards, getMatchingItems(cardList, CardRulesPredicates.IS_COLORLESS, PaperCard::getRules));
|
||||||
} else {
|
} else {
|
||||||
Iterables.addAll(cards, getMatchingItems(cardList, CardRulesPredicates.isColor(cc.getColor()), PaperCard::getRules));
|
Iterables.addAll(cards, getMatchingItems(cardList, CardRulesPredicates.isColor(cc.getColor()), PaperCard::getRules));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import forge.item.IPaperCard;
|
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
|
import forge.item.PaperCardPredicates;
|
||||||
import forge.util.Iterables;
|
import forge.util.Iterables;
|
||||||
|
|
||||||
public class DeckGenPool implements IDeckGenPool {
|
public class DeckGenPool implements IDeckGenPool {
|
||||||
@@ -37,7 +37,7 @@ public class DeckGenPool implements IDeckGenPool {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PaperCard getCard(String name, String edition) {
|
public PaperCard getCard(String name, String edition) {
|
||||||
Predicate<PaperCard> filter = IPaperCard.Predicates.printedInSet(edition).and(IPaperCard.Predicates.name(name));
|
Predicate<PaperCard> filter = PaperCardPredicates.printedInSet(edition).and(PaperCardPredicates.name(name));
|
||||||
Iterable<PaperCard> editionCards=Iterables.filter(cards.values(), filter);
|
Iterable<PaperCard> editionCards=Iterables.filter(cards.values(), filter);
|
||||||
if (editionCards.iterator().hasNext()){
|
if (editionCards.iterator().hasNext()){
|
||||||
return editionCards.iterator().next();
|
return editionCards.iterator().next();
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ import forge.card.*;
|
|||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.deck.CardPool;
|
import forge.deck.CardPool;
|
||||||
import forge.deck.DeckFormat;
|
import forge.deck.DeckFormat;
|
||||||
import forge.item.IPaperCard;
|
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
|
import forge.item.PaperCardPredicates;
|
||||||
import forge.util.*;
|
import forge.util.*;
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
|
||||||
@@ -87,12 +87,12 @@ public abstract class DeckGeneratorBase {
|
|||||||
final Iterable<PaperCard> cards = selectCardsOfMatchingColorForPlayer(forAi);
|
final Iterable<PaperCard> cards = selectCardsOfMatchingColorForPlayer(forAi);
|
||||||
// build subsets based on type
|
// build subsets based on type
|
||||||
|
|
||||||
final Iterable<PaperCard> creatures = Iterables.filter(cards, Predicates.compose(CardRulesPredicates.Presets.IS_CREATURE, PaperCard::getRules));
|
final Iterable<PaperCard> creatures = Iterables.filter(cards, Predicates.compose(CardRulesPredicates.IS_CREATURE, PaperCard::getRules));
|
||||||
final int creatCnt = (int) Math.ceil(getCreaturePercentage() * size);
|
final int creatCnt = (int) Math.ceil(getCreaturePercentage() * size);
|
||||||
trace.append("Creatures to add:").append(creatCnt).append("\n");
|
trace.append("Creatures to add:").append(creatCnt).append("\n");
|
||||||
addCmcAdjusted(creatures, creatCnt, cmcLevels);
|
addCmcAdjusted(creatures, creatCnt, cmcLevels);
|
||||||
|
|
||||||
Predicate<PaperCard> preSpells = Predicates.compose(CardRulesPredicates.Presets.IS_NON_CREATURE_SPELL, PaperCard::getRules);
|
Predicate<PaperCard> preSpells = Predicates.compose(CardRulesPredicates.IS_NON_CREATURE_SPELL, PaperCard::getRules);
|
||||||
final Iterable<PaperCard> spells = Iterables.filter(cards, preSpells);
|
final Iterable<PaperCard> spells = Iterables.filter(cards, preSpells);
|
||||||
final int spellCnt = (int) Math.ceil(getSpellPercentage() * size);
|
final int spellCnt = (int) Math.ceil(getSpellPercentage() * size);
|
||||||
trace.append("Spells to add:").append(spellCnt).append("\n");
|
trace.append("Spells to add:").append(spellCnt).append("\n");
|
||||||
@@ -108,10 +108,10 @@ public abstract class DeckGeneratorBase {
|
|||||||
protected boolean setBasicLandPool(String edition){
|
protected boolean setBasicLandPool(String edition){
|
||||||
Predicate<PaperCard> isSetBasicLand;
|
Predicate<PaperCard> isSetBasicLand;
|
||||||
if (edition !=null){
|
if (edition !=null){
|
||||||
isSetBasicLand = IPaperCard.Predicates.printedInSet(edition)
|
isSetBasicLand = PaperCardPredicates.printedInSet(edition)
|
||||||
.and(Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard::getRules));
|
.and(Predicates.compose(CardRulesPredicates.IS_BASIC_LAND, PaperCard::getRules));
|
||||||
}else{
|
}else{
|
||||||
isSetBasicLand = Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard::getRules);
|
isSetBasicLand = Predicates.compose(CardRulesPredicates.IS_BASIC_LAND, PaperCard::getRules);
|
||||||
}
|
}
|
||||||
|
|
||||||
landPool = new DeckGenPool(StaticData.instance().getCommonCards().getAllCards(isSetBasicLand));
|
landPool = new DeckGenPool(StaticData.instance().getCommonCards().getAllCards(isSetBasicLand));
|
||||||
@@ -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.NOT_BASIC_LAND, PaperCard::getRules);
|
Predicate<PaperCard> exceptBasicLand = Predicates.compose(CardRulesPredicates.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.NOT_BASIC_LAND;
|
Predicate<CardRules> exceptBasicLand = CardRulesPredicates.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])\\}",
|
||||||
|
|||||||
@@ -24,211 +24,6 @@ public interface IPaperCard extends InventoryItem, Serializable {
|
|||||||
String NO_ARTIST_NAME = "";
|
String NO_ARTIST_NAME = "";
|
||||||
String NO_FUNCTIONAL_VARIANT = "";
|
String NO_FUNCTIONAL_VARIANT = "";
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of filters based on CardPrinted values.
|
|
||||||
*/
|
|
||||||
abstract class Predicates {
|
|
||||||
|
|
||||||
public static Predicate<PaperCard> rarity(final boolean isEqual, final CardRarity value) {
|
|
||||||
return new PredicateRarity(value, isEqual);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Predicate<PaperCard> color(final boolean isEqual, final boolean noColor, final byte value) {
|
|
||||||
return new PredicateColor(value, noColor, isEqual);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Predicate<PaperCard> printedInSets(final String[] sets) {
|
|
||||||
return printedInSets(Lists.newArrayList(sets), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Predicate<PaperCard> printedInSets(final List<String> value, final boolean shouldContain) {
|
|
||||||
if ((value == null) || value.isEmpty()) {
|
|
||||||
return x -> true;
|
|
||||||
}
|
|
||||||
return new PredicateSets(value, shouldContain);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Predicate<PaperCard> printedInSet(final String value) {
|
|
||||||
if (StringUtils.isEmpty(value)) {
|
|
||||||
return x -> true;
|
|
||||||
}
|
|
||||||
return new PredicateSets(Lists.newArrayList(value), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Predicate<PaperCard> name(final String what) {
|
|
||||||
return new PredicateName(PredicateString.StringOp.EQUALS_IC, what);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Predicate<PaperCard> name(final PredicateString.StringOp op, final String what) {
|
|
||||||
return new PredicateName(op, what);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Predicate<PaperCard> names(final List<String> what) {
|
|
||||||
return new PredicateNames(what);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PredicateCards cards(final List<PaperCard> what) { return new PredicateCards(what); }
|
|
||||||
|
|
||||||
private static final class PredicateColor implements Predicate<PaperCard> {
|
|
||||||
|
|
||||||
private final byte operand;
|
|
||||||
private final boolean noColor;
|
|
||||||
private final boolean shouldBeEqual;
|
|
||||||
|
|
||||||
private PredicateColor(final byte color, final boolean noColor, final boolean wantEqual) {
|
|
||||||
this.operand = color;
|
|
||||||
this.noColor = noColor;
|
|
||||||
this.shouldBeEqual = wantEqual;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(final PaperCard card) {
|
|
||||||
boolean colorFound = false;
|
|
||||||
if (noColor) {
|
|
||||||
return card.getRules().getColor().isColorless() == shouldBeEqual;
|
|
||||||
}
|
|
||||||
for (final byte color : card.getRules().getColor()) {
|
|
||||||
if (color == operand) {
|
|
||||||
colorFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (card.getRules().getType().hasType(CoreType.Land)) {
|
|
||||||
for (final byte color : card.getRules().getColorIdentity()) {
|
|
||||||
if (color == operand) {
|
|
||||||
colorFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return colorFound == shouldBeEqual;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class PredicateRarity implements Predicate<PaperCard> {
|
|
||||||
private final CardRarity operand;
|
|
||||||
private final boolean shouldBeEqual;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(final PaperCard card) {
|
|
||||||
return (card.getRarity() == this.operand) == this.shouldBeEqual;
|
|
||||||
}
|
|
||||||
|
|
||||||
private PredicateRarity(final CardRarity type, final boolean wantEqual) {
|
|
||||||
this.operand = type;
|
|
||||||
this.shouldBeEqual = wantEqual;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class PredicateSets implements Predicate<PaperCard> {
|
|
||||||
private final Set<String> sets;
|
|
||||||
private final boolean mustContain;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(final PaperCard card) {
|
|
||||||
return this.sets.contains(card.getEdition()) == this.mustContain;
|
|
||||||
}
|
|
||||||
|
|
||||||
private PredicateSets(final List<String> wantSets, final boolean shouldContain) {
|
|
||||||
this.sets = new HashSet<>(wantSets);
|
|
||||||
this.mustContain = shouldContain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class PredicateName extends PredicateString<PaperCard> {
|
|
||||||
private final String operand;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(final PaperCard card) {
|
|
||||||
return this.op(card.getName(), this.operand);
|
|
||||||
}
|
|
||||||
|
|
||||||
private PredicateName(final PredicateString.StringOp operator, final String operand) {
|
|
||||||
super(operator);
|
|
||||||
this.operand = operand;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class PredicateNames extends PredicateString<PaperCard> {
|
|
||||||
private final List<String> operand;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(final PaperCard card) {
|
|
||||||
final String cardName = card.getName();
|
|
||||||
for (final String element : this.operand) {
|
|
||||||
if (this.op(cardName, element)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private PredicateNames(final List<String> operand) {
|
|
||||||
super(StringOp.EQUALS);
|
|
||||||
this.operand = operand;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class PredicateCards extends PredicateCard<PaperCard> {
|
|
||||||
private final List<PaperCard> operand;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(final PaperCard card) {
|
|
||||||
for (final PaperCard element : this.operand) {
|
|
||||||
if (this.op(card, element)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private PredicateCards(final List<PaperCard> operand) {
|
|
||||||
super(StringOp.EQUALS);
|
|
||||||
this.operand = operand;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pre-built predicates are stored here to allow their re-usage and
|
|
||||||
* easier access from code.
|
|
||||||
*/
|
|
||||||
public abstract static class Presets {
|
|
||||||
// Think twice before using these, since rarity is a prop of printed
|
|
||||||
// card.
|
|
||||||
/** The Constant isCommon. */
|
|
||||||
public static final Predicate<PaperCard> IS_COMMON = Predicates.rarity(true, CardRarity.Common);
|
|
||||||
|
|
||||||
/** The Constant isUncommon. */
|
|
||||||
public static final Predicate<PaperCard> IS_UNCOMMON = Predicates.rarity(true, CardRarity.Uncommon);
|
|
||||||
|
|
||||||
/** The Constant isRare. */
|
|
||||||
public static final Predicate<PaperCard> IS_RARE = Predicates.rarity(true, CardRarity.Rare);
|
|
||||||
|
|
||||||
/** The Constant isMythicRare. */
|
|
||||||
public static final Predicate<PaperCard> IS_MYTHIC_RARE = Predicates.rarity(true, CardRarity.MythicRare);
|
|
||||||
|
|
||||||
/** The Constant isRareOrMythic. */
|
|
||||||
public static final Predicate<PaperCard> IS_RARE_OR_MYTHIC = Presets.IS_RARE.or(Presets.IS_MYTHIC_RARE);
|
|
||||||
|
|
||||||
/** The Constant isSpecial. */
|
|
||||||
public static final Predicate<PaperCard> IS_SPECIAL = Predicates.rarity(true, CardRarity.Special);
|
|
||||||
|
|
||||||
/** The Constant exceptLands. */
|
|
||||||
public static final Predicate<PaperCard> IS_BASIC_LAND = Predicates.rarity(true, CardRarity.BasicLand);
|
|
||||||
|
|
||||||
public static final Predicate<PaperCard> IS_BLACK = Predicates.color(true, false, MagicColor.BLACK);
|
|
||||||
public static final Predicate<PaperCard> IS_BLUE = Predicates.color(true, false, MagicColor.BLUE);
|
|
||||||
public static final Predicate<PaperCard> IS_GREEN = Predicates.color(true, false, MagicColor.GREEN);
|
|
||||||
public static final Predicate<PaperCard> IS_RED = Predicates.color(true, false, MagicColor.RED);
|
|
||||||
public static final Predicate<PaperCard> IS_WHITE = Predicates.color(true, false, MagicColor.WHITE);
|
|
||||||
public static final Predicate<PaperCard> IS_COLORLESS = Predicates.color(true, true, MagicColor.COLORLESS);
|
|
||||||
|
|
||||||
public static final Predicate<PaperCard> IS_UNREBALANCED = PaperCard::isUnRebalanced;
|
|
||||||
public static final Predicate<PaperCard> IS_REBALANCED = PaperCard::isRebalanced;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
String getName();
|
String getName();
|
||||||
String getEdition();
|
String getEdition();
|
||||||
|
|||||||
@@ -10,34 +10,21 @@ public abstract class ItemPredicate {
|
|||||||
// Static builder methods - they choose concrete implementation by themselves
|
// Static builder methods - they choose concrete implementation by themselves
|
||||||
|
|
||||||
public static final Predicate<Object> IsBoosterPack = BoosterPack.class::isInstance;
|
public static final Predicate<Object> IsBoosterPack = BoosterPack.class::isInstance;
|
||||||
|
/**
|
||||||
|
* Checks that the inventory item is a Prebuilt Deck.
|
||||||
|
*/
|
||||||
public static final Predicate<Object> IsPrebuiltDeck = PreconDeck.class::isInstance;
|
public static final Predicate<Object> IsPrebuiltDeck = PreconDeck.class::isInstance;
|
||||||
public static final Predicate<Object> IsFatPack = FatPack.class::isInstance;
|
public static final Predicate<Object> IsFatPack = FatPack.class::isInstance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that the inventory item is a Tournament Pack.
|
* Checks that the inventory item is a Tournament Pack.
|
||||||
*
|
|
||||||
* @return the predicate
|
|
||||||
*/
|
*/
|
||||||
public static final Predicate<Object> IsTournamentPack = card -> card instanceof TournamentPack && !((TournamentPack) card).isStarterDeck();
|
public static final Predicate<Object> IsTournamentPack = card -> card instanceof TournamentPack && !((TournamentPack) card).isStarterDeck();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that the inventory item is a Starter Deck.
|
* Checks that the inventory item is a Starter Deck.
|
||||||
*
|
|
||||||
* @return the predicate
|
|
||||||
*/
|
*/
|
||||||
public static final Predicate<Object> IsStarterDeck = card -> card instanceof TournamentPack && ((TournamentPack) card).isStarterDeck();
|
public static final Predicate<Object> IsStarterDeck = card -> card instanceof TournamentPack && ((TournamentPack) card).isStarterDeck();
|
||||||
|
|
||||||
/**
|
public static final Predicate<Object> IS_PACK_OR_DECK = IsBoosterPack.or(IsFatPack).or(IsTournamentPack).or(IsStarterDeck).or(IsPrebuiltDeck);
|
||||||
* Checks that the inventory item is a Prebuilt Deck.
|
|
||||||
*
|
|
||||||
* @return the predicate
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Class Presets.
|
|
||||||
*/
|
|
||||||
public static class Presets {
|
|
||||||
/** The Item IsPack. */
|
|
||||||
public static final Predicate<Object> IS_PACK_OR_DECK = IsBoosterPack.or(IsFatPack).or(IsTournamentPack).or(IsStarterDeck).or(IsPrebuiltDeck);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
197
forge-core/src/main/java/forge/item/PaperCardPredicates.java
Normal file
197
forge-core/src/main/java/forge/item/PaperCardPredicates.java
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
package forge.item;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import forge.card.CardRarity;
|
||||||
|
import forge.card.CardType;
|
||||||
|
import forge.card.MagicColor;
|
||||||
|
import forge.util.PredicateCard;
|
||||||
|
import forge.util.PredicateString;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters based on PaperCard values.
|
||||||
|
*/
|
||||||
|
public abstract class PaperCardPredicates {
|
||||||
|
public static Predicate<PaperCard> rarity(final boolean isEqual, final CardRarity value) {
|
||||||
|
return new PredicateRarity(value, isEqual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Predicate<PaperCard> color(final boolean isEqual, final boolean noColor, final byte value) {
|
||||||
|
return new PredicateColor(value, noColor, isEqual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Predicate<PaperCard> printedInSets(final String[] sets) {
|
||||||
|
return printedInSets(Lists.newArrayList(sets), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Predicate<PaperCard> printedInSets(final List<String> value, final boolean shouldContain) {
|
||||||
|
if ((value == null) || value.isEmpty()) {
|
||||||
|
return x -> true;
|
||||||
|
}
|
||||||
|
return new PredicateSets(value, shouldContain);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Predicate<PaperCard> printedInSet(final String value) {
|
||||||
|
if (StringUtils.isEmpty(value)) {
|
||||||
|
return x -> true;
|
||||||
|
}
|
||||||
|
return new PredicateSets(Lists.newArrayList(value), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Predicate<PaperCard> name(final String what) {
|
||||||
|
return new PredicateName(PredicateString.StringOp.EQUALS_IC, what);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Predicate<PaperCard> name(final PredicateString.StringOp op, final String what) {
|
||||||
|
return new PredicateName(op, what);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Predicate<PaperCard> names(final List<String> what) {
|
||||||
|
return new PredicateNames(what);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Predicate<PaperCard> cards(final List<PaperCard> what) {
|
||||||
|
return new PredicateCards(what);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PredicateColor implements Predicate<PaperCard> {
|
||||||
|
|
||||||
|
private final byte operand;
|
||||||
|
private final boolean noColor;
|
||||||
|
private final boolean shouldBeEqual;
|
||||||
|
|
||||||
|
private PredicateColor(final byte color, final boolean noColor, final boolean wantEqual) {
|
||||||
|
this.operand = color;
|
||||||
|
this.noColor = noColor;
|
||||||
|
this.shouldBeEqual = wantEqual;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(final PaperCard card) {
|
||||||
|
boolean colorFound = false;
|
||||||
|
if (noColor) {
|
||||||
|
return card.getRules().getColor().isColorless() == shouldBeEqual;
|
||||||
|
}
|
||||||
|
for (final byte color : card.getRules().getColor()) {
|
||||||
|
if (color == operand) {
|
||||||
|
colorFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (card.getRules().getType().hasType(CardType.CoreType.Land)) {
|
||||||
|
for (final byte color : card.getRules().getColorIdentity()) {
|
||||||
|
if (color == operand) {
|
||||||
|
colorFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return colorFound == shouldBeEqual;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PredicateRarity implements Predicate<PaperCard> {
|
||||||
|
private final CardRarity operand;
|
||||||
|
private final boolean shouldBeEqual;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(final PaperCard card) {
|
||||||
|
return (card.getRarity() == this.operand) == this.shouldBeEqual;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PredicateRarity(final CardRarity type, final boolean wantEqual) {
|
||||||
|
this.operand = type;
|
||||||
|
this.shouldBeEqual = wantEqual;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PredicateSets implements Predicate<PaperCard> {
|
||||||
|
private final Set<String> sets;
|
||||||
|
private final boolean mustContain;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(final PaperCard card) {
|
||||||
|
return this.sets.contains(card.getEdition()) == this.mustContain;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PredicateSets(final List<String> wantSets, final boolean shouldContain) {
|
||||||
|
this.sets = new HashSet<>(wantSets);
|
||||||
|
this.mustContain = shouldContain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PredicateName extends PredicateString<PaperCard> {
|
||||||
|
private final String operand;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(final PaperCard card) {
|
||||||
|
return this.op(card.getName(), this.operand);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PredicateName(final StringOp operator, final String operand) {
|
||||||
|
super(operator);
|
||||||
|
this.operand = operand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PredicateNames extends PredicateString<PaperCard> {
|
||||||
|
private final List<String> operand;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(final PaperCard card) {
|
||||||
|
final String cardName = card.getName();
|
||||||
|
for (final String element : this.operand) {
|
||||||
|
if (this.op(cardName, element)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PredicateNames(final List<String> operand) {
|
||||||
|
super(StringOp.EQUALS);
|
||||||
|
this.operand = operand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PredicateCards extends PredicateCard<PaperCard> {
|
||||||
|
private final List<PaperCard> operand;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(final PaperCard card) {
|
||||||
|
for (final PaperCard element : this.operand) {
|
||||||
|
if (this.op(card, element)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PredicateCards(final List<PaperCard> operand) {
|
||||||
|
super(StringOp.EQUALS);
|
||||||
|
this.operand = operand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Predicate<PaperCard> IS_COMMON = PaperCardPredicates.rarity(true, CardRarity.Common);
|
||||||
|
public static final Predicate<PaperCard> IS_UNCOMMON = PaperCardPredicates.rarity(true, CardRarity.Uncommon);
|
||||||
|
public static final Predicate<PaperCard> IS_RARE = PaperCardPredicates.rarity(true, CardRarity.Rare);
|
||||||
|
public static final Predicate<PaperCard> IS_MYTHIC_RARE = PaperCardPredicates.rarity(true, CardRarity.MythicRare);
|
||||||
|
public static final Predicate<PaperCard> IS_RARE_OR_MYTHIC = PaperCardPredicates.IS_RARE.or(PaperCardPredicates.IS_MYTHIC_RARE);
|
||||||
|
public static final Predicate<PaperCard> IS_SPECIAL = PaperCardPredicates.rarity(true, CardRarity.Special);
|
||||||
|
public static final Predicate<PaperCard> IS_BASIC_LAND = PaperCardPredicates.rarity(true, CardRarity.BasicLand);
|
||||||
|
public static final Predicate<PaperCard> IS_BLACK = PaperCardPredicates.color(true, false, MagicColor.BLACK);
|
||||||
|
public static final Predicate<PaperCard> IS_BLUE = PaperCardPredicates.color(true, false, MagicColor.BLUE);
|
||||||
|
public static final Predicate<PaperCard> IS_GREEN = PaperCardPredicates.color(true, false, MagicColor.GREEN);
|
||||||
|
public static final Predicate<PaperCard> IS_RED = PaperCardPredicates.color(true, false, MagicColor.RED);
|
||||||
|
public static final Predicate<PaperCard> IS_WHITE = PaperCardPredicates.color(true, false, MagicColor.WHITE);
|
||||||
|
public static final Predicate<PaperCard> IS_COLORLESS = PaperCardPredicates.color(true, true, MagicColor.COLORLESS);
|
||||||
|
public static final Predicate<PaperCard> IS_UNREBALANCED = PaperCard::isUnRebalanced;
|
||||||
|
public static final Predicate<PaperCard> IS_REBALANCED = PaperCard::isRebalanced;
|
||||||
|
}
|
||||||
@@ -113,8 +113,8 @@ public abstract class SealedProduct implements InventoryItemFromSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected List<PaperCard> getRandomBasicLands(final String setCode, final int count) {
|
protected List<PaperCard> getRandomBasicLands(final String setCode, final int count) {
|
||||||
Predicate<PaperCard> cardsRule = IPaperCard.Predicates.printedInSet(setCode)
|
Predicate<PaperCard> cardsRule = PaperCardPredicates.printedInSet(setCode)
|
||||||
.and(Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard::getRules));
|
.and(Predicates.compose(CardRulesPredicates.IS_BASIC_LAND, PaperCard::getRules));
|
||||||
return Aggregates.random(Iterables.filter(StaticData.instance().getCommonCards().getAllCards(), cardsRule), count);
|
return Aggregates.random(Iterables.filter(StaticData.instance().getCommonCards().getAllCards(), cardsRule), count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import forge.StaticData;
|
|||||||
import forge.card.*;
|
import forge.card.*;
|
||||||
import forge.card.CardEdition.FoilType;
|
import forge.card.CardEdition.FoilType;
|
||||||
import forge.item.*;
|
import forge.item.*;
|
||||||
import forge.item.IPaperCard.Predicates.Presets;
|
|
||||||
import forge.util.*;
|
import forge.util.*;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
@@ -510,20 +509,20 @@ public class BoosterGenerator {
|
|||||||
Predicate<PaperCard> rarityPredicate = null;
|
Predicate<PaperCard> rarityPredicate = null;
|
||||||
switch (toAdd.getRarity()) {
|
switch (toAdd.getRarity()) {
|
||||||
case BasicLand:
|
case BasicLand:
|
||||||
rarityPredicate = Presets.IS_BASIC_LAND;
|
rarityPredicate = PaperCardPredicates.IS_BASIC_LAND;
|
||||||
break;
|
break;
|
||||||
case Common:
|
case Common:
|
||||||
rarityPredicate = Presets.IS_COMMON;
|
rarityPredicate = PaperCardPredicates.IS_COMMON;
|
||||||
break;
|
break;
|
||||||
case Uncommon:
|
case Uncommon:
|
||||||
rarityPredicate = Presets.IS_UNCOMMON;
|
rarityPredicate = PaperCardPredicates.IS_UNCOMMON;
|
||||||
break;
|
break;
|
||||||
case Rare:
|
case Rare:
|
||||||
case MythicRare:
|
case MythicRare:
|
||||||
rarityPredicate = Presets.IS_RARE_OR_MYTHIC;
|
rarityPredicate = PaperCardPredicates.IS_RARE_OR_MYTHIC;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rarityPredicate = Presets.IS_SPECIAL;
|
rarityPredicate = PaperCardPredicates.IS_SPECIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PaperCard toReplace = null;
|
PaperCard toReplace = null;
|
||||||
@@ -568,7 +567,7 @@ public class BoosterGenerator {
|
|||||||
public static PrintSheet makeSheet(String sheetKey, Iterable<PaperCard> src) {
|
public static PrintSheet makeSheet(String sheetKey, Iterable<PaperCard> src) {
|
||||||
PrintSheet ps = new PrintSheet(sheetKey);
|
PrintSheet ps = new PrintSheet(sheetKey);
|
||||||
String[] sKey = TextUtil.splitWithParenthesis(sheetKey, ' ', 2);
|
String[] sKey = TextUtil.splitWithParenthesis(sheetKey, ' ', 2);
|
||||||
Predicate<PaperCard> setPred = sKey.length > 1 ? IPaperCard.Predicates.printedInSets(sKey[1].split(" ")) : x1 -> true;
|
Predicate<PaperCard> setPred = sKey.length > 1 ? PaperCardPredicates.printedInSets(sKey[1].split(" ")) : x1 -> true;
|
||||||
|
|
||||||
List<String> operators = new LinkedList<>(Arrays.asList(TextUtil.splitWithParenthesis(sKey[0], ':')));
|
List<String> operators = new LinkedList<>(Arrays.asList(TextUtil.splitWithParenthesis(sKey[0], ':')));
|
||||||
Predicate<PaperCard> extraPred = buildExtraPredicate(operators);
|
Predicate<PaperCard> extraPred = buildExtraPredicate(operators);
|
||||||
@@ -613,31 +612,31 @@ public class BoosterGenerator {
|
|||||||
ps.addAll(Iterables.filter(src, predicate));
|
ps.addAll(Iterables.filter(src, predicate));
|
||||||
|
|
||||||
} else if (mainCode.equalsIgnoreCase(BoosterSlots.UNCOMMON_RARE)) { // for sets like ARN, where U1 cards are considered rare and U3 are uncommon
|
} else if (mainCode.equalsIgnoreCase(BoosterSlots.UNCOMMON_RARE)) { // for sets like ARN, where U1 cards are considered rare and U3 are uncommon
|
||||||
Predicate<PaperCard> predicateRares = setPred.and(Presets.IS_RARE).and(extraPred);
|
Predicate<PaperCard> predicateRares = setPred.and(PaperCardPredicates.IS_RARE).and(extraPred);
|
||||||
ps.addAll(Iterables.filter(src, predicateRares));
|
ps.addAll(Iterables.filter(src, predicateRares));
|
||||||
|
|
||||||
Predicate<PaperCard> predicateUncommon = setPred.and(Presets.IS_UNCOMMON).and(extraPred);
|
Predicate<PaperCard> predicateUncommon = setPred.and(PaperCardPredicates.IS_UNCOMMON).and(extraPred);
|
||||||
ps.addAll(Iterables.filter(src, predicateUncommon), 3);
|
ps.addAll(Iterables.filter(src, predicateUncommon), 3);
|
||||||
|
|
||||||
} else if (mainCode.equalsIgnoreCase(BoosterSlots.RARE_MYTHIC)) {
|
} else if (mainCode.equalsIgnoreCase(BoosterSlots.RARE_MYTHIC)) {
|
||||||
// Typical ratio of rares to mythics is 53:15, changing to 35:10 in smaller sets.
|
// Typical ratio of rares to mythics is 53:15, changing to 35:10 in smaller sets.
|
||||||
// To achieve the desired 1:8 are all mythics are added once, and all rares added twice per print sheet.
|
// To achieve the desired 1:8 are all mythics are added once, and all rares added twice per print sheet.
|
||||||
|
|
||||||
Predicate<PaperCard> predicateMythic = setPred.and(Presets.IS_MYTHIC_RARE).and(extraPred);
|
Predicate<PaperCard> predicateMythic = setPred.and(PaperCardPredicates.IS_MYTHIC_RARE).and(extraPred);
|
||||||
ps.addAll(Iterables.filter(src, predicateMythic));
|
ps.addAll(Iterables.filter(src, predicateMythic));
|
||||||
|
|
||||||
Predicate<PaperCard> predicateRare = setPred.and(Presets.IS_RARE).and(extraPred);
|
Predicate<PaperCard> predicateRare = setPred.and(PaperCardPredicates.IS_RARE).and(extraPred);
|
||||||
ps.addAll(Iterables.filter(src, predicateRare), 2);
|
ps.addAll(Iterables.filter(src, predicateRare), 2);
|
||||||
} else if (mainCode.equalsIgnoreCase(BoosterSlots.UNCOMMON_RARE_MYTHIC)) {
|
} else if (mainCode.equalsIgnoreCase(BoosterSlots.UNCOMMON_RARE_MYTHIC)) {
|
||||||
// Extended version of RARE_MYTHIC, used for Alchemy slots
|
// Extended version of RARE_MYTHIC, used for Alchemy slots
|
||||||
|
|
||||||
Predicate<PaperCard> predicateMythic = setPred.and(Presets.IS_MYTHIC_RARE).and(extraPred);
|
Predicate<PaperCard> predicateMythic = setPred.and(PaperCardPredicates.IS_MYTHIC_RARE).and(extraPred);
|
||||||
ps.addAll(Iterables.filter(src, predicateMythic));
|
ps.addAll(Iterables.filter(src, predicateMythic));
|
||||||
|
|
||||||
Predicate<PaperCard> predicateRare = setPred.and(Presets.IS_RARE).and(extraPred);
|
Predicate<PaperCard> predicateRare = setPred.and(PaperCardPredicates.IS_RARE).and(extraPred);
|
||||||
ps.addAll(Iterables.filter(src, predicateRare), 2);
|
ps.addAll(Iterables.filter(src, predicateRare), 2);
|
||||||
|
|
||||||
Predicate<PaperCard> predicateUncommon = setPred.and(Presets.IS_UNCOMMON).and(extraPred);
|
Predicate<PaperCard> predicateUncommon = setPred.and(PaperCardPredicates.IS_UNCOMMON).and(extraPred);
|
||||||
ps.addAll(Iterables.filter(src, predicateUncommon), 4);
|
ps.addAll(Iterables.filter(src, predicateUncommon), 4);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Booster generator: operator could not be parsed - " + mainCode);
|
throw new IllegalArgumentException("Booster generator: operator could not be parsed - " + mainCode);
|
||||||
@@ -675,48 +674,48 @@ public class BoosterGenerator {
|
|||||||
.or(CardRulesPredicates.splitType(CardSplitType.Modal)
|
.or(CardRulesPredicates.splitType(CardSplitType.Modal)
|
||||||
),
|
),
|
||||||
PaperCard::getRules);
|
PaperCard::getRules);
|
||||||
} else if (operator.equalsIgnoreCase(BoosterSlots.LAND)) { toAdd = Predicates.compose(CardRulesPredicates.Presets.IS_LAND, PaperCard::getRules);
|
} else if (operator.equalsIgnoreCase(BoosterSlots.LAND)) { toAdd = Predicates.compose(CardRulesPredicates.IS_LAND, PaperCard::getRules);
|
||||||
} else if (operator.equalsIgnoreCase(BoosterSlots.BASIC_LAND)) { toAdd = IPaperCard.Predicates.Presets.IS_BASIC_LAND;
|
} else if (operator.equalsIgnoreCase(BoosterSlots.BASIC_LAND)) { toAdd = PaperCardPredicates.IS_BASIC_LAND;
|
||||||
} else if (operator.equalsIgnoreCase(BoosterSlots.TIME_SHIFTED)) { toAdd = IPaperCard.Predicates.Presets.IS_SPECIAL;
|
} else if (operator.equalsIgnoreCase(BoosterSlots.TIME_SHIFTED)) { toAdd = PaperCardPredicates.IS_SPECIAL;
|
||||||
} else if (operator.equalsIgnoreCase(BoosterSlots.SPECIAL)) { toAdd = IPaperCard.Predicates.Presets.IS_SPECIAL;
|
} else if (operator.equalsIgnoreCase(BoosterSlots.SPECIAL)) { toAdd = PaperCardPredicates.IS_SPECIAL;
|
||||||
} else if (operator.equalsIgnoreCase(BoosterSlots.MYTHIC)) { toAdd = IPaperCard.Predicates.Presets.IS_MYTHIC_RARE;
|
} else if (operator.equalsIgnoreCase(BoosterSlots.MYTHIC)) { toAdd = PaperCardPredicates.IS_MYTHIC_RARE;
|
||||||
} else if (operator.equalsIgnoreCase(BoosterSlots.RARE)) { toAdd = IPaperCard.Predicates.Presets.IS_RARE;
|
} else if (operator.equalsIgnoreCase(BoosterSlots.RARE)) { toAdd = PaperCardPredicates.IS_RARE;
|
||||||
} else if (operator.equalsIgnoreCase(BoosterSlots.UNCOMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_UNCOMMON;
|
} else if (operator.equalsIgnoreCase(BoosterSlots.UNCOMMON)) { toAdd = PaperCardPredicates.IS_UNCOMMON;
|
||||||
} else if (operator.equalsIgnoreCase(BoosterSlots.COMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_COMMON;
|
} else if (operator.equalsIgnoreCase(BoosterSlots.COMMON)) { toAdd = PaperCardPredicates.IS_COMMON;
|
||||||
} else if (operator.startsWith("name(")) {
|
} else if (operator.startsWith("name(")) {
|
||||||
operator = StringUtils.strip(operator.substring(4), "() ");
|
operator = StringUtils.strip(operator.substring(4), "() ");
|
||||||
String[] cardNames = TextUtil.splitWithParenthesis(operator, ',', '"', '"');
|
String[] cardNames = TextUtil.splitWithParenthesis(operator, ',', '"', '"');
|
||||||
toAdd = IPaperCard.Predicates.names(Lists.newArrayList(cardNames));
|
toAdd = PaperCardPredicates.names(Lists.newArrayList(cardNames));
|
||||||
} else if (operator.startsWith("color(")) {
|
} else if (operator.startsWith("color(")) {
|
||||||
operator = StringUtils.strip(operator.substring("color(".length() + 1), "()\" ");
|
operator = StringUtils.strip(operator.substring("color(".length() + 1), "()\" ");
|
||||||
switch (operator.toLowerCase()) {
|
switch (operator.toLowerCase()) {
|
||||||
case "black":
|
case "black":
|
||||||
toAdd = Presets.IS_BLACK;
|
toAdd = PaperCardPredicates.IS_BLACK;
|
||||||
break;
|
break;
|
||||||
case "blue":
|
case "blue":
|
||||||
toAdd = Presets.IS_BLUE;
|
toAdd = PaperCardPredicates.IS_BLUE;
|
||||||
break;
|
break;
|
||||||
case "green":
|
case "green":
|
||||||
toAdd = Presets.IS_GREEN;
|
toAdd = PaperCardPredicates.IS_GREEN;
|
||||||
break;
|
break;
|
||||||
case "red":
|
case "red":
|
||||||
toAdd = Presets.IS_RED;
|
toAdd = PaperCardPredicates.IS_RED;
|
||||||
break;
|
break;
|
||||||
case "white":
|
case "white":
|
||||||
toAdd = Presets.IS_WHITE;
|
toAdd = PaperCardPredicates.IS_WHITE;
|
||||||
break;
|
break;
|
||||||
case "colorless":
|
case "colorless":
|
||||||
toAdd = Presets.IS_COLORLESS;
|
toAdd = PaperCardPredicates.IS_COLORLESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (operator.startsWith("fromSets(")) {
|
} else if (operator.startsWith("fromSets(")) {
|
||||||
operator = StringUtils.strip(operator.substring("fromSets(".length() + 1), "()\" ");
|
operator = StringUtils.strip(operator.substring("fromSets(".length() + 1), "()\" ");
|
||||||
String[] sets = operator.split(",");
|
String[] sets = operator.split(",");
|
||||||
toAdd = IPaperCard.Predicates.printedInSets(sets);
|
toAdd = PaperCardPredicates.printedInSets(sets);
|
||||||
} else if (operator.startsWith("fromSheet(") && invert) {
|
} else if (operator.startsWith("fromSheet(") && invert) {
|
||||||
String sheetName = StringUtils.strip(operator.substring(9), "()\" ");
|
String sheetName = StringUtils.strip(operator.substring(9), "()\" ");
|
||||||
Iterable<PaperCard> cards = StaticData.instance().getPrintSheets().get(sheetName).toFlatList();
|
Iterable<PaperCard> cards = StaticData.instance().getPrintSheets().get(sheetName).toFlatList();
|
||||||
toAdd = IPaperCard.Predicates.cards(Lists.newArrayList(cards));
|
toAdd = PaperCardPredicates.cards(Lists.newArrayList(cards));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toAdd == null) {
|
if (toAdd == null) {
|
||||||
|
|||||||
@@ -1099,7 +1099,7 @@ public class Game {
|
|||||||
|
|
||||||
private void chooseRandomCardsForAnte(final Player player, final Multimap<Player, Card> anteed) {
|
private void chooseRandomCardsForAnte(final Player player, final Multimap<Player, Card> anteed) {
|
||||||
final CardCollectionView lib = player.getCardsIn(ZoneType.Library);
|
final CardCollectionView lib = player.getCardsIn(ZoneType.Library);
|
||||||
Predicate<Card> goodForAnte = CardPredicates.Presets.BASIC_LANDS.negate();
|
Predicate<Card> goodForAnte = CardPredicates.BASIC_LANDS.negate();
|
||||||
Card ante = Aggregates.random(Iterables.filter(lib, goodForAnte));
|
Card ante = Aggregates.random(Iterables.filter(lib, goodForAnte));
|
||||||
if (ante == null) {
|
if (ante == null) {
|
||||||
getGameLog().add(GameLogEntryType.ANTE, "Only basic lands found. Will ante one of them");
|
getGameLog().add(GameLogEntryType.ANTE, "Only basic lands found. Will ante one of them");
|
||||||
|
|||||||
@@ -817,14 +817,14 @@ public class GameAction {
|
|||||||
if (!stAb.hasParam("ValidAttacker") || (stAb.hasParam("ValidBlocker") && stAb.getParam("ValidBlocker").equals("Creature.Self"))) {
|
if (!stAb.hasParam("ValidAttacker") || (stAb.hasParam("ValidBlocker") && stAb.getParam("ValidBlocker").equals("Creature.Self"))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (Card creature : Iterables.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES)) {
|
for (Card creature : Iterables.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.CREATURES)) {
|
||||||
if (stAb.matchesValidParam("ValidAttacker", creature)) {
|
if (stAb.matchesValidParam("ValidAttacker", creature)) {
|
||||||
creature.updateAbilityTextForView();
|
creature.updateAbilityTextForView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stAb.checkMode(StaticAbilityCantAttackBlock.MinMaxBlockerMode)) {
|
if (stAb.checkMode(StaticAbilityCantAttackBlock.MinMaxBlockerMode)) {
|
||||||
for (Card creature : Iterables.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES)) {
|
for (Card creature : Iterables.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.CREATURES)) {
|
||||||
if (stAb.matchesValidParam("ValidCard", creature)) {
|
if (stAb.matchesValidParam("ValidCard", creature)) {
|
||||||
creature.updateAbilityTextForView();
|
creature.updateAbilityTextForView();
|
||||||
}
|
}
|
||||||
@@ -1431,7 +1431,7 @@ public class GameAction {
|
|||||||
|
|
||||||
if (desCreats != null) {
|
if (desCreats != null) {
|
||||||
if (desCreats.size() > 1 && !orderedDesCreats) {
|
if (desCreats.size() > 1 && !orderedDesCreats) {
|
||||||
desCreats = CardLists.filter(desCreats, CardPredicates.Presets.CAN_BE_DESTROYED);
|
desCreats = CardLists.filter(desCreats, CardPredicates.CAN_BE_DESTROYED);
|
||||||
if (!desCreats.isEmpty()) {
|
if (!desCreats.isEmpty()) {
|
||||||
desCreats = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, desCreats, ZoneType.Graveyard, null);
|
desCreats = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, desCreats, ZoneType.Graveyard, null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
|||||||
|
|
||||||
public final CardCollectionView getEnchantedBy() {
|
public final CardCollectionView getEnchantedBy() {
|
||||||
// enchanted means attached by Aura
|
// enchanted means attached by Aura
|
||||||
return CardLists.filter(getAttachedCards(), CardPredicates.Presets.AURA);
|
return CardLists.filter(getAttachedCards(), CardPredicates.AURA);
|
||||||
}
|
}
|
||||||
|
|
||||||
// doesn't include phased out cards
|
// doesn't include phased out cards
|
||||||
@@ -176,7 +176,7 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
|||||||
|
|
||||||
public final boolean isEnchanted() {
|
public final boolean isEnchanted() {
|
||||||
// enchanted means attached by Aura
|
// enchanted means attached by Aura
|
||||||
return Iterables.any(getAttachedCards(), CardPredicates.Presets.AURA);
|
return Iterables.any(getAttachedCards(), CardPredicates.AURA);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean hasCardAttachment(Card c) {
|
public final boolean hasCardAttachment(Card c) {
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ import forge.card.CardEdition.CardInSet;
|
|||||||
import forge.card.CardRarity;
|
import forge.card.CardRarity;
|
||||||
import forge.deck.CardPool;
|
import forge.deck.CardPool;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.item.IPaperCard;
|
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
|
import forge.item.PaperCardPredicates;
|
||||||
import forge.util.FileSection;
|
import forge.util.FileSection;
|
||||||
import forge.util.FileUtil;
|
import forge.util.FileUtil;
|
||||||
import forge.util.Predicates;
|
import forge.util.Predicates;
|
||||||
@@ -138,17 +138,17 @@ public class GameFormat implements Comparable<GameFormat> {
|
|||||||
this.filterPrinted = this.buildFilterPrinted();
|
this.filterPrinted = this.buildFilterPrinted();
|
||||||
}
|
}
|
||||||
protected Predicate<PaperCard> buildFilter(boolean printed) {
|
protected Predicate<PaperCard> buildFilter(boolean printed) {
|
||||||
Predicate<PaperCard> p = IPaperCard.Predicates.names(this.getBannedCardNames()).negate();
|
Predicate<PaperCard> p = PaperCardPredicates.names(this.getBannedCardNames()).negate();
|
||||||
|
|
||||||
if (FormatSubType.ARENA.equals(this.getFormatSubType())) {
|
if (FormatSubType.ARENA.equals(this.getFormatSubType())) {
|
||||||
p = p.and(IPaperCard.Predicates.Presets.IS_UNREBALANCED.negate());
|
p = p.and(PaperCardPredicates.IS_UNREBALANCED.negate());
|
||||||
} else {
|
} else {
|
||||||
p = p.and(IPaperCard.Predicates.Presets.IS_REBALANCED.negate());
|
p = p.and(PaperCardPredicates.IS_REBALANCED.negate());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.getAllowedSetCodes().isEmpty()) {
|
if (!this.getAllowedSetCodes().isEmpty()) {
|
||||||
p = p.and(printed ?
|
p = p.and(printed ?
|
||||||
IPaperCard.Predicates.printedInSets(this.getAllowedSetCodes(), printed) :
|
PaperCardPredicates.printedInSets(this.getAllowedSetCodes(), printed) :
|
||||||
StaticData.instance().getCommonCards().wasPrintedInSets(this.getAllowedSetCodes()));
|
StaticData.instance().getCommonCards().wasPrintedInSets(this.getAllowedSetCodes()));
|
||||||
}
|
}
|
||||||
if (!this.getAllowedRarities().isEmpty()) {
|
if (!this.getAllowedRarities().isEmpty()) {
|
||||||
@@ -159,7 +159,7 @@ public class GameFormat implements Comparable<GameFormat> {
|
|||||||
p = p.and(Predicates.or(crp));
|
p = p.and(Predicates.or(crp));
|
||||||
}
|
}
|
||||||
if (!this.getAdditionalCards().isEmpty()) {
|
if (!this.getAdditionalCards().isEmpty()) {
|
||||||
p = p.or(IPaperCard.Predicates.names(this.getAdditionalCards()));
|
p = p.or(PaperCardPredicates.names(this.getAdditionalCards()));
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2225,7 +2225,7 @@ public class AbilityUtils {
|
|||||||
if (sq[0].equals("EnchantedControllerCreatures")) { // maybe refactor into a Valid with ControlledBy
|
if (sq[0].equals("EnchantedControllerCreatures")) { // maybe refactor into a Valid with ControlledBy
|
||||||
int v = 0;
|
int v = 0;
|
||||||
if (c.getEnchantingCard() != null) {
|
if (c.getEnchantingCard() != null) {
|
||||||
v = CardLists.count(c.getEnchantingCard().getController().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
|
v = CardLists.count(c.getEnchantingCard().getController().getCardsIn(ZoneType.Battlefield), CardPredicates.CREATURES);
|
||||||
}
|
}
|
||||||
return doXMath(v, expr, c, ctb);
|
return doXMath(v, expr, c, ctb);
|
||||||
}
|
}
|
||||||
@@ -3877,9 +3877,9 @@ public class AbilityUtils {
|
|||||||
// Refined qualities
|
// Refined qualities
|
||||||
|
|
||||||
// "Untapped Lands" - Count$UntappedTypeYouCtrl.Land
|
// "Untapped Lands" - Count$UntappedTypeYouCtrl.Land
|
||||||
// if (sq[0].contains("Untapped")) { someCards = CardLists.filter(someCards, Presets.UNTAPPED); }
|
// if (sq[0].contains("Untapped")) { someCards = CardLists.filter(someCards, CardPredicates.UNTAPPED); }
|
||||||
|
|
||||||
// if (sq[0].contains("Tapped")) { someCards = CardLists.filter(someCards, Presets.TAPPED); }
|
// if (sq[0].contains("Tapped")) { someCards = CardLists.filter(someCards, CardPredicates.TAPPED); }
|
||||||
|
|
||||||
// String sq0 = sq[0].toLowerCase();
|
// String sq0 = sq[0].toLowerCase();
|
||||||
// for (String color : MagicColor.Constant.ONLY_COLORS) {
|
// for (String color : MagicColor.Constant.ONLY_COLORS) {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import forge.game.card.CardCollection;
|
|||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates;
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerActionConfirmMode;
|
import forge.game.player.PlayerActionConfirmMode;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@@ -119,7 +118,7 @@ public class ChooseCardEffect extends SpellAbilityEffect {
|
|||||||
boolean dontRevealToOwner = true;
|
boolean dontRevealToOwner = true;
|
||||||
if (sa.hasParam("EachBasicType")) {
|
if (sa.hasParam("EachBasicType")) {
|
||||||
// Get all lands,
|
// Get all lands,
|
||||||
List<Card> land = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), Presets.LANDS);
|
List<Card> land = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.LANDS);
|
||||||
String eachBasic = sa.getParam("EachBasicType");
|
String eachBasic = sa.getParam("EachBasicType");
|
||||||
if (eachBasic.equals("Controlled")) {
|
if (eachBasic.equals("Controlled")) {
|
||||||
land = CardLists.filterControlledBy(land, p);
|
land = CardLists.filterControlledBy(land, p);
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class ChooseCardNameEffect extends SpellAbilityEffect {
|
|||||||
// Momir needs PaperCard
|
// Momir needs PaperCard
|
||||||
//Collection<PaperCard> cards = StaticData.instance().getCommonCards().getUniqueCards();
|
//Collection<PaperCard> cards = StaticData.instance().getCommonCards().getUniqueCards();
|
||||||
//Predicate<PaperCard> cpp = Predicates.and(
|
//Predicate<PaperCard> cpp = Predicates.and(
|
||||||
// Predicates.compose(CardRulesPredicates.Presets.IS_CREATURE, PaperCard.FN_GET_RULES),
|
// Predicates.compose(CardRulesPredicates.IS_CREATURE, PaperCard.FN_GET_RULES),
|
||||||
// Predicates.compose(CardRulesPredicates.cmc(ComparableOp.EQUALS, validAmount), PaperCard.FN_GET_RULES));
|
// Predicates.compose(CardRulesPredicates.cmc(ComparableOp.EQUALS, validAmount), PaperCard.FN_GET_RULES));
|
||||||
//cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
//cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
||||||
//if (!cards.isEmpty()) { chosen = Aggregates.random(cards).getName();
|
//if (!cards.isEmpty()) { chosen = Aggregates.random(cards).getName();
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ public class ConniveEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
p.drawCards(num, sa, moveParams);
|
p.drawCards(num, sa, moveParams);
|
||||||
|
|
||||||
CardCollection validDiscards = CardLists.filter(p.getCardsIn(ZoneType.Hand), CardPredicates.Presets.NON_TOKEN);
|
CardCollection validDiscards = CardLists.filter(p.getCardsIn(ZoneType.Hand), CardPredicates.NON_TOKEN);
|
||||||
if (validDiscards.isEmpty() || !p.canDiscardBy(sa, true)) { // hand being empty unlikely, just to be safe
|
if (validDiscards.isEmpty() || !p.canDiscardBy(sa, true)) { // hand being empty unlikely, just to be safe
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,11 +156,11 @@ public class CopyPermanentEffect extends TokenEffectBase {
|
|||||||
"X", Integer.toString(AbilityUtils.calculateAmount(host, "X", sa)));
|
"X", Integer.toString(AbilityUtils.calculateAmount(host, "X", sa)));
|
||||||
}
|
}
|
||||||
if (StringUtils.containsIgnoreCase(valid, "creature")) {
|
if (StringUtils.containsIgnoreCase(valid, "creature")) {
|
||||||
Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.Presets.IS_CREATURE, PaperCard::getRules);
|
Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.IS_CREATURE, PaperCard::getRules);
|
||||||
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
||||||
}
|
}
|
||||||
if (StringUtils.containsIgnoreCase(valid, "equipment")) {
|
if (StringUtils.containsIgnoreCase(valid, "equipment")) {
|
||||||
Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.Presets.IS_EQUIPMENT, PaperCard::getRules);
|
Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.IS_EQUIPMENT, PaperCard::getRules);
|
||||||
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
||||||
}
|
}
|
||||||
if (sa.hasParam("RandomCopied")) {
|
if (sa.hasParam("RandomCopied")) {
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ public class DestroyAllEffect extends SpellAbilityEffect {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// exclude cards that can't be destroyed at this moment
|
// exclude cards that can't be destroyed at this moment
|
||||||
list = CardLists.filter(list, CardPredicates.Presets.CAN_BE_DESTROYED);
|
list = CardLists.filter(list, CardPredicates.CAN_BE_DESTROYED);
|
||||||
|
|
||||||
list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard, sa);
|
list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard, sa);
|
||||||
|
|
||||||
|
|||||||
@@ -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.NON_LANDS);
|
int n = CardLists.count(milled, CardPredicates.NON_LANDS);
|
||||||
|
|
||||||
if (StaticAbilityGainLifeRadiation.gainLifeRadiation(p)) {
|
if (StaticAbilityGainLifeRadiation.gainLifeRadiation(p)) {
|
||||||
p.gainLife(n, sa.getHostCard(), sa);
|
p.gainLife(n, sa.getHostCard(), sa);
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ import forge.game.player.PlayerCollection;
|
|||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.item.BoosterPack;
|
import forge.item.*;
|
||||||
import forge.item.IPaperCard;
|
|
||||||
import forge.item.PaperCard;
|
|
||||||
import forge.item.SealedTemplate;
|
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
import forge.util.CardTranslation;
|
import forge.util.CardTranslation;
|
||||||
import forge.util.Iterables;
|
import forge.util.Iterables;
|
||||||
@@ -153,7 +150,7 @@ public class MakeCardEffect extends SpellAbilityEffect {
|
|||||||
while (toMake > 0) {
|
while (toMake > 0) {
|
||||||
PaperCard pc;
|
PaperCard pc;
|
||||||
if (pack != null) {
|
if (pack != null) {
|
||||||
pc = Iterables.getLast(Iterables.filter(pack, IPaperCard.Predicates.name(name)));
|
pc = Iterables.getLast(Iterables.filter(pack, PaperCardPredicates.name(name)));
|
||||||
} else {
|
} else {
|
||||||
pc = StaticData.instance().getCommonCards().getUniqueByName(name);
|
pc = StaticData.instance().getCommonCards().getUniqueByName(name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,11 +121,11 @@ public class PlayEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
} else if (valid.equalsIgnoreCase("sorcery")) {
|
} else if (valid.equalsIgnoreCase("sorcery")) {
|
||||||
cards = Lists.newArrayList(StaticData.instance().getCommonCards().getUniqueCards());
|
cards = Lists.newArrayList(StaticData.instance().getCommonCards().getUniqueCards());
|
||||||
final Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.Presets.IS_SORCERY, PaperCard::getRules);
|
final Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.IS_SORCERY, PaperCard::getRules);
|
||||||
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
||||||
} else if (valid.equalsIgnoreCase("instant")) {
|
} else if (valid.equalsIgnoreCase("instant")) {
|
||||||
cards = Lists.newArrayList(StaticData.instance().getCommonCards().getUniqueCards());
|
cards = Lists.newArrayList(StaticData.instance().getCommonCards().getUniqueCards());
|
||||||
final Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.Presets.IS_INSTANT, PaperCard::getRules);
|
final Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.IS_INSTANT, PaperCard::getRules);
|
||||||
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
||||||
}
|
}
|
||||||
if (sa.hasParam("RandomCopied")) {
|
if (sa.hasParam("RandomCopied")) {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class PlayLandVariantEffect extends SpellAbilityEffect {
|
|||||||
final String landType = sa.getParam("Clone");
|
final String landType = sa.getParam("Clone");
|
||||||
List<PaperCard> cards = Lists.newArrayList(StaticData.instance().getCommonCards().getUniqueCards());
|
List<PaperCard> cards = Lists.newArrayList(StaticData.instance().getCommonCards().getUniqueCards());
|
||||||
if ("BasicLand".equals(landType)) {
|
if ("BasicLand".equals(landType)) {
|
||||||
final Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard::getRules);
|
final Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.IS_BASIC_LAND, PaperCard::getRules);
|
||||||
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
||||||
}
|
}
|
||||||
// current color of source card
|
// current color of source card
|
||||||
|
|||||||
@@ -4,12 +4,7 @@ import com.google.common.collect.Maps;
|
|||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardCollectionView;
|
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
@@ -102,7 +97,7 @@ public class UntapEffect extends SpellAbilityEffect {
|
|||||||
valid, sa.getActivatingPlayer(), sa.getHostCard(), sa);
|
valid, sa.getActivatingPlayer(), sa.getHostCard(), sa);
|
||||||
// the few mandatory are handled differently
|
// the few mandatory are handled differently
|
||||||
if (!mandatory) {
|
if (!mandatory) {
|
||||||
list = CardLists.filter(list, Presets.TAPPED);
|
list = CardLists.filter(list, CardPredicates.TAPPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
final CardCollectionView selected = p.getController().chooseCardsForEffect(list, sa, Localizer.getInstance().getMessage("lblSelectCardToUntap"), mandatory ? num : 0, num, !mandatory, null);
|
final CardCollectionView selected = p.getController().chooseCardsForEffect(list, sa, Localizer.getInstance().getMessage("lblSelectCardToUntap"), mandatory ? num : 0, num, !mandatory, null);
|
||||||
|
|||||||
@@ -46,13 +46,13 @@ public class VentureEffect extends SpellAbilityEffect {
|
|||||||
if (sa.hasParam("Dungeon")) {
|
if (sa.hasParam("Dungeon")) {
|
||||||
dungeonCards = StaticData.instance().getVariantCards()
|
dungeonCards = StaticData.instance().getVariantCards()
|
||||||
.getAllCards(Predicates.compose(
|
.getAllCards(Predicates.compose(
|
||||||
CardRulesPredicates.Presets.IS_DUNGEON
|
CardRulesPredicates.IS_DUNGEON
|
||||||
.and(CardRulesPredicates.subType(StringOp.EQUALS, sa.getParam("Dungeon"))),
|
.and(CardRulesPredicates.subType(StringOp.EQUALS, sa.getParam("Dungeon"))),
|
||||||
PaperCard::getRules));
|
PaperCard::getRules));
|
||||||
} else {
|
} else {
|
||||||
// Create a new dungeon card chosen by player in command zone.
|
// Create a new dungeon card chosen by player in command zone.
|
||||||
dungeonCards = StaticData.instance().getVariantCards().getAllCards(
|
dungeonCards = StaticData.instance().getVariantCards().getAllCards(
|
||||||
Predicates.compose(CardRulesPredicates.Presets.IS_DUNGEON, PaperCard::getRules));
|
Predicates.compose(CardRulesPredicates.IS_DUNGEON, PaperCard::getRules));
|
||||||
dungeonCards.removeIf(c -> !c.getRules().isEnterableDungeon());
|
dungeonCards.removeIf(c -> !c.getRules().isEnterableDungeon());
|
||||||
}
|
}
|
||||||
String message = Localizer.getInstance().getMessage("lblChooseDungeon");
|
String message = Localizer.getInstance().getMessage("lblChooseDungeon");
|
||||||
|
|||||||
@@ -3862,11 +3862,11 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final CardCollectionView getEquippedBy() {
|
public final CardCollectionView getEquippedBy() {
|
||||||
return CardLists.filter(getAttachedCards(), CardPredicates.Presets.EQUIPMENT);
|
return CardLists.filter(getAttachedCards(), CardPredicates.EQUIPMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isEquipped() {
|
public final boolean isEquipped() {
|
||||||
return Iterables.any(getAttachedCards(), CardPredicates.Presets.EQUIPMENT);
|
return Iterables.any(getAttachedCards(), CardPredicates.EQUIPMENT);
|
||||||
}
|
}
|
||||||
public final boolean isEquippedBy(Card c) {
|
public final boolean isEquippedBy(Card c) {
|
||||||
return this.hasCardAttachment(c);
|
return this.hasCardAttachment(c);
|
||||||
@@ -3876,11 +3876,11 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final CardCollectionView getFortifiedBy() {
|
public final CardCollectionView getFortifiedBy() {
|
||||||
return CardLists.filter(getAttachedCards(), CardPredicates.Presets.FORTIFICATION);
|
return CardLists.filter(getAttachedCards(), CardPredicates.FORTIFICATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isFortified() {
|
public final boolean isFortified() {
|
||||||
return Iterables.any(getAttachedCards(), CardPredicates.Presets.FORTIFICATION);
|
return Iterables.any(getAttachedCards(), CardPredicates.FORTIFICATION);
|
||||||
}
|
}
|
||||||
public final boolean isFortifiedBy(Card c) {
|
public final boolean isFortifiedBy(Card c) {
|
||||||
// 301.5e + 301.6
|
// 301.5e + 301.6
|
||||||
|
|||||||
@@ -302,109 +302,41 @@ public final class CardPredicates {
|
|||||||
return c -> c.isAttraction() && c.getAttractionLights().contains(light);
|
return c -> c.isAttraction() && c.getAttractionLights().contains(light);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Presets {
|
public static final Predicate<Card> TAPPED = Card::isTapped;
|
||||||
|
public static final Predicate<Card> FACE_DOWN = Card::isFaceDown;
|
||||||
|
public static final Predicate<Card> UNTAPPED = Card::isUntapped;
|
||||||
|
public static final Predicate<Card> CAN_TAP = Card::canTap;
|
||||||
|
public static final Predicate<Card> CAN_CREW = Card::canCrew;
|
||||||
|
public static final Predicate<Card> CREATURES = Card::isCreature;
|
||||||
|
public static final Predicate<Card> NON_CREATURES = c -> !c.isCreature();
|
||||||
|
public static final Predicate<Card> ENCHANTMENTS = Card::isEnchantment;
|
||||||
|
public static final Predicate<Card> AURA = Card::isAura;
|
||||||
|
public static final Predicate<Card> EQUIPMENT = Card::isEquipment;
|
||||||
|
public static final Predicate<Card> FORTIFICATION = Card::isFortification;
|
||||||
|
public static final Predicate<Card> CURSE = Card::isCurse;
|
||||||
|
public static final Predicate<Card> UNENCHANTED = c -> !c.isEnchanted();
|
||||||
|
public static final Predicate<Card> ENCHANTED = GameEntity::isEnchanted;
|
||||||
|
public static final Predicate<Card> NON_TOKEN = c -> !(c.isToken() || c.isTokenCard());
|
||||||
|
public static final Predicate<Card> TOKEN = c -> c.isToken() || c.isTokenCard();
|
||||||
|
public static final Predicate<Card> BASIC_LANDS = c -> {
|
||||||
|
// the isBasicLand() check here may be sufficient...
|
||||||
|
return c.isLand() && c.isBasicLand();
|
||||||
|
};
|
||||||
|
public static final Predicate<Card> NONBASIC_LANDS = c -> c.isLand() && !c.isBasicLand();
|
||||||
|
|
||||||
/**
|
public static final Predicate<Card> ARTIFACTS = Card::isArtifact;
|
||||||
* a Predicate<Card> to get all cards that are tapped.
|
public static final Predicate<Card> INSTANTS_AND_SORCERIES = Card::isInstantOrSorcery;
|
||||||
*/
|
|
||||||
public static final Predicate<Card> TAPPED = Card::isTapped;
|
|
||||||
|
|
||||||
public static final Predicate<Card> FACE_DOWN = Card::isFaceDown;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all cards that are untapped.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> UNTAPPED = Card::isUntapped;
|
|
||||||
|
|
||||||
public static final Predicate<Card> CAN_TAP = Card::canTap;
|
|
||||||
|
|
||||||
public static final Predicate<Card> CAN_CREW = Card::canCrew;
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all creatures.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> ENCHANTMENTS = Card::isEnchantment;
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all aura.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> AURA = Card::isAura;
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all equipment.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> EQUIPMENT = Card::isEquipment;
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all fortification.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> FORTIFICATION = Card::isFortification;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all curse.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> CURSE = Card::isCurse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all unenchanted cards in a list.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> UNENCHANTED = c -> !c.isEnchanted();
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all enchanted cards in a list.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> ENCHANTED = GameEntity::isEnchanted;
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all nontoken cards.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> NON_TOKEN = c -> !(c.isToken() || c.isTokenCard());
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all token cards.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> TOKEN = c -> c.isToken() || c.isTokenCard();
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all basicLands.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> BASIC_LANDS = c -> {
|
|
||||||
// the isBasicLand() check here may be sufficient...
|
|
||||||
return c.isLand() && c.isBasicLand();
|
|
||||||
};
|
|
||||||
public static final Predicate<Card> NONBASIC_LANDS = c -> c.isLand() && !c.isBasicLand();
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all artifacts.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> ARTIFACTS = Card::isArtifact;
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all nonartifacts.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> LANDS_PRODUCING_MANA = c -> c.isBasicLand() || (c.isLand() && !c.getManaAbilities().isEmpty());
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all permanents.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> PERMANENTS = Card::isPermanent;
|
|
||||||
/**
|
|
||||||
* a Predicate<Card> to get all nonland permanents.
|
|
||||||
*/
|
|
||||||
public static final Predicate<Card> NONLAND_PERMANENTS = c -> c.isPermanent() && !c.isLand();
|
|
||||||
|
|
||||||
public static final Predicate<Card> hasFirstStrike = c -> c.isCreature() && (c.hasFirstStrike() || c.hasDoubleStrike());
|
|
||||||
public static final Predicate<Card> hasSecondStrike = c -> c.isCreature() && (!c.hasFirstStrike() || c.hasDoubleStrike());
|
|
||||||
public static final Predicate<Card> SNOW_LANDS = c -> c.isLand() && c.isSnow();
|
|
||||||
public static final Predicate<Card> PLANESWALKERS = Card::isPlaneswalker;
|
|
||||||
public static final Predicate<Card> BATTLES = Card::isBattle;
|
|
||||||
public static final Predicate<Card> CAN_BE_DESTROYED = Card::canBeDestroyed;
|
|
||||||
public static final Predicate<Card> ATTRACTIONS = Card::isAttraction;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public static final Predicate<Card> LANDS = Card::isLand;
|
||||||
|
public static final Predicate<Card> NON_LANDS = c -> !c.isLand();
|
||||||
|
public static final Predicate<Card> LANDS_PRODUCING_MANA = c -> c.isBasicLand() || (c.isLand() && !c.getManaAbilities().isEmpty());
|
||||||
|
public static final Predicate<Card> PERMANENTS = Card::isPermanent;
|
||||||
|
public static final Predicate<Card> NONLAND_PERMANENTS = c -> c.isPermanent() && !c.isLand();
|
||||||
|
public static final Predicate<Card> hasFirstStrike = c -> c.isCreature() && (c.hasFirstStrike() || c.hasDoubleStrike());
|
||||||
|
public static final Predicate<Card> hasSecondStrike = c -> c.isCreature() && (!c.hasFirstStrike() || c.hasDoubleStrike());
|
||||||
|
public static final Predicate<Card> SNOW_LANDS = c -> c.isLand() && c.isSnow();
|
||||||
|
public static final Predicate<Card> PLANESWALKERS = Card::isPlaneswalker;
|
||||||
|
public static final Predicate<Card> BATTLES = Card::isBattle;
|
||||||
|
public static final Predicate<Card> CAN_BE_DESTROYED = Card::canBeDestroyed;
|
||||||
|
public static final Predicate<Card> ATTRACTIONS = Card::isAttraction;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import forge.game.Game;
|
|||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.combat.AttackRequirement;
|
import forge.game.combat.AttackRequirement;
|
||||||
import forge.game.combat.AttackingBand;
|
import forge.game.combat.AttackingBand;
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
@@ -646,7 +645,7 @@ public class CardProperty {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("TopGraveyardCreature")) {
|
} else if (property.startsWith("TopGraveyardCreature")) {
|
||||||
CardCollection cards = CardLists.filter(card.getOwner().getCardsIn(ZoneType.Graveyard), CardPredicates.Presets.CREATURES);
|
CardCollection cards = CardLists.filter(card.getOwner().getCardsIn(ZoneType.Graveyard), CardPredicates.CREATURES);
|
||||||
Collections.reverse(cards);
|
Collections.reverse(cards);
|
||||||
if (cards.isEmpty() || !card.equals(cards.get(0))) {
|
if (cards.isEmpty() || !card.equals(cards.get(0))) {
|
||||||
return false;
|
return false;
|
||||||
@@ -931,7 +930,7 @@ public class CardProperty {
|
|||||||
return false;
|
return false;
|
||||||
} else if (restriction.equals("NonToken")) {
|
} else if (restriction.equals("NonToken")) {
|
||||||
return !CardLists.filter(game.getCardsIn(ZoneType.Battlefield),
|
return !CardLists.filter(game.getCardsIn(ZoneType.Battlefield),
|
||||||
Presets.NON_TOKEN, CardPredicates.sharesNameWith(card)).isEmpty();
|
CardPredicates.NON_TOKEN, CardPredicates.sharesNameWith(card)).isEmpty();
|
||||||
} else if (restriction.equals("TriggeredCard")) {
|
} else if (restriction.equals("TriggeredCard")) {
|
||||||
if (!(spellAbility instanceof SpellAbility)) {
|
if (!(spellAbility instanceof SpellAbility)) {
|
||||||
System.out.println("Looking at TriggeredCard but no SA?");
|
System.out.println("Looking at TriggeredCard but no SA?");
|
||||||
@@ -1305,7 +1304,7 @@ public class CardProperty {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("greatestPower")) {
|
} else if (property.startsWith("greatestPower")) {
|
||||||
CardCollectionView cards = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), Presets.CREATURES);
|
CardCollectionView cards = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.CREATURES);
|
||||||
if (property.contains("ControlledBy")) {
|
if (property.contains("ControlledBy")) {
|
||||||
FCollectionView<Player> p = AbilityUtils.getDefinedPlayers(source, property.split("ControlledBy")[1], spellAbility);
|
FCollectionView<Player> p = AbilityUtils.getDefinedPlayers(source, property.split("ControlledBy")[1], spellAbility);
|
||||||
cards = CardLists.filterControlledBy(cards, p);
|
cards = CardLists.filterControlledBy(cards, p);
|
||||||
@@ -1319,14 +1318,14 @@ public class CardProperty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("yardGreatestPower")) {
|
} else if (property.startsWith("yardGreatestPower")) {
|
||||||
final CardCollectionView cards = CardLists.filter(sourceController.getCardsIn(ZoneType.Graveyard), Presets.CREATURES);
|
final CardCollectionView cards = CardLists.filter(sourceController.getCardsIn(ZoneType.Graveyard), CardPredicates.CREATURES);
|
||||||
for (final Card crd : cards) {
|
for (final Card crd : cards) {
|
||||||
if (crd.getNetPower() > card.getNetPower()) {
|
if (crd.getNetPower() > card.getNetPower()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("leastPower")) {
|
} else if (property.startsWith("leastPower")) {
|
||||||
CardCollectionView cards = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), Presets.CREATURES);
|
CardCollectionView cards = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.CREATURES);
|
||||||
if (property.contains("ControlledBy")) {
|
if (property.contains("ControlledBy")) {
|
||||||
FCollectionView<Player> p = AbilityUtils.getDefinedPlayers(source, property.split("ControlledBy")[1], spellAbility);
|
FCollectionView<Player> p = AbilityUtils.getDefinedPlayers(source, property.split("ControlledBy")[1], spellAbility);
|
||||||
cards = CardLists.filterControlledBy(cards, p);
|
cards = CardLists.filterControlledBy(cards, p);
|
||||||
@@ -1340,7 +1339,7 @@ public class CardProperty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("leastToughness")) {
|
} else if (property.startsWith("leastToughness")) {
|
||||||
CardCollectionView cards = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), Presets.CREATURES);
|
CardCollectionView cards = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.CREATURES);
|
||||||
if (property.contains("ControlledBy")) { // 4/25/2023 only used for adventure mode Death Ring
|
if (property.contains("ControlledBy")) { // 4/25/2023 only used for adventure mode Death Ring
|
||||||
FCollectionView<Player> p = AbilityUtils.getDefinedPlayers(source, property.split("ControlledBy")[1], spellAbility);
|
FCollectionView<Player> p = AbilityUtils.getDefinedPlayers(source, property.split("ControlledBy")[1], spellAbility);
|
||||||
cards = CardLists.filterControlledBy(cards, p);
|
cards = CardLists.filterControlledBy(cards, p);
|
||||||
@@ -1363,7 +1362,7 @@ public class CardProperty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ("NonLandPermanent".equals(prop)) {
|
if ("NonLandPermanent".equals(prop)) {
|
||||||
cards = CardLists.filter(cards, CardPredicates.Presets.NONLAND_PERMANENTS);
|
cards = CardLists.filter(cards, CardPredicates.NONLAND_PERMANENTS);
|
||||||
} else {
|
} else {
|
||||||
cards = CardLists.getType(cards, prop);
|
cards = CardLists.getType(cards, prop);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -222,11 +222,11 @@ public class Combat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final CardCollection getDefendingPlaneswalkers() {
|
public final CardCollection getDefendingPlaneswalkers() {
|
||||||
return CardLists.filter(Iterables.filter(attackableEntries, Card.class), CardPredicates.Presets.PLANESWALKERS);
|
return CardLists.filter(Iterables.filter(attackableEntries, Card.class), CardPredicates.PLANESWALKERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final CardCollection getDefendingBattles() {
|
public final CardCollection getDefendingBattles() {
|
||||||
return CardLists.filter(Iterables.filter(attackableEntries, Card.class), CardPredicates.Presets.BATTLES);
|
return CardLists.filter(Iterables.filter(attackableEntries, Card.class), CardPredicates.BATTLES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Map<Card, GameEntity> getAttackersAndDefenders() {
|
public final Map<Card, GameEntity> getAttackersAndDefenders() {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class CombatUtil {
|
|||||||
|
|
||||||
// Relevant battles (protected by the attacking player's opponents)
|
// Relevant battles (protected by the attacking player's opponents)
|
||||||
final Game game = playerWhoAttacks.getGame();
|
final Game game = playerWhoAttacks.getGame();
|
||||||
final CardCollection battles = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.BATTLES);
|
final CardCollection battles = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.BATTLES);
|
||||||
for (Card battle : battles) {
|
for (Card battle : battles) {
|
||||||
if (battle.getType().hasSubtype("Siege") && battle.getProtectingPlayer().isOpponentOf(playerWhoAttacks)) {
|
if (battle.getType().hasSubtype("Siege") && battle.getProtectingPlayer().isOpponentOf(playerWhoAttacks)) {
|
||||||
defenders.add(battle);
|
defenders.add(battle);
|
||||||
|
|||||||
@@ -338,11 +338,11 @@ public class CostAdjustment {
|
|||||||
|
|
||||||
final Player activator = sa.getActivatingPlayer();
|
final Player activator = sa.getActivatingPlayer();
|
||||||
CardCollectionView untappedCards = CardLists.filter(activator.getCardsIn(ZoneType.Battlefield),
|
CardCollectionView untappedCards = CardLists.filter(activator.getCardsIn(ZoneType.Battlefield),
|
||||||
CardPredicates.Presets.CAN_TAP);
|
CardPredicates.CAN_TAP);
|
||||||
if (improvise) {
|
if (improvise) {
|
||||||
untappedCards = CardLists.filter(untappedCards, CardPredicates.Presets.ARTIFACTS);
|
untappedCards = CardLists.filter(untappedCards, CardPredicates.ARTIFACTS);
|
||||||
} else {
|
} else {
|
||||||
untappedCards = CardLists.filter(untappedCards, CardPredicates.Presets.CREATURES);
|
untappedCards = CardLists.filter(untappedCards, CardPredicates.CREATURES);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Card, ManaCostShard> convokedCards = activator.getController().chooseCardsForConvokeOrImprovise(sa,
|
Map<Card, ManaCostShard> convokedCards = activator.getController().chooseCardsForConvokeOrImprovise(sa,
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ package forge.game.cost;
|
|||||||
import forge.card.CardType;
|
import forge.card.CardType;
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
@@ -67,7 +66,7 @@ public class CostTapType extends CostPartWithList {
|
|||||||
if (!canTapSource) {
|
if (!canTapSource) {
|
||||||
typeList.remove(source);
|
typeList.remove(source);
|
||||||
}
|
}
|
||||||
typeList = CardLists.filter(typeList, ability.isCrew() ? Presets.CAN_CREW : Presets.CAN_TAP);
|
typeList = CardLists.filter(typeList, ability.isCrew() ? CardPredicates.CAN_CREW : CardPredicates.CAN_TAP);
|
||||||
|
|
||||||
return typeList.size();
|
return typeList.size();
|
||||||
}
|
}
|
||||||
@@ -165,7 +164,7 @@ public class CostTapType extends CostPartWithList {
|
|||||||
if (!canTapSource) {
|
if (!canTapSource) {
|
||||||
typeList.remove(source);
|
typeList.remove(source);
|
||||||
}
|
}
|
||||||
typeList = CardLists.filter(typeList, ability.isCrew() ? Presets.CAN_CREW : Presets.CAN_TAP);
|
typeList = CardLists.filter(typeList, ability.isCrew() ? CardPredicates.CAN_CREW : CardPredicates.CAN_TAP);
|
||||||
|
|
||||||
if (sameType) {
|
if (sameType) {
|
||||||
for (final Card card : typeList) {
|
for (final Card card : typeList) {
|
||||||
|
|||||||
@@ -19,11 +19,7 @@ package forge.game.cost;
|
|||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardCollectionView;
|
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
@@ -90,7 +86,7 @@ public class CostUntapType extends CostPartWithList {
|
|||||||
if (!canUntapSource) {
|
if (!canUntapSource) {
|
||||||
typeList.remove(source);
|
typeList.remove(source);
|
||||||
}
|
}
|
||||||
typeList = CardLists.filter(typeList, Presets.TAPPED);
|
typeList = CardLists.filter(typeList, CardPredicates.TAPPED);
|
||||||
|
|
||||||
final int amount = this.getAbilityAmount(ability);
|
final int amount = this.getAbilityAmount(ability);
|
||||||
return (typeList.size() != 0) && (typeList.size() >= amount);
|
return (typeList.size() != 0) && (typeList.size() >= amount);
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import forge.game.ability.AbilityKey;
|
|||||||
import forge.game.ability.effects.AddTurnEffect;
|
import forge.game.ability.effects.AddTurnEffect;
|
||||||
import forge.game.ability.effects.SkipPhaseEffect;
|
import forge.game.ability.effects.SkipPhaseEffect;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.combat.CombatUtil;
|
import forge.game.combat.CombatUtil;
|
||||||
import forge.game.cost.CostEnlist;
|
import forge.game.cost.CostEnlist;
|
||||||
@@ -185,7 +184,7 @@ public class PhaseHandler implements java.io.Serializable {
|
|||||||
|
|
||||||
game.getAction().resetActivationsPerTurn();
|
game.getAction().resetActivationsPerTurn();
|
||||||
|
|
||||||
final int lands = CardLists.count(playerTurn.getLandsInPlay(), Presets.UNTAPPED);
|
final int lands = CardLists.count(playerTurn.getLandsInPlay(), CardPredicates.UNTAPPED);
|
||||||
playerTurn.setNumPowerSurgeLands(lands);
|
playerTurn.setNumPowerSurgeLands(lands);
|
||||||
}
|
}
|
||||||
//update tokens
|
//update tokens
|
||||||
@@ -287,7 +286,7 @@ public class PhaseHandler implements java.io.Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// roll for attractions if we have any
|
// roll for attractions if we have any
|
||||||
if (Iterables.any(playerTurn.getCardsIn(ZoneType.Battlefield), Presets.ATTRACTIONS)) {
|
if (Iterables.any(playerTurn.getCardsIn(ZoneType.Battlefield), CardPredicates.ATTRACTIONS)) {
|
||||||
playerTurn.rollToVisitAttractions();
|
playerTurn.rollToVisitAttractions();
|
||||||
}
|
}
|
||||||
table.replaceCounterEffect(game, null, false);
|
table.replaceCounterEffect(game, null, false);
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import forge.game.card.Card;
|
|||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates;
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.card.CardZoneTable;
|
import forge.game.card.CardZoneTable;
|
||||||
import forge.game.keyword.Keyword;
|
import forge.game.keyword.Keyword;
|
||||||
import forge.game.keyword.KeywordInterface;
|
import forge.game.keyword.KeywordInterface;
|
||||||
@@ -113,7 +112,7 @@ public class Untap extends Phase {
|
|||||||
*/
|
*/
|
||||||
private void doUntap() {
|
private void doUntap() {
|
||||||
final Player player = game.getPhaseHandler().getPlayerTurn();
|
final Player player = game.getPhaseHandler().getPlayerTurn();
|
||||||
final Predicate<Card> tappedCanUntap = Presets.TAPPED.and(CANUNTAP);
|
final Predicate<Card> tappedCanUntap = CardPredicates.TAPPED.and(CANUNTAP);
|
||||||
Map<Player, CardCollection> untapMap = Maps.newHashMap();
|
Map<Player, CardCollection> untapMap = Maps.newHashMap();
|
||||||
|
|
||||||
CardCollection list = new CardCollection(player.getCardsIn(ZoneType.Battlefield));
|
CardCollection list = new CardCollection(player.getCardsIn(ZoneType.Battlefield));
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import forge.game.ability.ApiType;
|
|||||||
import forge.game.ability.effects.DetachedCardEffect;
|
import forge.game.ability.effects.DetachedCardEffect;
|
||||||
import forge.game.ability.effects.RollDiceEffect;
|
import forge.game.ability.effects.RollDiceEffect;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
|
||||||
import forge.game.event.*;
|
import forge.game.event.*;
|
||||||
import forge.game.keyword.*;
|
import forge.game.keyword.*;
|
||||||
import forge.game.keyword.KeywordCollection.KeywordCollectionView;
|
import forge.game.keyword.KeywordCollection.KeywordCollectionView;
|
||||||
@@ -63,7 +62,6 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -2084,7 +2082,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final boolean hasMetalcraft() {
|
public final boolean hasMetalcraft() {
|
||||||
return CardLists.count(getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.ARTIFACTS) >= 3;
|
return CardLists.count(getCardsIn(ZoneType.Battlefield), CardPredicates.ARTIFACTS) >= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean hasDesert() {
|
public final boolean hasDesert() {
|
||||||
@@ -2123,7 +2121,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final boolean hasLandfall() {
|
public final boolean hasLandfall() {
|
||||||
return Iterables.any(getZone(ZoneType.Battlefield).getCardsAddedThisTurn(null), CardPredicates.Presets.LANDS);
|
return Iterables.any(getZone(ZoneType.Battlefield).getCardsAddedThisTurn(null), CardPredicates.LANDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasFerocious() {
|
public boolean hasFerocious() {
|
||||||
@@ -2436,29 +2434,29 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
* use to get a list of creatures in play for a given player.
|
* use to get a list of creatures in play for a given player.
|
||||||
*/
|
*/
|
||||||
public CardCollection getCreaturesInPlay() {
|
public CardCollection getCreaturesInPlay() {
|
||||||
return CardLists.filter(getCardsIn(ZoneType.Battlefield), Presets.CREATURES);
|
return CardLists.filter(getCardsIn(ZoneType.Battlefield), CardPredicates.CREATURES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardCollection getPlaneswalkersInPlay() {
|
public CardCollection getPlaneswalkersInPlay() {
|
||||||
return CardLists.filter(getCardsIn(ZoneType.Battlefield), Presets.PLANESWALKERS);
|
return CardLists.filter(getCardsIn(ZoneType.Battlefield), CardPredicates.PLANESWALKERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardCollection getBattlesInPlay() {
|
public CardCollection getBattlesInPlay() {
|
||||||
return CardLists.filter(getCardsIn(ZoneType.Battlefield), Presets.BATTLES);
|
return CardLists.filter(getCardsIn(ZoneType.Battlefield), CardPredicates.BATTLES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* use to get a list of tokens in play for a given player.
|
* use to get a list of tokens in play for a given player.
|
||||||
*/
|
*/
|
||||||
public CardCollection getTokensInPlay() {
|
public CardCollection getTokensInPlay() {
|
||||||
return CardLists.filter(getCardsIn(ZoneType.Battlefield), Presets.TOKEN);
|
return CardLists.filter(getCardsIn(ZoneType.Battlefield), CardPredicates.TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* use to get a list of all lands a given player has on the battlefield.
|
* use to get a list of all lands a given player has on the battlefield.
|
||||||
*/
|
*/
|
||||||
public CardCollection getLandsInPlay() {
|
public CardCollection getLandsInPlay() {
|
||||||
return CardLists.filter(getCardsIn(ZoneType.Battlefield), Presets.LANDS);
|
return CardLists.filter(getCardsIn(ZoneType.Battlefield), CardPredicates.LANDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCardInPlay(final String cardName) {
|
public boolean isCardInPlay(final String cardName) {
|
||||||
@@ -3596,7 +3594,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isCursed() {
|
public final boolean isCursed() {
|
||||||
return CardLists.count(getAttachedCards(), CardPredicates.Presets.CURSE) > 0;
|
return CardLists.count(getAttachedCards(), CardPredicates.CURSE) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canDiscardBy(SpellAbility sa, final boolean effect) {
|
public boolean canDiscardBy(SpellAbility sa, final boolean effect) {
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ import java.util.Map;
|
|||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import forge.item.PaperCardPredicates;
|
||||||
import forge.util.Iterables;
|
import forge.util.Iterables;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
import forge.item.IPaperCard;
|
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.localinstance.properties.ForgeConstants;
|
import forge.localinstance.properties.ForgeConstants;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
@@ -374,7 +374,7 @@ public class ImportSourceAnalyzer {
|
|||||||
cardFileNamesBySet = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
cardFileNamesBySet = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
for (final CardEdition ce : FModel.getMagicDb().getEditions()) {
|
for (final CardEdition ce : FModel.getMagicDb().getEditions()) {
|
||||||
final Map<String, String> cardFileNames = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
final Map<String, String> cardFileNames = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
final Predicate<PaperCard> filter = IPaperCard.Predicates.printedInSet(ce.getCode());
|
final Predicate<PaperCard> filter = PaperCardPredicates.printedInSet(ce.getCode());
|
||||||
addSetCards(cardFileNames, FModel.getMagicDb().getCommonCards().getAllCards(), filter);
|
addSetCards(cardFileNames, FModel.getMagicDb().getCommonCards().getAllCards(), filter);
|
||||||
addSetCards(cardFileNames, FModel.getMagicDb().getVariantCards().getAllCards(), filter);
|
addSetCards(cardFileNames, FModel.getMagicDb().getVariantCards().getAllCards(), filter);
|
||||||
cardFileNamesBySet.put(ce.getCode2(), cardFileNames);
|
cardFileNamesBySet.put(ce.getCode2(), cardFileNames);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class CardPowerFilter extends ValueRangeFilter<PaperCard> {
|
|||||||
if (predicate == null) {
|
if (predicate == null) {
|
||||||
return x -> true;
|
return x -> true;
|
||||||
}
|
}
|
||||||
predicate = predicate.and(CardRulesPredicates.Presets.IS_CREATURE);
|
predicate = predicate.and(CardRulesPredicates.IS_CREATURE);
|
||||||
return Predicates.compose(predicate, PaperCard::getRules);
|
return Predicates.compose(predicate, PaperCard::getRules);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class CardToughnessFilter extends ValueRangeFilter<PaperCard> {
|
|||||||
if (predicate == null) {
|
if (predicate == null) {
|
||||||
return x -> true;
|
return x -> true;
|
||||||
}
|
}
|
||||||
predicate = predicate.and(CardRulesPredicates.Presets.IS_CREATURE);
|
predicate = predicate.and(CardRulesPredicates.IS_CREATURE);
|
||||||
return Predicates.compose(predicate, PaperCard::getRules);
|
return Predicates.compose(predicate, PaperCard::getRules);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public abstract class StatTypeFilter<T extends InventoryItem> extends ToggleButt
|
|||||||
protected <U extends InventoryItem> boolean showUnsupportedItem(U item) {
|
protected <U extends InventoryItem> boolean showUnsupportedItem(U item) {
|
||||||
FLabel btnPackOrDeck = buttonMap.get(StatTypes.PACK_OR_DECK); //support special pack/deck case
|
FLabel btnPackOrDeck = buttonMap.get(StatTypes.PACK_OR_DECK); //support special pack/deck case
|
||||||
if (btnPackOrDeck != null && btnPackOrDeck.isSelected()) {
|
if (btnPackOrDeck != null && btnPackOrDeck.isSelected()) {
|
||||||
return ItemPredicate.Presets.IS_PACK_OR_DECK.test(item);
|
return ItemPredicate.IS_PACK_OR_DECK.test(item);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ public abstract class StatTypeFilter<T extends InventoryItem> extends ToggleButt
|
|||||||
|
|
||||||
FLabel btnPackOrDeck = buttonMap.get(StatTypes.PACK_OR_DECK);
|
FLabel btnPackOrDeck = buttonMap.get(StatTypes.PACK_OR_DECK);
|
||||||
if (btnPackOrDeck != null) { //support special pack/deck case
|
if (btnPackOrDeck != null) { //support special pack/deck case
|
||||||
int count = items.countAll(ItemPredicate.Presets.IS_PACK_OR_DECK, InventoryItem.class);
|
int count = items.countAll(ItemPredicate.IS_PACK_OR_DECK, InventoryItem.class);
|
||||||
btnPackOrDeck.setText(String.valueOf(count));
|
btnPackOrDeck.setText(String.valueOf(count));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.NOT_BASIC_LAND, PaperCard::getRules);
|
final Predicate<PaperCard> notBasicLand = Predicates.compose(CardRulesPredicates.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));
|
||||||
|
|
||||||
|
|||||||
@@ -82,14 +82,14 @@ public final class CEditorCommander extends CDeckEditor<Deck> {
|
|||||||
CardDb commonCards = FModel.getMagicDb().getCommonCards();
|
CardDb commonCards = FModel.getMagicDb().getCommonCards();
|
||||||
if (gameType == GameType.Brawl){
|
if (gameType == GameType.Brawl){
|
||||||
GameFormat format = FModel.getFormats().get("Brawl");
|
GameFormat format = FModel.getFormats().get("Brawl");
|
||||||
Predicate<CardRules> commanderFilter = CardRulesPredicates.Presets.CAN_BE_BRAWL_COMMANDER;
|
Predicate<CardRules> commanderFilter = CardRulesPredicates.CAN_BE_BRAWL_COMMANDER;
|
||||||
commanderPool = ItemPool.createFrom(commonCards.getAllCardsNoAlt(format.getFilterPrinted().and(Predicates.compose(commanderFilter, PaperCard::getRules))), PaperCard.class);
|
commanderPool = ItemPool.createFrom(commonCards.getAllCardsNoAlt(format.getFilterPrinted().and(Predicates.compose(commanderFilter, PaperCard::getRules))), PaperCard.class);
|
||||||
normalPool = ItemPool.createFrom(format.getAllCards(), PaperCard.class);
|
normalPool = ItemPool.createFrom(format.getAllCards(), PaperCard.class);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Predicate<CardRules> commanderFilter = gameType == GameType.Oathbreaker
|
Predicate<CardRules> commanderFilter = gameType == GameType.Oathbreaker
|
||||||
? CardRulesPredicates.Presets.CAN_BE_OATHBREAKER.or(CardRulesPredicates.Presets.CAN_BE_SIGNATURE_SPELL)
|
? CardRulesPredicates.CAN_BE_OATHBREAKER.or(CardRulesPredicates.CAN_BE_SIGNATURE_SPELL)
|
||||||
: CardRulesPredicates.Presets.CAN_BE_COMMANDER;
|
: CardRulesPredicates.CAN_BE_COMMANDER;
|
||||||
commanderPool = ItemPool.createFrom(commonCards.getAllCardsNoAlt(Predicates.compose(commanderFilter, PaperCard::getRules)),PaperCard.class);
|
commanderPool = ItemPool.createFrom(commonCards.getAllCardsNoAlt(Predicates.compose(commanderFilter, PaperCard::getRules)),PaperCard.class);
|
||||||
normalPool = ItemPool.createFrom(commonCards.getAllCardsNoAlt(), PaperCard.class);
|
normalPool = ItemPool.createFrom(commonCards.getAllCardsNoAlt(), PaperCard.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ public final class CEditorQuest extends CDeckEditor<Deck> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ItemPool<PaperCard> getCommanderCardPool(){
|
private ItemPool<PaperCard> getCommanderCardPool(){
|
||||||
Predicate<PaperCard> commanderPredicate = Predicates.compose(CardRulesPredicates.Presets.CAN_BE_COMMANDER, PaperCard::getRules);
|
Predicate<PaperCard> commanderPredicate = Predicates.compose(CardRulesPredicates.CAN_BE_COMMANDER, PaperCard::getRules);
|
||||||
return getRemainingCardPool().getFilteredPool(commanderPredicate);
|
return getRemainingCardPool().getFilteredPool(commanderPredicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,16 +76,16 @@ public enum CStatistics implements ICDoc {
|
|||||||
// Hack-ish: avoid /0 cases, but still populate labels :)
|
// Hack-ish: avoid /0 cases, but still populate labels :)
|
||||||
if (total == 0) { total = 1; }
|
if (total == 0) { total = 1; }
|
||||||
|
|
||||||
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblCreature(), deck, CardRulesPredicates.Presets.IS_CREATURE, total);
|
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblCreature(), deck, CardRulesPredicates.IS_CREATURE, total);
|
||||||
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblLand(), deck, CardRulesPredicates.Presets.IS_LAND, total);
|
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblLand(), deck, CardRulesPredicates.IS_LAND, total);
|
||||||
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblEnchantment(), deck, CardRulesPredicates.Presets.IS_ENCHANTMENT, total);
|
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblEnchantment(), deck, CardRulesPredicates.IS_ENCHANTMENT, total);
|
||||||
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblArtifact(), deck, CardRulesPredicates.Presets.IS_ARTIFACT, total);
|
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblArtifact(), deck, CardRulesPredicates.IS_ARTIFACT, total);
|
||||||
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblInstant(), deck, CardRulesPredicates.Presets.IS_INSTANT, total);
|
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblInstant(), deck, CardRulesPredicates.IS_INSTANT, total);
|
||||||
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblSorcery(), deck, CardRulesPredicates.Presets.IS_SORCERY, total);
|
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblSorcery(), deck, CardRulesPredicates.IS_SORCERY, total);
|
||||||
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblPlaneswalker(), deck, CardRulesPredicates.Presets.IS_PLANESWALKER, total);
|
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblPlaneswalker(), deck, CardRulesPredicates.IS_PLANESWALKER, total);
|
||||||
|
|
||||||
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblMulti(), deck, CardRulesPredicates.Presets.IS_MULTICOLOR, total);
|
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblMulti(), deck, CardRulesPredicates.IS_MULTICOLOR, total);
|
||||||
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblColorless(), deck, CardRulesPredicates.Presets.IS_COLORLESS, total);
|
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblColorless(), deck, CardRulesPredicates.IS_COLORLESS, total);
|
||||||
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblBlack(), deck, CardRulesPredicates.isMonoColor(MagicColor.BLACK), total);
|
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblBlack(), deck, CardRulesPredicates.isMonoColor(MagicColor.BLACK), total);
|
||||||
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblBlue(), deck, CardRulesPredicates.isMonoColor(MagicColor.BLUE), total);
|
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblBlue(), deck, CardRulesPredicates.isMonoColor(MagicColor.BLUE), total);
|
||||||
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblGreen(), deck, CardRulesPredicates.isMonoColor(MagicColor.GREEN), total);
|
setLabelValue(VStatistics.SINGLETON_INSTANCE.getLblGreen(), deck, CardRulesPredicates.isMonoColor(MagicColor.GREEN), total);
|
||||||
|
|||||||
@@ -57,16 +57,16 @@ public class CStatisticsImporter {
|
|||||||
// Hack-ish: avoid /0 cases, but still populate labels :)
|
// Hack-ish: avoid /0 cases, but still populate labels :)
|
||||||
if (total == 0) { total = 1; }
|
if (total == 0) { total = 1; }
|
||||||
|
|
||||||
setLabelValue(this.view.getLblCreature(), deck, CardRulesPredicates.Presets.IS_CREATURE, total);
|
setLabelValue(this.view.getLblCreature(), deck, CardRulesPredicates.IS_CREATURE, total);
|
||||||
setLabelValue(this.view.getLblLand(), deck, CardRulesPredicates.Presets.IS_LAND, total);
|
setLabelValue(this.view.getLblLand(), deck, CardRulesPredicates.IS_LAND, total);
|
||||||
setLabelValue(this.view.getLblEnchantment(), deck, CardRulesPredicates.Presets.IS_ENCHANTMENT, total);
|
setLabelValue(this.view.getLblEnchantment(), deck, CardRulesPredicates.IS_ENCHANTMENT, total);
|
||||||
setLabelValue(this.view.getLblArtifact(), deck, CardRulesPredicates.Presets.IS_ARTIFACT, total);
|
setLabelValue(this.view.getLblArtifact(), deck, CardRulesPredicates.IS_ARTIFACT, total);
|
||||||
setLabelValue(this.view.getLblInstant(), deck, CardRulesPredicates.Presets.IS_INSTANT, total);
|
setLabelValue(this.view.getLblInstant(), deck, CardRulesPredicates.IS_INSTANT, total);
|
||||||
setLabelValue(this.view.getLblSorcery(), deck, CardRulesPredicates.Presets.IS_SORCERY, total);
|
setLabelValue(this.view.getLblSorcery(), deck, CardRulesPredicates.IS_SORCERY, total);
|
||||||
setLabelValue(this.view.getLblPlaneswalker(), deck, CardRulesPredicates.Presets.IS_PLANESWALKER, total);
|
setLabelValue(this.view.getLblPlaneswalker(), deck, CardRulesPredicates.IS_PLANESWALKER, total);
|
||||||
|
|
||||||
setLabelValue(this.view.getLblMulti(), deck, CardRulesPredicates.Presets.IS_MULTICOLOR, total);
|
setLabelValue(this.view.getLblMulti(), deck, CardRulesPredicates.IS_MULTICOLOR, total);
|
||||||
setLabelValue(this.view.getLblColorless(), deck, CardRulesPredicates.Presets.IS_COLORLESS, total);
|
setLabelValue(this.view.getLblColorless(), deck, CardRulesPredicates.IS_COLORLESS, total);
|
||||||
setLabelValue(this.view.getLblBlack(), deck, CardRulesPredicates.isMonoColor(MagicColor.BLACK), total);
|
setLabelValue(this.view.getLblBlack(), deck, CardRulesPredicates.isMonoColor(MagicColor.BLACK), total);
|
||||||
setLabelValue(this.view.getLblBlue(), deck, CardRulesPredicates.isMonoColor(MagicColor.BLUE), total);
|
setLabelValue(this.view.getLblBlue(), deck, CardRulesPredicates.isMonoColor(MagicColor.BLUE), total);
|
||||||
setLabelValue(this.view.getLblGreen(), deck, CardRulesPredicates.isMonoColor(MagicColor.GREEN), total);
|
setLabelValue(this.view.getLblGreen(), deck, CardRulesPredicates.isMonoColor(MagicColor.GREEN), total);
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ public class PlanarConquestCommanderGeneraterGA extends PlanarConquestGeneraterG
|
|||||||
|
|
||||||
Iterable<PaperCard> filtered= Iterables.filter(cards,
|
Iterable<PaperCard> filtered= Iterables.filter(cards,
|
||||||
Predicates.compose(CardRulesPredicates.IS_KEPT_IN_AI_DECKS, PaperCard::getRules)
|
Predicates.compose(CardRulesPredicates.IS_KEPT_IN_AI_DECKS, PaperCard::getRules)
|
||||||
.and(Predicates.compose(CardRulesPredicates.Presets.IS_PLANESWALKER, PaperCard::getRules))
|
.and(Predicates.compose(CardRulesPredicates.IS_PLANESWALKER, PaperCard::getRules))
|
||||||
//.and(Predicates.compose(CardRulesPredicates.Presets.IS_LEGENDARY, PaperCard::getRules))
|
//.and(Predicates.compose(CardRulesPredicates.IS_LEGENDARY, PaperCard::getRules))
|
||||||
.and(gameFormat.getFilterPrinted())
|
.and(gameFormat.getFilterPrinted())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public class PlanarConquestGeneraterGA extends AbstractGeneticAlgorithm<Deck> {
|
|||||||
|
|
||||||
Iterable<PaperCard> filtered= Iterables.filter(cards,
|
Iterable<PaperCard> filtered= Iterables.filter(cards,
|
||||||
Predicates.compose(CardRulesPredicates.IS_KEPT_IN_AI_DECKS, PaperCard::getRules)
|
Predicates.compose(CardRulesPredicates.IS_KEPT_IN_AI_DECKS, PaperCard::getRules)
|
||||||
.and(Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard::getRules))
|
.and(Predicates.compose(CardRulesPredicates.IS_NON_LAND, PaperCard::getRules))
|
||||||
.and(gameFormat.getFilterPrinted())
|
.and(gameFormat.getFilterPrinted())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public class PlanarConquestTribalGeneraterGA extends PlanarConquestGeneraterGA {
|
|||||||
Iterable<PaperCard> filteredTribe= Iterables.filter(cards,
|
Iterable<PaperCard> filteredTribe= Iterables.filter(cards,
|
||||||
Predicates.compose(CardRulesPredicates.IS_KEPT_IN_AI_DECKS, PaperCard::getRules)
|
Predicates.compose(CardRulesPredicates.IS_KEPT_IN_AI_DECKS, PaperCard::getRules)
|
||||||
.and(Predicates.compose(CardRulesPredicates.hasCreatureType("Pirate"), PaperCard::getRules))
|
.and(Predicates.compose(CardRulesPredicates.hasCreatureType("Pirate"), PaperCard::getRules))
|
||||||
.and(Predicates.compose(CardRulesPredicates.Presets.IS_CREATURE, PaperCard::getRules))
|
.and(Predicates.compose(CardRulesPredicates.IS_CREATURE, PaperCard::getRules))
|
||||||
.and(gameFormat.getFilterPrinted())
|
.and(gameFormat.getFilterPrinted())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -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.NOT_BASIC_LAND, PaperCard::getRules));
|
CardPool deckNoBasicLands = enemyDeck.getMain().getFilteredPool(Predicates.compose(CardRulesPredicates.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 ));
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class CardPowerFilter extends ValueRangeFilter<PaperCard> {
|
|||||||
if (predicate == null) {
|
if (predicate == null) {
|
||||||
return x -> true;
|
return x -> true;
|
||||||
}
|
}
|
||||||
predicate = predicate.and(CardRulesPredicates.Presets.IS_CREATURE);
|
predicate = predicate.and(CardRulesPredicates.IS_CREATURE);
|
||||||
return Predicates.compose(predicate, PaperCard::getRules);
|
return Predicates.compose(predicate, PaperCard::getRules);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class CardToughnessFilter extends ValueRangeFilter<PaperCard> {
|
|||||||
if (predicate == null) {
|
if (predicate == null) {
|
||||||
return x -> true;
|
return x -> true;
|
||||||
}
|
}
|
||||||
predicate = predicate.and(CardRulesPredicates.Presets.IS_CREATURE);
|
predicate = predicate.and(CardRulesPredicates.IS_CREATURE);
|
||||||
return Predicates.compose(predicate, PaperCard::getRules);
|
return Predicates.compose(predicate, PaperCard::getRules);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public abstract class StatTypeFilter<T extends InventoryItem> extends ToggleButt
|
|||||||
protected <U extends InventoryItem> boolean showUnsupportedItem(U item) {
|
protected <U extends InventoryItem> boolean showUnsupportedItem(U item) {
|
||||||
FLabel btnPackOrDeck = buttonMap.get(StatTypes.PACK_OR_DECK); //support special pack/deck case
|
FLabel btnPackOrDeck = buttonMap.get(StatTypes.PACK_OR_DECK); //support special pack/deck case
|
||||||
if (btnPackOrDeck != null && btnPackOrDeck.isSelected()) {
|
if (btnPackOrDeck != null && btnPackOrDeck.isSelected()) {
|
||||||
return ItemPredicate.Presets.IS_PACK_OR_DECK.test(item);
|
return ItemPredicate.IS_PACK_OR_DECK.test(item);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.NOT_TRUE_BASIC_LAND, PaperCard::getRules));
|
, Predicates.compose(CardRulesPredicates.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.NOT_TRUE_BASIC_LAND, PaperCard::getRules))){
|
Predicates.compose(CardRulesPredicates.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.NOT_TRUE_BASIC_LAND, PaperCard::getRules));
|
, Predicates.compose(CardRulesPredicates.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.NOT_TRUE_BASIC_LAND, PaperCard::getRules))){
|
Predicates.compose(CardRulesPredicates.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())];
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class CommanderDeckGenerator extends DeckProxy implements Comparable<Comm
|
|||||||
Predicate<CardRules> canPlay = isForAi ? DeckGeneratorBase.AI_CAN_PLAY : CardRulesPredicates.IS_KEPT_IN_RANDOM_DECKS;
|
Predicate<CardRules> canPlay = isForAi ? DeckGeneratorBase.AI_CAN_PLAY : CardRulesPredicates.IS_KEPT_IN_RANDOM_DECKS;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Iterable<PaperCard> legends = Iterables.filter(uniqueCards.toFlatList(), format.isLegalCardPredicate()
|
Iterable<PaperCard> legends = Iterables.filter(uniqueCards.toFlatList(), format.isLegalCardPredicate()
|
||||||
.and(Predicates.compose(CardRulesPredicates.Presets.CAN_BE_BRAWL_COMMANDER.and(canPlay), PaperCard::getRules)));
|
.and(Predicates.compose(CardRulesPredicates.CAN_BE_BRAWL_COMMANDER.and(canPlay), PaperCard::getRules)));
|
||||||
final List<DeckProxy> decks = new ArrayList<>();
|
final List<DeckProxy> decks = new ArrayList<>();
|
||||||
for (PaperCard legend: legends) {
|
for (PaperCard legend: legends) {
|
||||||
decks.add(new CommanderDeckGenerator(legend, format, isForAi, isCardGen));
|
decks.add(new CommanderDeckGenerator(legend, format, isForAi, isCardGen));
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user