mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
DeckFormat: A deck can have any number of cards named CARDNAME.
This commit is contained in:
committed by
Michael Kamensky
parent
af3c645521
commit
0606a00942
@@ -20,6 +20,8 @@ package forge.deck;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.StaticData;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.CardRulesPredicates;
|
||||
@@ -47,7 +49,7 @@ public enum DeckFormat {
|
||||
QuestDeck ( Range.between(40, Integer.MAX_VALUE), Range.between(0, 15), 4),
|
||||
Limited ( Range.between(40, Integer.MAX_VALUE), null, Integer.MAX_VALUE),
|
||||
Commander ( Range.is(99), Range.between(0, 10), 1, new Predicate<CardRules>() {
|
||||
private final Set<String> bannedCards = new HashSet<String>(Arrays.asList(
|
||||
private final Set<String> bannedCards = ImmutableSet.of(
|
||||
"Adriana's Valor", "Advantageous Proclamation", "Amulet of Quoz", "Ancestral Recall", "Assemble the Rank and Vile",
|
||||
"Backup Plan", "Balance", "Biorhythm", "Black Lotus", "Brago's Favor", "Braids, Cabal Minion", "Bronze Tablet",
|
||||
"Channel", "Chaos Orb", "Coalition Victory", "Contract from Below", "Darkpact", "Demonic Attorney", "Double Stroke",
|
||||
@@ -59,7 +61,7 @@ public enum DeckFormat {
|
||||
"Rebirth", "Recurring Nightmare", "Rofellos, Llanowar Emissary", "Secret Summoning", "Secrets of Paradise",
|
||||
"Sentinel Dispatch", "Shahrazad", "Sovereign's Realm", "Summoner's Bond", "Sundering Titan", "Sway of the Stars",
|
||||
"Sylvan Primordial", "Tempest Efreet", "Time Vault", "Time Walk", "Timmerian Fiends", "Tinker", "Tolarian Academy",
|
||||
"Trade Secrets", "Unexpected Potential", "Upheaval", "Weight Advantage", "Worldfire", "Worldknit", "Yawgmoth's Bargain"));
|
||||
"Trade Secrets", "Unexpected Potential", "Upheaval", "Weight Advantage", "Worldfire", "Worldknit", "Yawgmoth's Bargain");
|
||||
@Override
|
||||
public boolean apply(CardRules rules) {
|
||||
if (bannedCards.contains(rules.getName())) {
|
||||
@@ -70,8 +72,8 @@ public enum DeckFormat {
|
||||
}),
|
||||
Pauper ( Range.is(60), Range.between(0, 10), 1),
|
||||
Brawl ( Range.is(59), Range.between(0, 15), 1, null, new Predicate<PaperCard>() {
|
||||
private final Set<String> bannedCards = new HashSet<String>(Arrays.asList(
|
||||
"Baral, Chief of Compliance","Smuggler's Copter","Sorcerous Spyglass"));
|
||||
private final Set<String> bannedCards = ImmutableSet.of(
|
||||
"Baral, Chief of Compliance","Smuggler's Copter","Sorcerous Spyglass");
|
||||
@Override
|
||||
public boolean apply(PaperCard card) {
|
||||
//why do we need to hard code the bannings here - they are defined in the GameFormat predicate used below
|
||||
@@ -81,7 +83,7 @@ public enum DeckFormat {
|
||||
return StaticData.instance() == null ? false : StaticData.instance().getBrawlPredicate().apply(card);
|
||||
}
|
||||
}) {
|
||||
private final ImmutableSet<String> bannedCommanders = ImmutableSet.of("Baral, Chief of Compliance");
|
||||
private final Set<String> bannedCommanders = ImmutableSet.of("Baral, Chief of Compliance");
|
||||
|
||||
@Override
|
||||
public boolean isLegalCommander(CardRules rules) {
|
||||
@@ -89,11 +91,11 @@ public enum DeckFormat {
|
||||
}
|
||||
},
|
||||
TinyLeaders ( Range.is(49), Range.between(0, 10), 1, new Predicate<CardRules>() {
|
||||
private final Set<String> bannedCards = new HashSet<String>(Arrays.asList(
|
||||
private final Set<String> bannedCards = ImmutableSet.of(
|
||||
"Ancestral Recall", "Balance", "Black Lotus", "Black Vise", "Channel", "Chaos Orb", "Contract From Below", "Counterbalance", "Darkpact", "Demonic Attorney", "Demonic Tutor", "Earthcraft", "Edric, Spymaster of Trest", "Falling Star",
|
||||
"Fastbond", "Flash", "Goblin Recruiter", "Grindstone", "Hermit Druid", "Imperial Seal", "Jeweled Bird", "Karakas", "Library of Alexandria", "Mana Crypt", "Mana Drain", "Mana Vault", "Metalworker", "Mind Twist", "Mishra's Workshop",
|
||||
"Mox Emerald", "Mox Jet", "Mox Pearl", "Mox Ruby", "Mox Sapphire", "Necropotence", "Shahrazad", "Skullclamp", "Sol Ring", "Strip Mine", "Survival of the Fittest", "Sword of Body and Mind", "Time Vault", "Time Walk", "Timetwister",
|
||||
"Timmerian Fiends", "Tolarian Academy", "Umezawa's Jitte", "Vampiric Tutor", "Wheel of Fortune", "Yawgmoth's Will"));
|
||||
"Timmerian Fiends", "Tolarian Academy", "Umezawa's Jitte", "Vampiric Tutor", "Wheel of Fortune", "Yawgmoth's Will");
|
||||
|
||||
@Override
|
||||
public boolean apply(CardRules rules) {
|
||||
@@ -112,7 +114,7 @@ public enum DeckFormat {
|
||||
return true;
|
||||
}
|
||||
}) {
|
||||
private final ImmutableSet<String> bannedCommanders = ImmutableSet.of("Derevi, Empyrial Tactician", "Erayo, Soratami Ascendant", "Rofellos, Llanowar Emissary");
|
||||
private final Set<String> bannedCommanders = ImmutableSet.of("Derevi, Empyrial Tactician", "Erayo, Soratami Ascendant", "Rofellos, Llanowar Emissary");
|
||||
|
||||
@Override
|
||||
public boolean isLegalCommander(CardRules rules) {
|
||||
@@ -141,13 +143,6 @@ public enum DeckFormat {
|
||||
private final static String ADVPROCLAMATION = "Advantageous Proclamation";
|
||||
private final static String SOVREALM = "Sovereign's Realm";
|
||||
|
||||
private static final List<String> limitExceptions = Arrays.asList(
|
||||
new String[]{"Relentless Rats", "Shadowborn Apostle", "Rat Colony"});
|
||||
|
||||
public static List<String> getLimitExceptions(){
|
||||
return limitExceptions;
|
||||
}
|
||||
|
||||
private DeckFormat(Range<Integer> mainRange0, Range<Integer> sideRange0, int maxCardCopies0, Predicate<CardRules> cardPoolFilter0, Predicate<PaperCard> paperCardPoolFilter0) {
|
||||
mainRange = mainRange0;
|
||||
sideRange = sideRange0;
|
||||
@@ -342,7 +337,6 @@ public enum DeckFormat {
|
||||
//basic lands, Shadowborn Apostle, Relentless Rats and Rat Colony
|
||||
|
||||
final CardPool allCards = deck.getAllCardsInASinglePool(hasCommander());
|
||||
final ImmutableSet<String> limitExceptions = ImmutableSet.of("Relentless Rats", "Shadowborn Apostle", "Rat Colony");
|
||||
|
||||
// should group all cards by name, so that different editions of same card are really counted as the same card
|
||||
for (final Entry<String, Integer> cp : Aggregates.groupSumBy(allCards, PaperCard.FN_GET_NAME)) {
|
||||
@@ -351,8 +345,7 @@ public enum DeckFormat {
|
||||
return TextUtil.concatWithSpace("contains the nonexisting card", cp.getKey());
|
||||
}
|
||||
|
||||
final boolean canHaveMultiple = simpleCard.getRules().getType().isBasicLand() || limitExceptions.contains(cp.getKey());
|
||||
if (!canHaveMultiple && cp.getValue() > maxCopies) {
|
||||
if (!canHaveAnyNumberOf(simpleCard) && cp.getValue() > maxCopies) {
|
||||
return TextUtil.concatWithSpace("must not contain more than", String.valueOf(maxCopies), "copies of the card", cp.getKey());
|
||||
}
|
||||
}
|
||||
@@ -370,6 +363,12 @@ public enum DeckFormat {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean canHaveAnyNumberOf(final IPaperCard icard) {
|
||||
return icard.getRules().getType().isBasicLand()
|
||||
|| Iterables.contains(icard.getRules().getMainPart().getKeywords(),
|
||||
"A deck can have any number of cards named CARDNAME.");
|
||||
}
|
||||
|
||||
public static String getPlaneSectionConformanceProblem(final CardPool planes) {
|
||||
//Must contain at least 10 planes/phenomenons, but max 2 phenomenons. Singleton.
|
||||
if (planes == null || planes.countAll() < 10) {
|
||||
|
||||
@@ -201,8 +201,7 @@ public abstract class ACEditorBase<TItem extends InventoryItem, TModel extends D
|
||||
int qty = itemEntry.getValue();
|
||||
|
||||
int max;
|
||||
if (deck == null || card == null || card.getRules().getType().isBasic() ||
|
||||
limit == CardLimit.None || DeckFormat.getLimitExceptions().contains(card.getName())) {
|
||||
if (deck == null || card == null || limit == CardLimit.None || DeckFormat.canHaveAnyNumberOf(card)) {
|
||||
max = Integer.MAX_VALUE;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -730,7 +730,7 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
||||
if (deck == null || card == null) {
|
||||
max = Integer.MAX_VALUE;
|
||||
}
|
||||
else if (limit == CardLimit.None || card.getRules().getType().isBasic() || DeckFormat.getLimitExceptions().contains(card.getName())) {
|
||||
else if (limit == CardLimit.None || DeckFormat.canHaveAnyNumberOf(card)) {
|
||||
max = Integer.MAX_VALUE;
|
||||
if (parentScreen.isLimitedEditor() && !isAddSource) {
|
||||
//prevent adding more than is in other pool when editing limited decks
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
Name:Rat Colony
|
||||
ManaCost:1 B
|
||||
Types:Creature Rat
|
||||
Text:A deck can have any number of cards named Rat Colony.
|
||||
PT:2/1
|
||||
K:A deck can have any number of cards named CARDNAME.
|
||||
S:Mode$ Continuous | Affected$ Card.Self | AddPower$ X | References$ X | Description$ CARDNAME gets +1/+0 for each other Rat you control.
|
||||
SVar:X:Count$Valid Rat.YouCtrl+Other
|
||||
SVar:BuffedBy:Rat
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
Name:Relentless Rats
|
||||
ManaCost:1 B B
|
||||
Types:Creature Rat
|
||||
Text:A deck can have any number of cards named Relentless Rats.
|
||||
PT:2/2
|
||||
K:A deck can have any number of cards named CARDNAME.
|
||||
S:Mode$ Continuous | Affected$ Card.Self | AddPower$ X | AddToughness$ X | References$ X | Description$ CARDNAME gets +1/+1 for each other creature on the battlefield named Relentless Rats.
|
||||
SVar:X:Count$Valid Creature.namedRelentless Rats+Other
|
||||
SVar:BuffedBy:Creature.namedRelentless Rats
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
Name:Shadowborn Apostle
|
||||
ManaCost:B
|
||||
Types:Creature Human Cleric
|
||||
Text:A deck can have any number of cards named Shadowborn Apostle.
|
||||
PT:1/1
|
||||
K:A deck can have any number of cards named CARDNAME.
|
||||
A:AB$ ChangeZone | Cost$ B Sac<6/Creature.namedShadowborn Apostle/creatures named Shadowborn Apostle> | Origin$ Library | Destination$ Battlefield | ChangeType$ Creature.Demon | ChangeNum$ 1 | SpellDescription$ Search your library for a Demon creature, put it onto the battlefield, then shuffle your library.
|
||||
DeckNeeds:Name$Shadowborn Apostle
|
||||
DeckNeeds:Type$Demon
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
Name:Persistent Petitioners
|
||||
ManaCost:1 U
|
||||
Types:Creature Human Advisor
|
||||
PT:1/3
|
||||
K:A deck can have any number of cards named CARDNAME.
|
||||
A:AB$ Mill | Cost$ 1 T | NumCards$ 1 | ValidTgts$ Player | TgtPrompt$ Choose a player | SpellDescription$ Target player puts the top card of their library into their graveyard.
|
||||
A:AB$ Mill | Cost$ tapXType<4/Advisor> | NumCards$ 12 | ValidTgts$ Player | TgtPrompt$ Choose a player | SpellDescription$ Target player puts the top twelve cards of their library into their graveyard.
|
||||
SVar:BuffedBy:Creature.namedPersistent Petitioners
|
||||
DeckNeeds:Type$Advisor
|
||||
Oracle:{1}, {T}: Target player puts the top card of their library into their graveyard.\nTap four untapped Advisors you control: Target player puts the top twelve cards of their library into their graveyard.\nA deck can have any number of cards named Persistent Petitioners.
|
||||
@@ -358,7 +358,7 @@ public class QuestSpellShop {
|
||||
}
|
||||
|
||||
//If this card has an exception to the card limit, e.g.: Relentless Rats, get the quest preference
|
||||
if (DeckFormat.getLimitExceptions().contains(card.getName())) {
|
||||
if (DeckFormat.canHaveAnyNumberOf(card)) {
|
||||
numToKeep = FModel.getQuestPreferences().getPrefInt(QPref.PLAYSET_ANY_NUMBER_SIZE);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user