From 13adabd1693343294510b810c7afa7ab045d0c4b Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Tue, 28 Jan 2025 01:17:11 +0400 Subject: [PATCH] deck: added boosters for some sets and other (related to #13160): * added boosters to Innistrad: Double Feature (DBL); * added boosters to 30th Anniversary Edition (30A); * added Chaos Orb reprint to 30A; * fixed wrong card art styles in ZNE; --- .../src/mage/sets/InnistradDoubleFeature.java | 10 ++- Mage.Sets/src/mage/sets/SecretLairDrop.java | 2 +- .../mage/sets/The30thAnniversaryEdition.java | 15 ++--- .../mage/sets/ZendikarRisingExpeditions.java | 62 +++++++++---------- .../main/java/mage/cards/ExpansionSet.java | 17 ++--- 5 files changed, 55 insertions(+), 51 deletions(-) diff --git a/Mage.Sets/src/mage/sets/InnistradDoubleFeature.java b/Mage.Sets/src/mage/sets/InnistradDoubleFeature.java index 0f57868bee1..5c5007cae54 100644 --- a/Mage.Sets/src/mage/sets/InnistradDoubleFeature.java +++ b/Mage.Sets/src/mage/sets/InnistradDoubleFeature.java @@ -17,8 +17,14 @@ public final class InnistradDoubleFeature extends ExpansionSet { private InnistradDoubleFeature() { super("Innistrad: Double Feature", "DBL", ExpansionSet.buildDate(2021, 1, 28), SetType.SUPPLEMENTAL); + + // https://magic.wizards.com/en/news/feature/innistrad-double-feature-product-overview-2021-11-15 + // #535 Endless Ranks of the Dead is promo card, not in booster + // contains cards from x2 sets: Midnight Hunt and Crimson Vow + // simplified booster generation to use shared cards from both sets (real booster use 50/50 distribution) + this.enableDraftBooster(534, 0, 8 + 1, 4, 2); this.hasBasicLands = false; - // TODO: add booster generation + this.numBoosterDoubleFaced = -1; cards.add(new SetCardInfo("Abandon the Post", 127, Rarity.COMMON, mage.cards.a.AbandonThePost.class)); cards.add(new SetCardInfo("Abrade", 406, Rarity.COMMON, mage.cards.a.Abrade.class)); @@ -328,8 +334,8 @@ public final class InnistradDoubleFeature extends ExpansionSet { cards.add(new SetCardInfo("Howlpack Avenger", 429, Rarity.RARE, mage.cards.h.HowlpackAvenger.class)); cards.add(new SetCardInfo("Howlpack Piper", 472, Rarity.RARE, mage.cards.h.HowlpackPiper.class)); cards.add(new SetCardInfo("Hullbreaker Horror", 330, Rarity.RARE, mage.cards.h.HullbreakerHorror.class)); - cards.add(new SetCardInfo("Hungry Ridgewolf", 428, Rarity.COMMON, mage.cards.h.HungryRidgewolf.class)); cards.add(new SetCardInfo("Hungry for More", 228, Rarity.UNCOMMON, mage.cards.h.HungryForMore.class)); + cards.add(new SetCardInfo("Hungry Ridgewolf", 428, Rarity.COMMON, mage.cards.h.HungryRidgewolf.class)); cards.add(new SetCardInfo("Ill-Tempered Loner", 429, Rarity.RARE, mage.cards.i.IllTemperedLoner.class)); cards.add(new SetCardInfo("Immolation", 144, Rarity.COMMON, mage.cards.i.Immolation.class)); cards.add(new SetCardInfo("Infernal Grasp", 107, Rarity.UNCOMMON, mage.cards.i.InfernalGrasp.class)); diff --git a/Mage.Sets/src/mage/sets/SecretLairDrop.java b/Mage.Sets/src/mage/sets/SecretLairDrop.java index c4784b7e671..8636e57e720 100644 --- a/Mage.Sets/src/mage/sets/SecretLairDrop.java +++ b/Mage.Sets/src/mage/sets/SecretLairDrop.java @@ -17,7 +17,7 @@ public class SecretLairDrop extends ExpansionSet { private SecretLairDrop() { super("Secret Lair Drop", "SLD", ExpansionSet.buildDate(2020, 3, 12), SetType.PROMOTIONAL); - this.hasBoosters = false; + this.hasBoosters = false; // no boosters, it's a cards shop this.hasBasicLands = true; // warning diff --git a/Mage.Sets/src/mage/sets/The30thAnniversaryEdition.java b/Mage.Sets/src/mage/sets/The30thAnniversaryEdition.java index 4db6233f6aa..da2481071a1 100644 --- a/Mage.Sets/src/mage/sets/The30thAnniversaryEdition.java +++ b/Mage.Sets/src/mage/sets/The30thAnniversaryEdition.java @@ -19,13 +19,10 @@ public class The30thAnniversaryEdition extends ExpansionSet { private The30thAnniversaryEdition() { super("30th Anniversary Edition", "30A", ExpansionSet.buildDate(2022, 11, 28), SetType.PROMOTIONAL); - this.hasBasicLands = true; - this.numBoosterLands = 3; - this.numBoosterCommon = 7; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.numBoosterSpecial = 1; - this.ratioBoosterMythic = 8; + + // https://mtg.fandom.com/wiki/30th_Anniversary_Edition + // Approximately three out of every ten packs will contain a rare retro frame card + this.enableDraftBooster(Integer.MAX_VALUE, 3, 7, 3, 1 + 1); // +1 to rare instead retro frame cards.add(new SetCardInfo("Air Elemental", 343, Rarity.UNCOMMON, mage.cards.a.AirElemental.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Air Elemental", 46, Rarity.UNCOMMON, mage.cards.a.AirElemental.class, NON_FULL_USE_VARIOUS)); @@ -89,8 +86,8 @@ public class The30thAnniversaryEdition extends ExpansionSet { cards.add(new SetCardInfo("Celestial Prism", 527, Rarity.UNCOMMON, mage.cards.c.CelestialPrism.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Channel", 184, Rarity.UNCOMMON, mage.cards.c.Channel.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Channel", 481, Rarity.UNCOMMON, mage.cards.c.Channel.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Chaos Orb", 231, Rarity.RARE, mage.cards.c.ChaosOrb.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Chaos Orb", 528, Rarity.RARE, mage.cards.c.ChaosOrb.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Chaos Orb", 231, Rarity.RARE, mage.cards.c.ChaosOrb.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Chaos Orb", 528, Rarity.RARE, mage.cards.c.ChaosOrb.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Chaoslace", 136, Rarity.RARE, mage.cards.c.Chaoslace.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Chaoslace", 433, Rarity.RARE, mage.cards.c.Chaoslace.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Circle of Protection: Black", 10, Rarity.COMMON, mage.cards.c.CircleOfProtectionBlack.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage.Sets/src/mage/sets/ZendikarRisingExpeditions.java b/Mage.Sets/src/mage/sets/ZendikarRisingExpeditions.java index 8a169634610..4f786bf2f98 100644 --- a/Mage.Sets/src/mage/sets/ZendikarRisingExpeditions.java +++ b/Mage.Sets/src/mage/sets/ZendikarRisingExpeditions.java @@ -18,38 +18,38 @@ public final class ZendikarRisingExpeditions extends ExpansionSet { private ZendikarRisingExpeditions() { super("Zendikar Rising Expeditions", "ZNE", ExpansionSet.buildDate(2020, 9, 25), SetType.PROMOTIONAL); this.blockName = "Masterpiece Series"; - this.hasBoosters = false; + this.hasBoosters = false; // no boosters, it's a box toppers this.hasBasicLands = false; - cards.add(new SetCardInfo("Ancient Tomb", 21, Rarity.MYTHIC, mage.cards.a.AncientTomb.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Arid Mesa", 9, Rarity.MYTHIC, mage.cards.a.AridMesa.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Blackcleave Cliffs", 13, Rarity.MYTHIC, mage.cards.b.BlackcleaveCliffs.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Bloodstained Mire", 3, Rarity.MYTHIC, mage.cards.b.BloodstainedMire.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Bountiful Promenade", 20, Rarity.MYTHIC, mage.cards.b.BountifulPromenade.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Cavern of Souls", 22, Rarity.MYTHIC, mage.cards.c.CavernOfSouls.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Celestial Colonnade", 23, Rarity.MYTHIC, mage.cards.c.CelestialColonnade.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Copperline Gorge", 14, Rarity.MYTHIC, mage.cards.c.CopperlineGorge.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Creeping Tar Pit", 24, Rarity.MYTHIC, mage.cards.c.CreepingTarPit.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Darkslick Shores", 12, Rarity.MYTHIC, mage.cards.d.DarkslickShores.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Flooded Strand", 1, Rarity.MYTHIC, mage.cards.f.FloodedStrand.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Grove of the Burnwillows", 25, Rarity.MYTHIC, mage.cards.g.GroveOfTheBurnwillows.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Horizon Canopy", 26, Rarity.MYTHIC, mage.cards.h.HorizonCanopy.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Luxury Suite", 18, Rarity.MYTHIC, mage.cards.l.LuxurySuite.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Marsh Flats", 6, Rarity.MYTHIC, mage.cards.m.MarshFlats.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Misty Rainforest", 10, Rarity.MYTHIC, mage.cards.m.MistyRainforest.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Morphic Pool", 17, Rarity.MYTHIC, mage.cards.m.MorphicPool.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Polluted Delta", 2, Rarity.MYTHIC, mage.cards.p.PollutedDelta.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Prismatic Vista", 27, Rarity.MYTHIC, mage.cards.p.PrismaticVista.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Razorverge Thicket", 15, Rarity.MYTHIC, mage.cards.r.RazorvergeThicket.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Scalding Tarn", 7, Rarity.MYTHIC, mage.cards.s.ScaldingTarn.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Sea of Clouds", 16, Rarity.MYTHIC, mage.cards.s.SeaOfClouds.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Seachrome Coast", 11, Rarity.MYTHIC, mage.cards.s.SeachromeCoast.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Spire Garden", 19, Rarity.MYTHIC, mage.cards.s.SpireGarden.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Strip Mine", 28, Rarity.MYTHIC, mage.cards.s.StripMine.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Valakut, the Molten Pinnacle", 29, Rarity.MYTHIC, mage.cards.v.ValakutTheMoltenPinnacle.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Verdant Catacombs", 8, Rarity.MYTHIC, mage.cards.v.VerdantCatacombs.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Wasteland", 30, Rarity.MYTHIC, mage.cards.w.Wasteland.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Windswept Heath", 5, Rarity.MYTHIC, mage.cards.w.WindsweptHeath.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Wooded Foothills", 4, Rarity.MYTHIC, mage.cards.w.WoodedFoothills.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Ancient Tomb", 21, Rarity.MYTHIC, mage.cards.a.AncientTomb.class)); + cards.add(new SetCardInfo("Arid Mesa", 9, Rarity.MYTHIC, mage.cards.a.AridMesa.class)); + cards.add(new SetCardInfo("Blackcleave Cliffs", 13, Rarity.MYTHIC, mage.cards.b.BlackcleaveCliffs.class)); + cards.add(new SetCardInfo("Bloodstained Mire", 3, Rarity.MYTHIC, mage.cards.b.BloodstainedMire.class)); + cards.add(new SetCardInfo("Bountiful Promenade", 20, Rarity.MYTHIC, mage.cards.b.BountifulPromenade.class)); + cards.add(new SetCardInfo("Cavern of Souls", 22, Rarity.MYTHIC, mage.cards.c.CavernOfSouls.class)); + cards.add(new SetCardInfo("Celestial Colonnade", 23, Rarity.MYTHIC, mage.cards.c.CelestialColonnade.class)); + cards.add(new SetCardInfo("Copperline Gorge", 14, Rarity.MYTHIC, mage.cards.c.CopperlineGorge.class)); + cards.add(new SetCardInfo("Creeping Tar Pit", 24, Rarity.MYTHIC, mage.cards.c.CreepingTarPit.class)); + cards.add(new SetCardInfo("Darkslick Shores", 12, Rarity.MYTHIC, mage.cards.d.DarkslickShores.class)); + cards.add(new SetCardInfo("Flooded Strand", 1, Rarity.MYTHIC, mage.cards.f.FloodedStrand.class)); + cards.add(new SetCardInfo("Grove of the Burnwillows", 25, Rarity.MYTHIC, mage.cards.g.GroveOfTheBurnwillows.class)); + cards.add(new SetCardInfo("Horizon Canopy", 26, Rarity.MYTHIC, mage.cards.h.HorizonCanopy.class)); + cards.add(new SetCardInfo("Luxury Suite", 18, Rarity.MYTHIC, mage.cards.l.LuxurySuite.class)); + cards.add(new SetCardInfo("Marsh Flats", 6, Rarity.MYTHIC, mage.cards.m.MarshFlats.class)); + cards.add(new SetCardInfo("Misty Rainforest", 10, Rarity.MYTHIC, mage.cards.m.MistyRainforest.class)); + cards.add(new SetCardInfo("Morphic Pool", 17, Rarity.MYTHIC, mage.cards.m.MorphicPool.class)); + cards.add(new SetCardInfo("Polluted Delta", 2, Rarity.MYTHIC, mage.cards.p.PollutedDelta.class)); + cards.add(new SetCardInfo("Prismatic Vista", 27, Rarity.MYTHIC, mage.cards.p.PrismaticVista.class)); + cards.add(new SetCardInfo("Razorverge Thicket", 15, Rarity.MYTHIC, mage.cards.r.RazorvergeThicket.class)); + cards.add(new SetCardInfo("Scalding Tarn", 7, Rarity.MYTHIC, mage.cards.s.ScaldingTarn.class)); + cards.add(new SetCardInfo("Sea of Clouds", 16, Rarity.MYTHIC, mage.cards.s.SeaOfClouds.class)); + cards.add(new SetCardInfo("Seachrome Coast", 11, Rarity.MYTHIC, mage.cards.s.SeachromeCoast.class)); + cards.add(new SetCardInfo("Spire Garden", 19, Rarity.MYTHIC, mage.cards.s.SpireGarden.class)); + cards.add(new SetCardInfo("Strip Mine", 28, Rarity.MYTHIC, mage.cards.s.StripMine.class)); + cards.add(new SetCardInfo("Valakut, the Molten Pinnacle", 29, Rarity.MYTHIC, mage.cards.v.ValakutTheMoltenPinnacle.class)); + cards.add(new SetCardInfo("Verdant Catacombs", 8, Rarity.MYTHIC, mage.cards.v.VerdantCatacombs.class)); + cards.add(new SetCardInfo("Wasteland", 30, Rarity.MYTHIC, mage.cards.w.Wasteland.class)); + cards.add(new SetCardInfo("Windswept Heath", 5, Rarity.MYTHIC, mage.cards.w.WindsweptHeath.class)); + cards.add(new SetCardInfo("Wooded Foothills", 4, Rarity.MYTHIC, mage.cards.w.WoodedFoothills.class)); } } diff --git a/Mage/src/main/java/mage/cards/ExpansionSet.java b/Mage/src/main/java/mage/cards/ExpansionSet.java index 40d24d761da..da2dcf13a53 100644 --- a/Mage/src/main/java/mage/cards/ExpansionSet.java +++ b/Mage/src/main/java/mage/cards/ExpansionSet.java @@ -189,7 +189,7 @@ public abstract class ExpansionSet implements Serializable { protected int numBoosterCommon; protected int numBoosterUncommon; protected int numBoosterRare; - protected int numBoosterDoubleFaced; // -1 = include normally 0 = exclude 1-n = include explicit + protected int numBoosterDoubleFaced; // -1 = include by rarity slots, 0 = fail on tests, 1-n = include explicit protected double ratioBoosterMythic; protected boolean hasUnbalancedColors = false; @@ -744,17 +744,18 @@ public abstract class ExpansionSet implements Serializable { /** * Old default booster configuration (before 2024 - MKM) */ - public void enableDraftBooster(int maxCardNumberInBooster) { + public void enableDraftBooster(int maxCardNumberInBooster, int land, int common, int uncommon, int rare) { // https://draftsim.com/draft-booster-vs-set-booster-mtg/ this.hasBoosters = true; this.maxCardNumberInBooster = maxCardNumberInBooster; - this.hasBasicLands = true; - this.numBoosterLands = 1; - this.numBoosterCommon = 10; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 8; + this.numBoosterLands = land; + this.hasBasicLands = land > 0; + + this.numBoosterCommon = common; + this.numBoosterUncommon = uncommon; + this.numBoosterRare = rare; + this.ratioBoosterMythic = 8; // 12.5% chance of a mythic rare } /**