From 79120e7484210ae2aefe006300f3f1873867528b Mon Sep 17 00:00:00 2001 From: Quercitron Date: Wed, 25 Jul 2018 02:46:31 +0300 Subject: [PATCH] Make color distribution in booster more uniform --- Mage.Sets/src/mage/sets/Dominaria.java | 2 +- .../mage/test/sets/BoosterGenerationTest.java | 15 +++- .../main/java/mage/cards/ExpansionSet.java | 87 +++++++++++++++++-- Mage/src/main/java/mage/util/RandomUtil.java | 4 + 4 files changed, 95 insertions(+), 13 deletions(-) diff --git a/Mage.Sets/src/mage/sets/Dominaria.java b/Mage.Sets/src/mage/sets/Dominaria.java index 6e48f762fe..98d533f195 100644 --- a/Mage.Sets/src/mage/sets/Dominaria.java +++ b/Mage.Sets/src/mage/sets/Dominaria.java @@ -26,7 +26,7 @@ public final class Dominaria extends ExpansionSet { this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 8; - this.needsLegends = true; + this.needsLegendCreature = true; this.maxCardNumberInBooster = 269; cards.add(new SetCardInfo("Academy Drake", 40, Rarity.COMMON, mage.cards.a.AcademyDrake.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/sets/BoosterGenerationTest.java b/Mage.Tests/src/test/java/org/mage/test/sets/BoosterGenerationTest.java index b6da9a2d9e..85f8da3236 100644 --- a/Mage.Tests/src/test/java/org/mage/test/sets/BoosterGenerationTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/sets/BoosterGenerationTest.java @@ -9,10 +9,8 @@ import mage.cards.repository.CardInfo; import mage.cards.repository.CardScanner; import mage.constants.CardType; import mage.constants.Rarity; -import mage.sets.CoreSet2019; -import mage.sets.FateReforged; -import mage.sets.MastersEditionII; -import mage.sets.MastersEditionIV; +import mage.sets.*; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -115,6 +113,15 @@ public class BoosterGenerationTest extends MageTestBase { assertTrue(allCards.stream().anyMatch(card -> card.getCardType().contains(CardType.LAND) && card.getRarity().equals(Rarity.COMMON))); } + @Test + public void testDominaria_EveryBoosterContainsLegendaryCreature() { + for (int i = 0; i < 10; i++) { + List booster = Dominaria.getInstance().createBooster(); + // check that booster contains legendary creature + assertTrue(booster.stream().anyMatch(card -> card.isCreature() && card.isLegendary())); + } + } + private static String str(List cards) { StringBuilder sb = new StringBuilder("["); Iterator iterator = cards.iterator(); diff --git a/Mage/src/main/java/mage/cards/ExpansionSet.java b/Mage/src/main/java/mage/cards/ExpansionSet.java index 2e0750d00e..f58e7c41c9 100644 --- a/Mage/src/main/java/mage/cards/ExpansionSet.java +++ b/Mage/src/main/java/mage/cards/ExpansionSet.java @@ -1,6 +1,7 @@ package mage.cards; +import mage.ObjectColor; import mage.cards.repository.CardCriteria; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; @@ -96,7 +97,11 @@ public abstract class ExpansionSet implements Serializable { protected int numBoosterRare; protected int numBoosterDoubleFaced; // -1 = include normally 0 = exclude 1-n = include explicit protected int ratioBoosterMythic; - protected boolean needsLegends = false; + + protected boolean needsLegendCreature = false; + protected boolean validateBoosterColors = true; + protected double rejectMissingColorProbability = 0.8; + protected double rejectSameColorUncommonsProbability = 0.8; protected int maxCardNumberInBooster; // used to omit cards with collector numbers beyond the regular cards in a set for boosters @@ -186,17 +191,83 @@ public abstract class ExpansionSet implements Serializable { } public List createBooster() { - if (needsLegends) { - for (int i = 0; i < 100000; i++) {//don't want to somehow loop forever - List booster = tryBooster(); - for (Card card : booster) { - if (card.isLegendary() && card.isCreature()) {// Dominaria packs must contain at least one legendary creature. - return booster; + for (int i = 0; i < 100; i++) {//don't want to somehow loop forever + List booster = tryBooster(); + if (boosterIsValid(booster)) { + return booster; + } + } + return tryBooster(); + } + + protected boolean boosterIsValid(List booster) { + if (validateBoosterColors) { + if (!validateColors(booster)) { + return false; + } + } + + if (needsLegendCreature) { + if (booster.stream().noneMatch(card -> card.isLegendary() && card.isCreature())) { + return false; + } + } + + return true; + } + + protected boolean validateColors(List booster) { + List magicColors = + Arrays.asList(ObjectColor.WHITE, ObjectColor.BLUE, ObjectColor.BLACK, ObjectColor.RED, ObjectColor.GREEN); + + // all cards colors + Map colorWeight = new HashMap<>(); + // uncommon/rare/mythic cards colors + Map uncommonWeight = new HashMap<>(); + + for (ObjectColor color : magicColors) { + colorWeight.put(color, 0); + uncommonWeight.put(color, 0); + } + + // count colors in the booster + for (Card card : booster) { + ObjectColor cardColor = card.getColor(null); + if (cardColor != null) { + List colors = cardColor.getColors(); + // todo: do we need gold color? + colors.remove(ObjectColor.GOLD); + if (!colors.isEmpty()) { + // 60 - full card weight + // multicolored cards add part of the weight to each color + int cardColorWeight = 60 / colors.size(); + for (ObjectColor color : colors) { + colorWeight.put(color, colorWeight.get(color) + cardColorWeight); + if (card.getRarity() != Rarity.COMMON) { + uncommonWeight.put(color, uncommonWeight.get(color) + cardColorWeight); + } } } } } - return tryBooster(); + + // check that all colors are present + if (magicColors.stream().anyMatch(color -> colorWeight.get(color) < 60)) { + // reject only part of the boosters + if (RandomUtil.nextDouble() < rejectMissingColorProbability) { + return false; + } + } + + // check that we don't have 3 or more uncommons/rares of the same color + if (magicColors.stream().anyMatch(color -> uncommonWeight.get(color) >= 180)) { + // reject only part of the boosters + if (RandomUtil.nextDouble() < rejectSameColorUncommonsProbability) { + return false; + } + } + + return true; } public List tryBooster() { diff --git a/Mage/src/main/java/mage/util/RandomUtil.java b/Mage/src/main/java/mage/util/RandomUtil.java index aa08d60938..2930798341 100644 --- a/Mage/src/main/java/mage/util/RandomUtil.java +++ b/Mage/src/main/java/mage/util/RandomUtil.java @@ -26,4 +26,8 @@ public final class RandomUtil { public static boolean nextBoolean() { return ThreadLocalRandom.current().nextBoolean(); } + + public static double nextDouble() { + return ThreadLocalRandom.current().nextDouble(); + } }