diff --git a/forge-core/src/main/java/forge/card/CardEdition.java b/forge-core/src/main/java/forge/card/CardEdition.java index c69b165d995..bc3d1854a28 100644 --- a/forge-core/src/main/java/forge/card/CardEdition.java +++ b/forge-core/src/main/java/forge/card/CardEdition.java @@ -124,6 +124,7 @@ public final class CardEdition implements Comparable { // immutable private boolean smallSetOverride = false; private String boosterMustContain = ""; private String boosterReplaceSlotFromPrintSheet = ""; + private String[] chaosDraftThemes = new String[0]; private boolean doublePickToStartRound = false; private final CardInSet[] cards; private final Map tokenNormalized; @@ -195,6 +196,7 @@ public final class CardEdition implements Comparable { // immutable public boolean getDoublePickToStartRound() { return doublePickToStartRound; } public String getBoosterMustContain() { return boosterMustContain; } public String getBoosterReplaceSlotFromPrintSheet() { return boosterReplaceSlotFromPrintSheet; } + public String[] getChaosDraftThemes() { return chaosDraftThemes; } public CardInSet[] getCards() { return cards; } public boolean isModern() { return getDate().after(parseDate("2003-07-27")); } //8ED and above are modern except some promo cards and others @@ -385,6 +387,9 @@ public final class CardEdition implements Comparable { // immutable res.boosterMustContain = section.get("BoosterMustContain", ""); // e.g. Dominaria guaranteed legendary creature res.boosterReplaceSlotFromPrintSheet = section.get("BoosterReplaceSlotFromPrintSheet", ""); // e.g. Zendikar Rising guaranteed double-faced card + + res.chaosDraftThemes = section.get("ChaosDraftThemes", "").split(";"); // semicolon separated list of theme names + return res; } diff --git a/forge-core/src/main/java/forge/item/generation/ChaosBoosterSupplier.java b/forge-core/src/main/java/forge/item/generation/ChaosBoosterSupplier.java index a6dc60d6d83..c4a38769dc1 100644 --- a/forge-core/src/main/java/forge/item/generation/ChaosBoosterSupplier.java +++ b/forge-core/src/main/java/forge/item/generation/ChaosBoosterSupplier.java @@ -3,23 +3,20 @@ package forge.item.generation; import forge.card.CardEdition; import forge.item.BoosterPack; import forge.item.PaperCard; +import forge.util.BagRandomizer; import java.util.List; public class ChaosBoosterSupplier implements IUnOpenedProduct { - private List sets; + private BagRandomizer randomizer; - public ChaosBoosterSupplier(List sets) { - this.sets = sets; + public ChaosBoosterSupplier(Iterable sets) throws IllegalArgumentException { + randomizer = new BagRandomizer<>(sets); } @Override public List get() { - if (sets.size() == 0) { - System.out.println("No chaos boosters left to supply."); - return null; - } - final CardEdition set = sets.remove(0); + final CardEdition set = randomizer.getNextItem(); final BoosterPack pack = new BoosterPack(set.getCode(), set.getBoosterTemplate()); return pack.getCards(); } diff --git a/forge-core/src/main/java/forge/util/BagRandomizer.java b/forge-core/src/main/java/forge/util/BagRandomizer.java new file mode 100644 index 00000000000..80bef2ac791 --- /dev/null +++ b/forge-core/src/main/java/forge/util/BagRandomizer.java @@ -0,0 +1,76 @@ +package forge.util; + +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Random; + +/** + * Data structure that allows random draws from a set number of items, + * where all items are returned once before the first will be retrieved. + * The bag will be shuffled after each time all items have been returned. + * @param an object + */ +public class BagRandomizer implements Iterable{ + private static Random random = new SecureRandom(); + + private T[] bag; + private int currentPosition = 0; + + public BagRandomizer(T[] items) throws IllegalArgumentException { + if (items.length == 0) { + throw new IllegalArgumentException("Must include at least one item!"); + } + bag = items; + shuffleBag(); + } + + public BagRandomizer(Iterable items) throws IllegalArgumentException { + ArrayList list = new ArrayList<>(); + for (T item : items) { + list.add(item); + } + if (list.size() == 0) { + throw new IllegalArgumentException("Must include at least one item!"); + } + bag = (T[]) list.toArray(); + shuffleBag(); + } + + public T getNextItem() { + // reset bag if last position is reached + if (currentPosition >= bag.length) { + shuffleBag(); + currentPosition = 0; + } + return bag[currentPosition++]; + } + + private void shuffleBag() { + int n = bag.length; + for (int i = 0; i < n; i++) { + int r = (int) (random.nextDouble() * (i + 1)); + T swap = bag[r]; + bag[r] = bag[i]; + bag[i] = swap; + } + } + + @Override + public Iterator iterator() { + return new BagRandomizerIterator(); + } + + private class BagRandomizerIterator implements Iterator { + + @Override + public boolean hasNext() { + return bag.length > 0; + } + + @Override + public T next() { + return (T) BagRandomizer.this.getNextItem(); + } + } +} diff --git a/forge-gui/res/blockdata/chaosdraftthemes.txt b/forge-gui/res/blockdata/chaosdraftthemes.txt new file mode 100644 index 00000000000..dd2e57914a8 --- /dev/null +++ b/forge-gui/res/blockdata/chaosdraftthemes.txt @@ -0,0 +1,10 @@ +# Order, Tag, Label +1, DEFAULT, All sets (default) +11, MODERN, Modern legal expansions +12, PIONEER, Pioneer legal expansions +13, STANDARD, Standard legal expansions +21, CORE_SET, Core Sets +22, MASTERS_SET, Masters Sets (paper only) +30, MIRRODIN, Mirrodin (Plane) +30, RAVNICA, Ravnica (Plane) +40, GRAVEYARD_MATTERS, Graveyard matters diff --git a/forge-gui/res/editions/Amonkhet.txt b/forge-gui/res/editions/Amonkhet.txt index 96365a69612..2e7e9a002ab 100644 --- a/forge-gui/res/editions/Amonkhet.txt +++ b/forge-gui/res/editions/Amonkhet.txt @@ -9,6 +9,7 @@ BoosterCovers=5 Booster=10 Common:!fromSheet("AKH Planeswalker Decks and Toolkit"), 3 Uncommon:!fromSheet("AKH Planeswalker Decks and Toolkit"), 1 RareMythic:!fromSheet("AKH Planeswalker Decks and Toolkit"), 1 BasicLand AKH AdditionalSheetForFoils=fromSheet("MPS Amonkhet Invocations") AdditionalSetUnlockedInQuest=MPS_AKH +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] 1 M Angel of Sanctions diff --git a/forge-gui/res/editions/Avacyn Restored.txt b/forge-gui/res/editions/Avacyn Restored.txt index 3d3de349056..22d9dc9e78e 100644 --- a/forge-gui/res/editions/Avacyn Restored.txt +++ b/forge-gui/res/editions/Avacyn Restored.txt @@ -7,6 +7,7 @@ MciCode=avr Type=Expansion BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] 167 C Abundant Growth diff --git a/forge-gui/res/editions/Classic Sixth Edition.txt b/forge-gui/res/editions/Classic Sixth Edition.txt index 56499cc924a..1993eade79c 100644 --- a/forge-gui/res/editions/Classic Sixth Edition.txt +++ b/forge-gui/res/editions/Classic Sixth Edition.txt @@ -9,6 +9,7 @@ Border=White BoosterCovers=1 Booster=11 Common, 3 Uncommon, 1 Rare Foil=NotSupported +ChaosDraftThemes=CORE_SET [cards] 163 U AEther Flash diff --git a/forge-gui/res/editions/Dark Ascension.txt b/forge-gui/res/editions/Dark Ascension.txt index c39a28fd4a9..4b4044e6ca2 100644 --- a/forge-gui/res/editions/Dark Ascension.txt +++ b/forge-gui/res/editions/Dark Ascension.txt @@ -7,6 +7,7 @@ MciCode=dka Type=Expansion BoosterCovers=3 Booster=9 Common:!dfc, 3 Uncommon:!dfc, 1 RareMythic:!dfc, 1 dfc, 1 BasicLand ISD +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] 81 U Afflicted Deserter diff --git a/forge-gui/res/editions/Darksteel.txt b/forge-gui/res/editions/Darksteel.txt index fc5084bec80..414babc1ea8 100644 --- a/forge-gui/res/editions/Darksteel.txt +++ b/forge-gui/res/editions/Darksteel.txt @@ -8,6 +8,7 @@ Type=Expansion BoosterCovers=3 Booster=11 Common, 3 Uncommon, 1 Rare FoilAlwaysInCommonSlot=False +ChaosDraftThemes=MIRRODIN [cards] 37 R AEther Snap diff --git a/forge-gui/res/editions/Dissension.txt b/forge-gui/res/editions/Dissension.txt index 34179da950d..503c21d5cb3 100644 --- a/forge-gui/res/editions/Dissension.txt +++ b/forge-gui/res/editions/Dissension.txt @@ -8,6 +8,7 @@ Type=Expansion BoosterCovers=3 Booster=11 Common, 3 Uncommon, 1 Rare FoilAlwaysInCommonSlot=False +ChaosDraftThemes=RAVNICA [cards] 1 C Aurora Eidolon diff --git a/forge-gui/res/editions/Double Masters.txt b/forge-gui/res/editions/Double Masters.txt index 5dec0146172..91197ed1e46 100644 --- a/forge-gui/res/editions/Double Masters.txt +++ b/forge-gui/res/editions/Double Masters.txt @@ -7,6 +7,7 @@ BoosterCovers=3 Booster=8 Common, 3 Uncommon, 2 RareMythic, 2 fromSheet("2XM Foils") Foil=NotSupported DoublePick=true +ChaosDraftThemes=MASTERS_SET [cards] 1 M Karn Liberated diff --git a/forge-gui/res/editions/Dragon's Maze.txt b/forge-gui/res/editions/Dragon's Maze.txt index e6b83cee621..ba9091da0ff 100644 --- a/forge-gui/res/editions/Dragon's Maze.txt +++ b/forge-gui/res/editions/Dragon's Maze.txt @@ -7,6 +7,7 @@ MciCode=dgm Type=Expansion BoosterCovers=3 Booster=10 Common:!land, 3 Uncommon, 1 RareMythic:!land, 1 fromSheet("DGM Lands") +ChaosDraftThemes=RAVNICA [cards] 1 C Boros Mastiff diff --git a/forge-gui/res/editions/Eighth Edition.txt b/forge-gui/res/editions/Eighth Edition.txt index 19ca2c2083e..74e85840549 100644 --- a/forge-gui/res/editions/Eighth Edition.txt +++ b/forge-gui/res/editions/Eighth Edition.txt @@ -9,6 +9,7 @@ Border=White BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 Rare, 1 BasicLand FoilAlwaysInCommonSlot=False +ChaosDraftThemes=CORE_SET [cards] 117 U Abyssal Specter diff --git a/forge-gui/res/editions/Eldritch Moon.txt b/forge-gui/res/editions/Eldritch Moon.txt index e3b743bd969..865db975d3e 100644 --- a/forge-gui/res/editions/Eldritch Moon.txt +++ b/forge-gui/res/editions/Eldritch Moon.txt @@ -9,6 +9,7 @@ BoosterCovers=3 Booster=9 Common:!dfc, 3 Uncommon:!dfc, 1 RareMythic:!dfc, 1 dfc:!Rare:!Mythic, 1 BasicLand SOI ChanceReplaceCommonWith=.125F dfc:RareMythic TreatAsSmallSet=true +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] 1 U Abundant Maw diff --git a/forge-gui/res/editions/Eternal Masters.txt b/forge-gui/res/editions/Eternal Masters.txt index 29d5548c6b0..0a389e78f9a 100644 --- a/forge-gui/res/editions/Eternal Masters.txt +++ b/forge-gui/res/editions/Eternal Masters.txt @@ -7,6 +7,7 @@ Type=Reprint BoosterCovers=3 Booster=11 Common, 3 Uncommon, 1 RareMythic FoilChanceInBooster=100 +ChaosDraftThemes=MASTERS_SET [cards] 1 C Aven Riftwatcher diff --git a/forge-gui/res/editions/Fate Reforged.txt b/forge-gui/res/editions/Fate Reforged.txt index e3810f09b24..04e5ca0f0a2 100644 --- a/forge-gui/res/editions/Fate Reforged.txt +++ b/forge-gui/res/editions/Fate Reforged.txt @@ -6,6 +6,7 @@ MciCode=frf Type=Expansion BoosterCovers=3 Booster=10 Common:!land, 3 Uncommon, 1 RareMythic, 1 fromSheet("FRF Lands"), 0 fromSheet("FRF Basic Lands") +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] 1 M Ugin, the Spirit Dragon diff --git a/forge-gui/res/editions/Fifth Dawn.txt b/forge-gui/res/editions/Fifth Dawn.txt index 48d6c8868cf..c973dbb7db3 100644 --- a/forge-gui/res/editions/Fifth Dawn.txt +++ b/forge-gui/res/editions/Fifth Dawn.txt @@ -8,6 +8,7 @@ Type=Expansion BoosterCovers=3 Booster=11 Common, 3 Uncommon, 1 Rare FoilAlwaysInCommonSlot=False +ChaosDraftThemes=MIRRODIN [cards] 1 C Abuna's Chant diff --git a/forge-gui/res/editions/Fifth Edition.txt b/forge-gui/res/editions/Fifth Edition.txt index 3b8505bbb2e..e64a00f7bc9 100644 --- a/forge-gui/res/editions/Fifth Edition.txt +++ b/forge-gui/res/editions/Fifth Edition.txt @@ -9,6 +9,7 @@ Border=White BoosterCovers=5 Booster=11 Common, 3 Uncommon, 1 Rare Foil=NotSupported +ChaosDraftThemes=CORE_SET [cards] U AEther Storm diff --git a/forge-gui/res/editions/Fourth Edition.txt b/forge-gui/res/editions/Fourth Edition.txt index e8f7bbffc9f..6f17253c343 100644 --- a/forge-gui/res/editions/Fourth Edition.txt +++ b/forge-gui/res/editions/Fourth Edition.txt @@ -9,6 +9,7 @@ Border=White BoosterCovers=5 Booster=11 Common, 3 Uncommon, 1 Rare Foil=NotSupported +ChaosDraftThemes=CORE_SET [cards] U Abomination diff --git a/forge-gui/res/editions/Gatecrash.txt b/forge-gui/res/editions/Gatecrash.txt index 4aa1ef9bf83..f11064b7914 100644 --- a/forge-gui/res/editions/Gatecrash.txt +++ b/forge-gui/res/editions/Gatecrash.txt @@ -7,6 +7,7 @@ MciCode=gtc Type=Expansion BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand RTR +ChaosDraftThemes=RAVNICA [cards] 29 U AEtherize diff --git a/forge-gui/res/editions/Guildpact.txt b/forge-gui/res/editions/Guildpact.txt index b13ecda5861..d6226592ab9 100644 --- a/forge-gui/res/editions/Guildpact.txt +++ b/forge-gui/res/editions/Guildpact.txt @@ -8,6 +8,7 @@ Type=Expansion BoosterCovers=3 Booster=11 Common, 3 Uncommon, 1 Rare FoilAlwaysInCommonSlot=False +ChaosDraftThemes=RAVNICA [cards] 22 U AEtherplasm diff --git a/forge-gui/res/editions/Guilds of Ravnica.txt b/forge-gui/res/editions/Guilds of Ravnica.txt index 606558dcf9d..63a2f016a6e 100644 --- a/forge-gui/res/editions/Guilds of Ravnica.txt +++ b/forge-gui/res/editions/Guilds of Ravnica.txt @@ -8,6 +8,7 @@ Type=Expansion BoosterCovers=5 Booster=10 Common:!fromSheet("GRN Secret Cards"), 3 Uncommon:!fromSheet("GRN Secret Cards"), 1 RareMythic:!fromSheet("GRN Secret Cards"), 1 fromSheet("GRN Lands") AdditionalSetUnlockedInQuest=GK1 +ChaosDraftThemes=RAVNICA;GRAVEYARD_MATTERS [cards] 1 C Blade Instructor diff --git a/forge-gui/res/editions/Hour of Devastation.txt b/forge-gui/res/editions/Hour of Devastation.txt index 71192b7c2b8..9c3c2483381 100644 --- a/forge-gui/res/editions/Hour of Devastation.txt +++ b/forge-gui/res/editions/Hour of Devastation.txt @@ -10,6 +10,7 @@ Booster=10 Common:!fromSheet("HOU Planeswalker Decks and Toolkit"), 3 Uncommon:! AdditionalSheetForFoils=fromSheet("MPS Hour of Devastation Invocations") AdditionalSetUnlockedInQuest=MPS_AKH TreatAsSmallSet=true +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] 1 C Act of Heroism diff --git a/forge-gui/res/editions/Iconic Masters.txt b/forge-gui/res/editions/Iconic Masters.txt index 902079fd311..16b2327147b 100644 --- a/forge-gui/res/editions/Iconic Masters.txt +++ b/forge-gui/res/editions/Iconic Masters.txt @@ -7,6 +7,7 @@ Type=Reprint BoosterCovers=3 Booster=11 Common, 3 Uncommon, 1 RareMythic FoilChanceInBooster=100 +ChaosDraftThemes=MASTERS_SET [cards] 1 C Scion of Ugin diff --git a/forge-gui/res/editions/Innistrad.txt b/forge-gui/res/editions/Innistrad.txt index 7655c58e08f..161fd42ffda 100644 --- a/forge-gui/res/editions/Innistrad.txt +++ b/forge-gui/res/editions/Innistrad.txt @@ -7,6 +7,7 @@ MciCode=isd Type=Expansion BoosterCovers=5 Booster=9 Common:!dfc, 3 Uncommon:!dfc, 1 RareMythic:!dfc, 1 dfc, 1 BasicLand +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] 85 U Abattoir Ghoul diff --git a/forge-gui/res/editions/Judgment.txt b/forge-gui/res/editions/Judgment.txt index 26e92e549eb..ce71ba23ef2 100644 --- a/forge-gui/res/editions/Judgment.txt +++ b/forge-gui/res/editions/Judgment.txt @@ -9,6 +9,7 @@ BoosterCovers=1 Booster=11 Common, 3 Uncommon, 1 Rare Foil=OldStyle FoilAlwaysInCommonSlot=False +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] 1 U Ancestor's Chosen diff --git a/forge-gui/res/editions/Khans of Tarkir.txt b/forge-gui/res/editions/Khans of Tarkir.txt index b1b96ce023e..b8fde746cc6 100644 --- a/forge-gui/res/editions/Khans of Tarkir.txt +++ b/forge-gui/res/editions/Khans of Tarkir.txt @@ -7,6 +7,7 @@ MciCode=ktk Type=Expansion BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand KTK +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] 1 U Abzan Battle Priest diff --git a/forge-gui/res/editions/Limited Edition Beta.txt b/forge-gui/res/editions/Limited Edition Beta.txt index f312ed2a90a..c428fa67b8f 100644 --- a/forge-gui/res/editions/Limited Edition Beta.txt +++ b/forge-gui/res/editions/Limited Edition Beta.txt @@ -8,6 +8,7 @@ Type=Core BoosterCovers=1 Booster=11 Common, 3 Uncommon, 1 Rare Foil=NotSupported +ChaosDraftThemes=CORE_SET [cards] U Air Elemental diff --git a/forge-gui/res/editions/Magic 2010.txt b/forge-gui/res/editions/Magic 2010.txt index 39141f5576a..6b4ddf84592 100644 --- a/forge-gui/res/editions/Magic 2010.txt +++ b/forge-gui/res/editions/Magic 2010.txt @@ -7,6 +7,7 @@ MciCode=m10 Type=Core BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand +ChaosDraftThemes=CORE_SET [cards] 165 U Acidic Slime diff --git a/forge-gui/res/editions/Magic 2011.txt b/forge-gui/res/editions/Magic 2011.txt index 945a4d29d2a..790b7760fd1 100644 --- a/forge-gui/res/editions/Magic 2011.txt +++ b/forge-gui/res/editions/Magic 2011.txt @@ -7,6 +7,7 @@ MciCode=m11 Type=Core BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand +ChaosDraftThemes=CORE_SET [cards] 41 C AEther Adept diff --git a/forge-gui/res/editions/Magic 2012.txt b/forge-gui/res/editions/Magic 2012.txt index 86bb22faed6..0d71d2afad6 100644 --- a/forge-gui/res/editions/Magic 2012.txt +++ b/forge-gui/res/editions/Magic 2012.txt @@ -7,6 +7,7 @@ MciCode=m12 Type=Core BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand +ChaosDraftThemes=CORE_SET [cards] 41 C AEther Adept diff --git a/forge-gui/res/editions/Magic 2013.txt b/forge-gui/res/editions/Magic 2013.txt index 2dab22e50c0..21e5555ae31 100644 --- a/forge-gui/res/editions/Magic 2013.txt +++ b/forge-gui/res/editions/Magic 2013.txt @@ -7,6 +7,7 @@ MciCode=m13 Type=Core BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand +ChaosDraftThemes=CORE_SET [cards] 159 U Acidic Slime diff --git a/forge-gui/res/editions/Magic 2014.txt b/forge-gui/res/editions/Magic 2014.txt index 0934c02e1ef..005c769c514 100644 --- a/forge-gui/res/editions/Magic 2014.txt +++ b/forge-gui/res/editions/Magic 2014.txt @@ -7,6 +7,7 @@ MciCode=m14 Type=Core BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand +ChaosDraftThemes=CORE_SET [cards] 1 M Ajani, Caller of the Pride diff --git a/forge-gui/res/editions/Magic 2015.txt b/forge-gui/res/editions/Magic 2015.txt index 8d560ecd154..597577e6985 100644 --- a/forge-gui/res/editions/Magic 2015.txt +++ b/forge-gui/res/editions/Magic 2015.txt @@ -7,6 +7,7 @@ MciCode=m15 Type=Core BoosterCovers=5 Booster=10 Common:!fromSheet("M15 Sample Cards"), 3 Uncommon:!fromSheet("M15 Sample Cards"), 1 RareMythic:!fromSheet("M15 Sample Cards"), 1 BasicLand +ChaosDraftThemes=CORE_SET [cards] 1 M Ajani Steadfast diff --git a/forge-gui/res/editions/Magic 2019.txt b/forge-gui/res/editions/Magic 2019.txt index 157a0a2cf18..f7cc4829eb1 100644 --- a/forge-gui/res/editions/Magic 2019.txt +++ b/forge-gui/res/editions/Magic 2019.txt @@ -7,6 +7,7 @@ MciCode=m19 Type=Core BoosterCovers=5 Booster=10 Common:!fromSheet("M19 Secret Cards"), 3 Uncommon:!fromSheet("M19 Secret Cards"), 1 RareMythic:!fromSheet("M19 Secret Cards"), 1 fromSheet("M19 Lands") +ChaosDraftThemes=CORE_SET [cards] 1 U Aegis of the Heavens diff --git a/forge-gui/res/editions/Magic 2020.txt b/forge-gui/res/editions/Magic 2020.txt index 89184a08add..2a099ef55ba 100644 --- a/forge-gui/res/editions/Magic 2020.txt +++ b/forge-gui/res/editions/Magic 2020.txt @@ -6,6 +6,7 @@ MciCode=m20 Type=Core BoosterCovers=3 Booster=10 Common:!fromSheet("M20 Secret Cards"), 3 Uncommon:!fromSheet("M20 Secret Cards"), 1 RareMythic:!fromSheet("M20 Secret Cards"), 1 fromSheet("M20 Lands") +ChaosDraftThemes=CORE_SET [cards] 1 C Aerial Assault diff --git a/forge-gui/res/editions/Magic 2021.txt b/forge-gui/res/editions/Magic 2021.txt index ed49e37ba09..125329342ae 100644 --- a/forge-gui/res/editions/Magic 2021.txt +++ b/forge-gui/res/editions/Magic 2021.txt @@ -6,6 +6,7 @@ Type=Core BoosterCovers=3 Booster=10 Common:!fromSheet("M21 Secret Cards"), 3 Uncommon:!fromSheet("M21 Secret Cards"), 1 RareMythic:!fromSheet("M21 Secret Cards"), 1 fromSheet("M21 Lands") Prerelease=6 Boosters, 1 RareMythic+ +ChaosDraftThemes=CORE_SET [cards] 1 M Ugin, the Spirit Dragon diff --git a/forge-gui/res/editions/Magic Origins.txt b/forge-gui/res/editions/Magic Origins.txt index 2204e442dd9..aa0093974de 100644 --- a/forge-gui/res/editions/Magic Origins.txt +++ b/forge-gui/res/editions/Magic Origins.txt @@ -7,6 +7,7 @@ MciCode=ori Type=Core BoosterCovers=5 Booster=10 Common:!fromSheet("ORI Sample Cards"), 3 Uncommon:!fromSheet("ORI Sample Cards"), 1 RareMythic:!fromSheet("ORI Sample Cards"), 1 BasicLand +ChaosDraftThemes=CORE_SET [cards] 1 C Akroan Jailer diff --git a/forge-gui/res/editions/Masters 25.txt b/forge-gui/res/editions/Masters 25.txt index 041803b48aa..9bfe3430f3d 100644 --- a/forge-gui/res/editions/Masters 25.txt +++ b/forge-gui/res/editions/Masters 25.txt @@ -7,6 +7,7 @@ Type=Reprint BoosterCovers=3 Booster=11 Common, 3 Uncommon, 1 RareMythic FoilChanceInBooster=100 +ChaosDraftThemes=MASTERS_SET [cards] 1 C Act of Heroism diff --git a/forge-gui/res/editions/Mirrodin Besieged.txt b/forge-gui/res/editions/Mirrodin Besieged.txt index d91196d2e92..069270b54e3 100644 --- a/forge-gui/res/editions/Mirrodin Besieged.txt +++ b/forge-gui/res/editions/Mirrodin Besieged.txt @@ -7,6 +7,7 @@ MciCode=mbs Type=Expansion BoosterCovers=3 Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand +ChaosDraftThemes=MIRRODIN [cards] 1 U Accorder Paladin diff --git a/forge-gui/res/editions/Mirrodin.txt b/forge-gui/res/editions/Mirrodin.txt index 4185ca1b114..17ee49445d9 100644 --- a/forge-gui/res/editions/Mirrodin.txt +++ b/forge-gui/res/editions/Mirrodin.txt @@ -8,6 +8,7 @@ Type=Expansion BoosterCovers=5 Booster=11 Common, 3 Uncommon, 1 Rare FoilAlwaysInCommonSlot=False +ChaosDraftThemes=MIRRODIN [cards] 141 C AEther Spellbomb diff --git a/forge-gui/res/editions/Modern Horizons.txt b/forge-gui/res/editions/Modern Horizons.txt index bed63eab73c..ae1ce47d837 100644 --- a/forge-gui/res/editions/Modern Horizons.txt +++ b/forge-gui/res/editions/Modern Horizons.txt @@ -7,6 +7,7 @@ MciCode=mh1 Type=Other BoosterCovers=5 Booster=10 Common:!fromSheet("MH1 Secret Cards"), 3 Uncommon:!fromSheet("MH1 Secret Cards"), 1 RareMythic:!fromSheet("MH1 Secret Cards"), 1 fromSheet("MH1 Lands") +ChaosDraftThemes=MASTERS_SET;GRAVEYARD_MATTERS [cards] diff --git a/forge-gui/res/editions/Modern Masters 2015.txt b/forge-gui/res/editions/Modern Masters 2015.txt index 1548ad57511..ceb09d77f71 100644 --- a/forge-gui/res/editions/Modern Masters 2015.txt +++ b/forge-gui/res/editions/Modern Masters 2015.txt @@ -7,6 +7,7 @@ Type=Reprint BoosterCovers=3 Booster=11 Common, 3 Uncommon, 1 RareMythic FoilChanceInBooster=100 +ChaosDraftThemes=MASTERS_SET [cards] 1 R All Is Dust diff --git a/forge-gui/res/editions/Modern Masters 2017.txt b/forge-gui/res/editions/Modern Masters 2017.txt index 4cd03184bb7..257b2a84d85 100644 --- a/forge-gui/res/editions/Modern Masters 2017.txt +++ b/forge-gui/res/editions/Modern Masters 2017.txt @@ -7,6 +7,7 @@ Type=Reprint BoosterCovers=3 Booster=11 Common, 3 Uncommon, 1 RareMythic FoilChanceInBooster=100 +ChaosDraftThemes=MASTERS_SET;GRAVEYARD_MATTERS [cards] 1 C Attended Knight diff --git a/forge-gui/res/editions/Modern Masters.txt b/forge-gui/res/editions/Modern Masters.txt index ddc3e94db80..a1bf70b93eb 100644 --- a/forge-gui/res/editions/Modern Masters.txt +++ b/forge-gui/res/editions/Modern Masters.txt @@ -7,6 +7,7 @@ Type=Reprint BoosterCovers=3 Booster=11 Common, 3 Uncommon, 1 RareMythic FoilChanceInBooster=100 +ChaosDraftThemes=MASTERS_SET [cards] 1 R Adarkar Valkyrie diff --git a/forge-gui/res/editions/New Phyrexia.txt b/forge-gui/res/editions/New Phyrexia.txt index e3001c0aa00..34ef161abb8 100644 --- a/forge-gui/res/editions/New Phyrexia.txt +++ b/forge-gui/res/editions/New Phyrexia.txt @@ -7,6 +7,7 @@ MciCode=nph Type=Expansion BoosterCovers=3 Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand +ChaosDraftThemes=MIRRODIN [cards] 78 U Act of Aggression diff --git a/forge-gui/res/editions/Ninth Edition.txt b/forge-gui/res/editions/Ninth Edition.txt index 6f9dbcc9584..dce5aa6170c 100644 --- a/forge-gui/res/editions/Ninth Edition.txt +++ b/forge-gui/res/editions/Ninth Edition.txt @@ -9,6 +9,7 @@ Border=White BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 Rare, 1 BasicLand FoilAlwaysInCommonSlot=False +ChaosDraftThemes=CORE_SET [cards] 317 R Adarkar Wastes diff --git a/forge-gui/res/editions/Odyssey.txt b/forge-gui/res/editions/Odyssey.txt index 60b1164d686..7e1e0f47eeb 100644 --- a/forge-gui/res/editions/Odyssey.txt +++ b/forge-gui/res/editions/Odyssey.txt @@ -9,6 +9,7 @@ BoosterCovers=3 Booster=11 Common, 3 Uncommon, 1 Rare Foil=OldStyle FoilAlwaysInCommonSlot=False +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] 60 C AEther Burst diff --git a/forge-gui/res/editions/Ravnica Allegiance.txt b/forge-gui/res/editions/Ravnica Allegiance.txt index c614de27d60..889ac8f637c 100644 --- a/forge-gui/res/editions/Ravnica Allegiance.txt +++ b/forge-gui/res/editions/Ravnica Allegiance.txt @@ -7,6 +7,7 @@ MciCode=rna Type=Expansion BoosterCovers=5 Booster=10 Common:!fromSheet("RNA Secret Cards"), 3 Uncommon:!fromSheet("RNA Secret Cards"), 1 RareMythic:!fromSheet("RNA Secret Cards"), 1 fromSheet("RNA Lands") +ChaosDraftThemes=RAVNICA [cards] 1 M Angel of Grace diff --git a/forge-gui/res/editions/Ravnica City of Guilds.txt b/forge-gui/res/editions/Ravnica City of Guilds.txt index fdb72964748..bc98825cf3f 100644 --- a/forge-gui/res/editions/Ravnica City of Guilds.txt +++ b/forge-gui/res/editions/Ravnica City of Guilds.txt @@ -8,6 +8,7 @@ Type=Expansion BoosterCovers=5 Booster=11 Common, 3 Uncommon, 1 Rare FoilAlwaysInCommonSlot=False +ChaosDraftThemes=RAVNICA [cards] 190 R Agrus Kos, Wojek Veteran diff --git a/forge-gui/res/editions/Return to Ravnica.txt b/forge-gui/res/editions/Return to Ravnica.txt index 0d0ad645ebb..2d4aada621d 100644 --- a/forge-gui/res/editions/Return to Ravnica.txt +++ b/forge-gui/res/editions/Return to Ravnica.txt @@ -7,6 +7,7 @@ MciCode=rtr Type=Expansion BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand +ChaosDraftThemes=RAVNICA;GRAVEYARD_MATTERS [cards] 141 R Abrupt Decay diff --git a/forge-gui/res/editions/Revised Edition.txt b/forge-gui/res/editions/Revised Edition.txt index 101947233c7..ccc051bebe1 100644 --- a/forge-gui/res/editions/Revised Edition.txt +++ b/forge-gui/res/editions/Revised Edition.txt @@ -9,6 +9,7 @@ Border=White BoosterCovers=1 Booster=11 Common, 3 Uncommon, 1 Rare Foil=NotSupported +ChaosDraftThemes=CORE_SET [cards] U Air Elemental diff --git a/forge-gui/res/editions/Scars of Mirrodin.txt b/forge-gui/res/editions/Scars of Mirrodin.txt index 481198839fe..606ecf4d937 100644 --- a/forge-gui/res/editions/Scars of Mirrodin.txt +++ b/forge-gui/res/editions/Scars of Mirrodin.txt @@ -7,6 +7,7 @@ MciCode=som Type=Expansion BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand +ChaosDraftThemes=MIRRODIN [cards] 1 U Abuna Acolyte diff --git a/forge-gui/res/editions/Scourge.txt b/forge-gui/res/editions/Scourge.txt index eb932a6c227..9a7a5354a2a 100644 --- a/forge-gui/res/editions/Scourge.txt +++ b/forge-gui/res/editions/Scourge.txt @@ -9,6 +9,7 @@ BoosterCovers=3 Booster=11 Common, 3 Uncommon, 1 Rare Foil=OldStyle FoilAlwaysInCommonSlot=False +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] 109 C Accelerated Mutation diff --git a/forge-gui/res/editions/Seventh Edition.txt b/forge-gui/res/editions/Seventh Edition.txt index 8da1f7d6838..3feaac56c79 100644 --- a/forge-gui/res/editions/Seventh Edition.txt +++ b/forge-gui/res/editions/Seventh Edition.txt @@ -10,6 +10,7 @@ BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 Rare, 1 BasicLand Foil=OldStyle FoilAlwaysInCommonSlot=False +ChaosDraftThemes=CORE_SET [cards] 172 U AEther Flash diff --git a/forge-gui/res/editions/Shadows over Innistrad.txt b/forge-gui/res/editions/Shadows over Innistrad.txt index 224c0915cfe..7cd7a64fbda 100644 --- a/forge-gui/res/editions/Shadows over Innistrad.txt +++ b/forge-gui/res/editions/Shadows over Innistrad.txt @@ -8,6 +8,7 @@ MciCode=soi BoosterCovers=5 Booster=9 Common:!dfc, 3 Uncommon:!dfc, 1 RareMythic:!dfc, 1 dfc:!Rare:!Mythic, 1 BasicLand ChanceReplaceCommonWith=.125F dfc:RareMythic +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] diff --git a/forge-gui/res/editions/Tenth Edition.txt b/forge-gui/res/editions/Tenth Edition.txt index 7ed4e1896c5..69f99486b31 100644 --- a/forge-gui/res/editions/Tenth Edition.txt +++ b/forge-gui/res/editions/Tenth Edition.txt @@ -7,6 +7,7 @@ MciCode=10e Type=Core BoosterCovers=5 Booster=10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +ChaosDraftThemes=CORE_SET [cards] 249 R Abundance diff --git a/forge-gui/res/editions/Theros Beyond Death.txt b/forge-gui/res/editions/Theros Beyond Death.txt index 7d38b479b01..12b9eb14c51 100644 --- a/forge-gui/res/editions/Theros Beyond Death.txt +++ b/forge-gui/res/editions/Theros Beyond Death.txt @@ -7,6 +7,7 @@ Type=Expansion BoosterCovers=3 Booster=10 Common:!fromSheet("THB Secret Cards"), 3 Uncommon:!fromSheet("THB Secret Cards"), 1 RareMythic:!fromSheet("THB Secret Cards"), 1 BasicLand Prerelease=6 Boosters, 1 RareMythic+ +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] 1 U Alseid of Life's Bounty diff --git a/forge-gui/res/editions/Torment.txt b/forge-gui/res/editions/Torment.txt index 5bf2e07e83e..033ea556ec8 100644 --- a/forge-gui/res/editions/Torment.txt +++ b/forge-gui/res/editions/Torment.txt @@ -9,6 +9,7 @@ BoosterCovers=1 Booster=11 Common, 3 Uncommon, 1 Rare Foil=OldStyle FoilAlwaysInCommonSlot=False +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] 90 C Accelerate diff --git a/forge-gui/res/editions/Ultimate Masters.txt b/forge-gui/res/editions/Ultimate Masters.txt index 0c799d1cb69..de468aa72da 100644 --- a/forge-gui/res/editions/Ultimate Masters.txt +++ b/forge-gui/res/editions/Ultimate Masters.txt @@ -8,6 +8,7 @@ Type=Reprint BoosterCovers=3 Booster=11 Common, 3 Uncommon, 1 RareMythic FoilChanceInBooster=100 +ChaosDraftThemes=MASTERS_SET;GRAVEYARD_MATTERS [cards] 1 R All Is Dust diff --git a/forge-gui/res/editions/Unlimited Edition.txt b/forge-gui/res/editions/Unlimited Edition.txt index ead1be21f6e..54e891f24bf 100644 --- a/forge-gui/res/editions/Unlimited Edition.txt +++ b/forge-gui/res/editions/Unlimited Edition.txt @@ -9,6 +9,7 @@ Border=White BoosterCovers=1 Booster=11 Common, 3 Uncommon, 1 Rare Foil=NotSupported +ChaosDraftThemes=CORE_SET [cards] U Air Elemental diff --git a/forge-gui/res/editions/War of the Spark.txt b/forge-gui/res/editions/War of the Spark.txt index 01c65804bf3..9ab696b37a5 100644 --- a/forge-gui/res/editions/War of the Spark.txt +++ b/forge-gui/res/editions/War of the Spark.txt @@ -8,6 +8,7 @@ Type=Expansion BoosterCovers=3 Booster=10 Common:!fromSheet("WAR Secret Cards"), 3 Uncommon:!fromSheet("WAR Secret Cards"), 1 RareMythic:!fromSheet("WAR Secret Cards"), 1 BasicLand BoosterMustContain=Planeswalker +ChaosDraftThemes=RAVNICA [cards] 1 R Karn, the Great Creator diff --git a/forge-gui/res/editions/Weatherlight.txt b/forge-gui/res/editions/Weatherlight.txt index 1ef49097fbf..c6b40184429 100644 --- a/forge-gui/res/editions/Weatherlight.txt +++ b/forge-gui/res/editions/Weatherlight.txt @@ -8,6 +8,7 @@ Type=Expansion BoosterCovers=1 Booster=11 Common, 3 Uncommon, 1 Rare Foil=NotSupported +ChaosDraftThemes=GRAVEYARD_MATTERS [cards] U AEther Flash diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index a2e1662921d..cee314236db 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -1929,6 +1929,7 @@ lblPlanarDeckZone=Weltendeck lblNoneZone=Keine #BoosterDraft.java lblChooseBlock=Wähle Block +lblChooseChaosTheme=Wähle ein Chaos-Draft-Thema lblBlockNotContainSetCombinations={0} enthält keine Set-Auswahl. lblChooseSetCombination=Treffe Set-Auswahl lblNotFoundCustomDraftFiles=Keine angepaßte Draft-Datei gefunden. diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 5c9b42477b9..f58b045ed8c 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -1929,6 +1929,7 @@ lblPlanarDeckZone=planardeck lblNoneZone=none #BoosterDraft.java lblChooseBlock=Choose Block +lblChooseChaosTheme=Choose Chaos Draft Theme lblBlockNotContainSetCombinations={0} does not contain any set combinations. lblChooseSetCombination=Choose Set Combination lblNotFoundCustomDraftFiles=No custom draft files found. diff --git a/forge-gui/src/main/java/forge/limited/BoosterDraft.java b/forge-gui/src/main/java/forge/limited/BoosterDraft.java index a3ffdf73ebe..78af6def2b4 100644 --- a/forge-gui/src/main/java/forge/limited/BoosterDraft.java +++ b/forge-gui/src/main/java/forge/limited/BoosterDraft.java @@ -20,7 +20,6 @@ package forge.limited; import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; import forge.StaticData; import forge.card.CardEdition; import forge.deck.CardPool; @@ -41,7 +40,6 @@ import forge.util.gui.SGuiChoose; import forge.util.gui.SOptionPane; import forge.util.storage.IStorage; import forge.util.Localizer; -import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.ArrayUtils; import java.io.File; @@ -181,34 +179,40 @@ public class BoosterDraft implements IBoosterDraft { break; case Chaos: + /** + * A chaos draft consists of boosters from many different sets. + * Default settings are boosters from all sets with a booster size of 15 cards. + * Alternatively, the sets can be restricted to a format like Modern or to a theme. + * Examples for themes: sets that take place on a certain plane, core sets, masters sets, + * or sets that share a mechanic. + */ + // Get chaos draft themes + final List themes = new ArrayList<>(); + final IStorage themeStorage = FModel.getThemedChaosDrafts(); + for (final ThemedChaosDraft theme : themeStorage) { + themes.add(theme); + } + Collections.sort(themes); // sort for user interface + // Ask user to select theme + final String dialogQuestion = Localizer.getInstance().getMessage("lblChooseChaosTheme"); + final ThemedChaosDraft theme = SGuiChoose.oneOrNone(dialogQuestion, themes); + if (theme == null) { + return false; // abort if no theme is selected + } + // Filter all sets by theme restrictions + final Predicate themeFilter = theme.getEditionFilter(); final CardEdition.Collection allEditions = StaticData.instance().getEditions(); - final Iterable chaosDraftEditions = Iterables.filter(allEditions.getOrderedEditions(), new Predicate() { - @Override - public boolean apply(final CardEdition cardEdition) { - boolean isExpansion = cardEdition.getType().equals(CardEdition.Type.EXPANSION); - boolean isCoreSet = cardEdition.getType().equals(CardEdition.Type.CORE); - boolean isReprintSet = cardEdition.getType().equals(CardEdition.Type.REPRINT); - if (isExpansion || isCoreSet || isReprintSet) { - // Only allow sets with 15 cards in booster packs - if (cardEdition.hasBoosterTemplate()) { - final List> slots = cardEdition.getBoosterTemplate().getSlots(); - int boosterSize = 0; - for (Pair slot : slots) { - boosterSize += slot.getRight(); - } - return boosterSize == 15; - } - } - return false; - } - }); - - // Randomize order of sets - List shuffled = Lists.newArrayList(chaosDraftEditions); - Collections.shuffle(shuffled); - - final Supplier> ChaosDraftSupplier = new ChaosBoosterSupplier(shuffled); - + final Iterable chaosDraftEditions = Iterables.filter( + allEditions.getOrderedEditions(), + themeFilter); + // Add chaos "boosters" as special suppliers + final Supplier> ChaosDraftSupplier; + try { + ChaosDraftSupplier = new ChaosBoosterSupplier(chaosDraftEditions); + } catch(IllegalArgumentException e) { + System.out.println(e.getMessage()); + return false; + } for (int i = 0; i < 3; i++) { this.product.add(ChaosDraftSupplier); } diff --git a/forge-gui/src/main/java/forge/limited/ThemedChaosDraft.java b/forge-gui/src/main/java/forge/limited/ThemedChaosDraft.java new file mode 100644 index 00000000000..1b207167087 --- /dev/null +++ b/forge-gui/src/main/java/forge/limited/ThemedChaosDraft.java @@ -0,0 +1,218 @@ +package forge.limited; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; + +import forge.card.CardEdition; +import forge.game.GameFormat; +import forge.model.FModel; +import forge.util.TextUtil; +import forge.util.storage.StorageReaderFile; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.List; + +/** + * Themed chaos draft allows limiting the pool of available random boosters for a draft to a certain theme. + */ +public class ThemedChaosDraft implements Comparable { + private final String tag; + private final String label; + private final int orderNumber; + + /** + * @param tag Tag name used in edition files. + * @param label Label used in user interface. + * @param orderNumber Number used to order entries in user interface. + */ + public ThemedChaosDraft(String tag, String label, int orderNumber) { + this.tag = tag; + this.label = label; + this.orderNumber = orderNumber; + } + + /** + * @return theme tag + */ + public String getTag() { return tag; } + + /** + * @return theme label + */ + public String getLabel() { return label; } + + /** + * @return theme order number + */ + public int getOrderNumber() { return orderNumber; } + + /** + * @return Predicate to sort out editions not belonging to the chaos draft theme + */ + public Predicate getEditionFilter() { + Predicate filter; + switch(tag) { + case "DEFAULT": + filter = DEFAULT_FILTER; + break; + case "MODERN": + case "PIONEER": + case "STANDARD": + filter = getFormatFilter(tag); + break; + default: + filter = themedFilter; + } + return filter; + } + + /** + * Filter to select editions by ChaosDraftThemes tag defined in edition files. + * Tag must be defined in res/blockdata/chaosdraftthemes.txt + */ + private final Predicate themedFilter = new Predicate() { + @Override + public boolean apply(final CardEdition cardEdition) { + String[] themes = cardEdition.getChaosDraftThemes(); + for (String theme : themes) { + if (tag.equals(theme)) return true; + } + return false; + } + }; + + /** + * @param formatName format to filter by, currently supported: MODERN, PIONEER, STANDARD + * @return Filter to select editions belonging to a certain constructed format. + */ + private Predicate getFormatFilter(String formatName) { + GameFormat.Collection formats = FModel.getFormats(); + GameFormat format; + switch(formatName) { + case "MODERN": + format = formats.getModern(); + break; + case "PIONEER": + format = formats.getPioneer(); + break; + case "STANDARD": + default: + format = formats.getStandard(); + } + return new Predicate() { + @Override + public boolean apply(final CardEdition cardEdition){ + return DEFAULT_FILTER.apply(cardEdition) && format.isSetLegal(cardEdition.getCode()); + } + }; + } + + /** + * Default filter that only allows actual sets that were printed as 15-card boosters + */ + private static final Predicate DEFAULT_FILTER = new Predicate() { + @Override + public boolean apply(final CardEdition cardEdition) { + boolean isExpansion = cardEdition.getType().equals(CardEdition.Type.EXPANSION); + boolean isCoreSet = cardEdition.getType().equals(CardEdition.Type.CORE); + boolean isReprintSet = cardEdition.getType().equals(CardEdition.Type.REPRINT); + if (isExpansion || isCoreSet || isReprintSet) { + // Only allow sets with 15 cards in booster packs + if (cardEdition.hasBoosterTemplate()) { + final List> slots = cardEdition.getBoosterTemplate().getSlots(); + int boosterSize = 0; + for (Pair slot : slots) { + boosterSize += slot.getRight(); + } + return boosterSize == 15; + } + } + return false; + } + }; + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return this.label; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + ((this.tag == null) ? 0 : this.tag.hashCode()); + result = (prime * result) + ((this.label == null) ? 0 : this.label.hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + @Override + public int compareTo(ThemedChaosDraft other) { + return (this.orderNumber != other.orderNumber) + ? this.orderNumber - other.orderNumber + : this.label.compareTo(other.label); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (this.getClass() != obj.getClass()) { + return false; + } + + final ThemedChaosDraft other = (ThemedChaosDraft) obj; + if (!this.label.equals(other.label)) { + return false; + } + if (!this.tag.equals(other.tag)) { + return false; + } + return true; + } + + public static final Function FN_GET_TAG = new Function() { + @Override + public String apply(ThemedChaosDraft themedChaosBooster) { + return themedChaosBooster.getTag(); + } + }; + + public static class Reader extends StorageReaderFile { + public Reader(String pathname) { + super(pathname, ThemedChaosDraft.FN_GET_TAG); + } + + @Override + protected ThemedChaosDraft read(String line, int idx) { + final String[] sParts = TextUtil.splitWithParenthesis(line, ',', 3); + int orderNumber = Integer.parseInt(sParts[0].trim(), 10); + String tag = sParts[1].trim(); + String label = sParts[2].trim(); + return new ThemedChaosDraft(tag, label, orderNumber); + } + } +} diff --git a/forge-gui/src/main/java/forge/model/FModel.java b/forge-gui/src/main/java/forge/model/FModel.java index fe3dc41129f..1c1a621b8c1 100644 --- a/forge-gui/src/main/java/forge/model/FModel.java +++ b/forge-gui/src/main/java/forge/model/FModel.java @@ -37,6 +37,7 @@ import forge.gauntlet.GauntletData; import forge.interfaces.IProgressBar; import forge.itemmanager.ItemManagerConfig; import forge.limited.GauntletMini; +import forge.limited.ThemedChaosDraft; import forge.planarconquest.ConquestController; import forge.planarconquest.ConquestPlane; import forge.planarconquest.ConquestPreferences; @@ -91,6 +92,7 @@ public final class FModel { private static IStorage blocks; private static IStorage fantasyBlocks; + private static IStorage themedChaosDrafts; private static IStorage planes; private static IStorage worlds; private static GameFormat.Collection formats; @@ -187,6 +189,7 @@ public final class FModel { questPreferences = new QuestPreferences(); conquestPreferences = new ConquestPreferences(); fantasyBlocks = new StorageBase<>("Custom blocks", new CardBlock.Reader(ForgeConstants.BLOCK_DATA_DIR + "fantasyblocks.txt", magicDb.getEditions())); + themedChaosDrafts = new StorageBase<>("Themed Chaos Drafts", new ThemedChaosDraft.Reader(ForgeConstants.BLOCK_DATA_DIR + "chaosdraftthemes.txt")); planes = new StorageBase<>("Conquest planes", new ConquestPlane.Reader(ForgeConstants.CONQUEST_PLANES_DIR + "planes.txt")); Map standardWorlds = new QuestWorld.Reader(ForgeConstants.QUEST_WORLD_DIR + "worlds.txt").readAll(); Map customWorlds = new QuestWorld.Reader(ForgeConstants.USER_QUEST_WORLD_DIR + "customworlds.txt").readAll(); @@ -383,6 +386,10 @@ public final class FModel { return fantasyBlocks; } + public static IStorage getThemedChaosDrafts() { + return themedChaosDrafts; + } + public static TournamentData getTournamentData() { return tournamentData; } public static void setTournamentData(TournamentData tournamentData) { FModel.tournamentData = tournamentData; }