mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 02:38:02 +00:00
UnOpenedProduct now supports limited pools (when you define that there is a single card per cube)
This commit is contained in:
@@ -18,9 +18,9 @@
|
|||||||
package forge.card;
|
package forge.card;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
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;
|
||||||
@@ -47,7 +47,7 @@ import forge.util.TextUtil;
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class BoosterGenerator {
|
public class BoosterGenerator {
|
||||||
private final static Map<String, PrintSheet> cachedSheets = new HashMap<String, PrintSheet>();
|
private final static Map<String, PrintSheet> cachedSheets = new TreeMap<String, PrintSheet>(String.CASE_INSENSITIVE_ORDER);
|
||||||
private static final synchronized PrintSheet getPrintSheet(String key) {
|
private static final synchronized PrintSheet getPrintSheet(String key) {
|
||||||
if( !cachedSheets.containsKey(key) )
|
if( !cachedSheets.containsKey(key) )
|
||||||
cachedSheets.put(key, makeSheet(key, CardDb.instance().getAllCards()));
|
cachedSheets.put(key, makeSheet(key, CardDb.instance().getAllCards()));
|
||||||
@@ -69,26 +69,8 @@ public class BoosterGenerator {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If they request cards from an arbitrary pool, there's no use to cache printsheets.
|
|
||||||
public static final List<CardPrinted> getBoosterPack(SealedProductTemplate booster, Iterable<CardPrinted> sourcePool) {
|
|
||||||
if(sourcePool == CardDb.instance().getAllCards())
|
|
||||||
throw new IllegalArgumentException("Do not use this overload to obtain boosters based on complete cardDb");
|
|
||||||
if(null == sourcePool)
|
|
||||||
return getBoosterPack(booster);
|
|
||||||
|
|
||||||
List<CardPrinted> result = new ArrayList<CardPrinted>();
|
|
||||||
for(Pair<String, Integer> slot : booster.getSlots()) {
|
|
||||||
String slotType = slot.getLeft(); // add expansion symbol here?
|
|
||||||
int numCards = slot.getRight().intValue();
|
|
||||||
|
|
||||||
PrintSheet ps = makeSheet(slotType, sourcePool);
|
|
||||||
result.addAll(ps.random(numCards, true));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static final PrintSheet makeSheet(String sheetKey, Iterable<CardPrinted> src) {
|
public static final PrintSheet makeSheet(String sheetKey, Iterable<CardPrinted> src) {
|
||||||
PrintSheet ps = new PrintSheet(sheetKey);
|
PrintSheet ps = new PrintSheet(sheetKey);
|
||||||
String[] sKey = TextUtil.splitWithParenthesis(sheetKey, ' ', '(', ')', 2);
|
String[] sKey = TextUtil.splitWithParenthesis(sheetKey, ' ', '(', ')', 2);
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,8 @@ import java.io.File;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
|
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.game.limited.CustomLimited;
|
import forge.game.limited.CustomLimited;
|
||||||
import forge.item.CardDb;
|
|
||||||
import forge.item.CardPrinted;
|
import forge.item.CardPrinted;
|
||||||
import forge.item.IPaperCard;
|
import forge.item.IPaperCard;
|
||||||
import forge.util.FileUtil;
|
import forge.util.FileUtil;
|
||||||
@@ -168,8 +165,7 @@ public class MetaSet {
|
|||||||
|
|
||||||
case JoinedSet:
|
case JoinedSet:
|
||||||
Predicate<CardPrinted> predicate = IPaperCard.Predicates.printedInSets(data.split(" "));
|
Predicate<CardPrinted> predicate = IPaperCard.Predicates.printedInSets(data.split(" "));
|
||||||
Iterable<CardPrinted> pool = Iterables.filter(CardDb.instance().getAllCards(), predicate);
|
return new UnOpenedProduct(BoosterTemplate.genericBooster, predicate);
|
||||||
return new UnOpenedProduct(BoosterTemplate.genericBooster, pool);
|
|
||||||
|
|
||||||
case Choose:
|
case Choose:
|
||||||
return new UnOpenedMeta(data, true);
|
return new UnOpenedMeta(data, true);
|
||||||
|
|||||||
@@ -29,25 +29,20 @@ public class SealedProductTemplate {
|
|||||||
protected final List<Pair<String, Integer>> slots;
|
protected final List<Pair<String, Integer>> slots;
|
||||||
|
|
||||||
|
|
||||||
public String getEdition() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final List<Pair<String, Integer>> getSlots() {
|
public final List<Pair<String, Integer>> getSlots() {
|
||||||
return slots;
|
return slots;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getEdition() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public SealedProductTemplate(Iterable<Pair<String, Integer>> itrSlots)
|
public SealedProductTemplate(Iterable<Pair<String, Integer>> itrSlots)
|
||||||
{
|
{
|
||||||
slots = Lists.newArrayList(itrSlots);
|
slots = Lists.newArrayList(itrSlots);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
public int getNumberOfCardsExpected() {
|
||||||
public SealedProductTemplate(int qty) {
|
|
||||||
this(Lists.newArrayList(Pair.of("any", qty)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTotal() {
|
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
for(Pair<String, Integer> p : slots) {
|
for(Pair<String, Integer> p : slots) {
|
||||||
sum += p.getRight().intValue();
|
sum += p.getRight().intValue();
|
||||||
|
|||||||
@@ -1,41 +1,83 @@
|
|||||||
package forge.card;
|
package forge.card;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
import forge.item.CardDb;
|
||||||
import forge.item.CardPrinted;
|
import forge.item.CardPrinted;
|
||||||
import forge.item.ItemPoolView;
|
import forge.item.ItemPoolView;
|
||||||
|
import forge.item.PrintSheet;
|
||||||
|
|
||||||
public class UnOpenedProduct implements IUnOpenedProduct {
|
public class UnOpenedProduct implements IUnOpenedProduct {
|
||||||
|
|
||||||
private final ItemPoolView<CardPrinted> cards;
|
|
||||||
private final Iterable<CardPrinted> cardPoolFlat;
|
|
||||||
private final SealedProductTemplate tpl;
|
private final SealedProductTemplate tpl;
|
||||||
/**
|
private final Map<String, PrintSheet> sheets;
|
||||||
* TODO: Write javadoc for Constructor.
|
private boolean poolLimited = false; // if true after successful generation cards are removed from printsheets.
|
||||||
*/
|
|
||||||
|
public final boolean isPoolLimited() {
|
||||||
|
return poolLimited;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setLimitedPool(boolean considerNumbersInPool) {
|
||||||
|
this.poolLimited = considerNumbersInPool; // TODO: Add 0 to parameter's name.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Means to select from all unique cards (from base game, ie. no schemes or avatars)
|
||||||
public UnOpenedProduct(SealedProductTemplate template) {
|
public UnOpenedProduct(SealedProductTemplate template) {
|
||||||
tpl = template;
|
tpl = template;
|
||||||
cards = null;
|
sheets = null;
|
||||||
cardPoolFlat = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Invoke this constructor only if you are sure that the pool is not equal to deafult carddb
|
||||||
public UnOpenedProduct(SealedProductTemplate template, ItemPoolView<CardPrinted> pool) {
|
public UnOpenedProduct(SealedProductTemplate template, ItemPoolView<CardPrinted> pool) {
|
||||||
cards = pool;
|
this(template, pool.toFlatList());
|
||||||
cardPoolFlat = null;
|
|
||||||
tpl = template;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnOpenedProduct(SealedProductTemplate template, Iterable<CardPrinted> pool) {
|
public UnOpenedProduct(SealedProductTemplate template, Iterable<CardPrinted> cards) {
|
||||||
cardPoolFlat = pool;
|
|
||||||
tpl = template;
|
tpl = template;
|
||||||
cards = null;
|
sheets = new TreeMap<String, PrintSheet>();
|
||||||
|
prebuildSheets(cards);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnOpenedProduct(SealedProductTemplate sealedProductTemplate, Predicate<CardPrinted> filterPrinted) {
|
||||||
|
this(sealedProductTemplate, Iterables.filter(CardDb.instance().getAllCards(), filterPrinted));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prebuildSheets(Iterable<CardPrinted> sourceList) {
|
||||||
|
for(Pair<String, Integer> cc : tpl.getSlots()) {
|
||||||
|
sheets.put(cc.getKey(), BoosterGenerator.makeSheet(cc.getKey(), sourceList));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CardPrinted> get() {
|
public List<CardPrinted> get() {
|
||||||
return cards == null && cardPoolFlat == null ? BoosterGenerator.getBoosterPack(tpl)
|
return sheets == null ? BoosterGenerator.getBoosterPack(tpl) : getBoosterPack();
|
||||||
: BoosterGenerator.getBoosterPack(tpl, cardPoolFlat == null ? cards.toFlatList() : cardPoolFlat);
|
}
|
||||||
|
|
||||||
|
// If they request cards from an arbitrary pool, there's no use to cache printsheets.
|
||||||
|
private final List<CardPrinted> getBoosterPack() {
|
||||||
|
List<CardPrinted> result = new ArrayList<CardPrinted>();
|
||||||
|
for(Pair<String, Integer> slot : tpl.getSlots()) {
|
||||||
|
PrintSheet ps = sheets.get(slot.getLeft());
|
||||||
|
if(ps.isEmpty() && poolLimited ) {
|
||||||
|
throw new IllegalStateException("The cardpool has been depleted and has no more cards for slot " + slot.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CardPrinted> foundCards = ps.random(slot.getRight().intValue(), true);
|
||||||
|
if(poolLimited)
|
||||||
|
ps.removeAll(foundCards);
|
||||||
|
result.addAll(foundCards);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +36,6 @@ import com.google.common.base.Supplier;
|
|||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.Constant.Preferences;
|
import forge.Constant.Preferences;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.BoosterGenerator;
|
|
||||||
import forge.card.BoosterTemplate;
|
import forge.card.BoosterTemplate;
|
||||||
import forge.card.CardBlock;
|
import forge.card.CardBlock;
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
@@ -89,9 +88,7 @@ public final class BoosterDraft implements IBoosterDraft {
|
|||||||
|
|
||||||
switch (draftType) {
|
switch (draftType) {
|
||||||
case Full: // Draft from all cards in Forge
|
case Full: // Draft from all cards in Forge
|
||||||
Supplier<List<CardPrinted>> s = new Supplier<List<CardPrinted>>() {
|
Supplier<List<CardPrinted>> s = new UnOpenedProduct(BoosterTemplate.genericBooster);
|
||||||
@Override public List<CardPrinted> get() { return BoosterGenerator.getBoosterPack(BoosterTemplate.genericBooster); }
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) this.product.add(s);
|
for (int i = 0; i < 3; i++) this.product.add(s);
|
||||||
IBoosterDraft.LAND_SET_CODE[0] = CardDb.instance().getCard("Plains").getEdition();
|
IBoosterDraft.LAND_SET_CODE[0] = CardDb.instance().getCard("Plains").getEdition();
|
||||||
@@ -167,8 +164,9 @@ public final class BoosterDraft implements IBoosterDraft {
|
|||||||
|
|
||||||
final SealedProductTemplate tpl = draft.getSealedProductTemplate();
|
final SealedProductTemplate tpl = draft.getSealedProductTemplate();
|
||||||
|
|
||||||
|
UnOpenedProduct toAdd = new UnOpenedProduct(tpl, dPool);
|
||||||
for (int i = 0; i < draft.getNumPacks(); i++) {
|
for (int i = 0; i < draft.getNumPacks(); i++) {
|
||||||
this.product.add(new UnOpenedProduct(tpl, dPool));
|
this.product.add(toAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
IBoosterDraft.LAND_SET_CODE[0] = draft.getLandSetCode();
|
IBoosterDraft.LAND_SET_CODE[0] = draft.getLandSetCode();
|
||||||
|
|||||||
@@ -246,19 +246,17 @@ public class SealedDeckFormat {
|
|||||||
if (element.endsWith(".sealed")) {
|
if (element.endsWith(".sealed")) {
|
||||||
final List<String> dfData = FileUtil.readFile("res/sealed/" + element);
|
final List<String> dfData = FileUtil.readFile("res/sealed/" + element);
|
||||||
final CustomLimited cs = CustomLimited.parse(dfData, Singletons.getModel().getDecks().getCubes());
|
final CustomLimited cs = CustomLimited.parse(dfData, Singletons.getModel().getDecks().getCubes());
|
||||||
if (cs.getSealedProductTemplate().getTotal() > 5) { // Do not allow too small cubes to be played as 'stand-alone'!
|
if (cs.getSealedProductTemplate().getNumberOfCardsExpected() > 5) { // Do not allow too small cubes to be played as 'stand-alone'!
|
||||||
customs.add(cs);
|
customs.add(cs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// present list to user
|
// present list to user
|
||||||
if (customs.size() < 1) {
|
if (customs.isEmpty()) {
|
||||||
JOptionPane.showMessageDialog(null, "No custom sealed files found.", "",
|
JOptionPane.showMessageDialog(null, "No custom sealed files found.", "", JOptionPane.INFORMATION_MESSAGE);
|
||||||
JOptionPane.INFORMATION_MESSAGE);
|
|
||||||
} else {
|
} else {
|
||||||
final CustomLimited draft = GuiChoose.one("Choose Custom Sealed Pool",
|
final CustomLimited draft = GuiChoose.one("Choose Custom Sealed Pool", customs);
|
||||||
customs);
|
|
||||||
|
|
||||||
|
|
||||||
// Choose number of boosters
|
// Choose number of boosters
|
||||||
@@ -270,8 +268,9 @@ public class SealedDeckFormat {
|
|||||||
|
|
||||||
Integer nrBoosters = GuiChoose.one("How many booster packs?", integers);
|
Integer nrBoosters = GuiChoose.one("How many booster packs?", integers);
|
||||||
|
|
||||||
|
IUnOpenedProduct toAdd = new UnOpenedProduct(draft.getSealedProductTemplate(), draft.getCardPool());
|
||||||
for (int i = 0; i < nrBoosters; i++) {
|
for (int i = 0; i < nrBoosters; i++) {
|
||||||
this.product.add(new UnOpenedProduct(draft.getSealedProductTemplate(), draft.getCardPool()));
|
this.product.add(toAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getLandSetCode()[0] = draft.getLandSetCode();
|
this.getLandSetCode()[0] = draft.getLandSetCode();
|
||||||
|
|||||||
@@ -71,6 +71,6 @@ public class FatPack extends OpenablePack {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTotalCards() {
|
public int getTotalCards() {
|
||||||
return super.getTotalCards() * fpData.getCntBoosters() + fpData.getTotal();
|
return super.getTotalCards() * fpData.getCntBoosters() + fpData.getNumberOfCardsExpected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public abstract class OpenablePack implements InventoryItemFromSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getTotalCards() {
|
public int getTotalCards() {
|
||||||
return contents.getTotal();
|
return contents.getNumberOfCardsExpected();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -52,6 +52,13 @@ public class PrintSheet {
|
|||||||
cardsWithWeights.add(card, weight);
|
cardsWithWeights.add(card, weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Cuts cards out of a sheet - they won't be printed again.
|
||||||
|
* Please use mutable sheets for cubes only.*/
|
||||||
|
public void removeAll(Iterable<CardPrinted> cards) {
|
||||||
|
for(CardPrinted card : cards)
|
||||||
|
cardsWithWeights.remove(card);
|
||||||
|
}
|
||||||
|
|
||||||
private CardPrinted fetchRoulette(int start, int roulette, Collection<CardPrinted> toSkip) {
|
private CardPrinted fetchRoulette(int start, int roulette, Collection<CardPrinted> toSkip) {
|
||||||
int sum = start;
|
int sum = start;
|
||||||
boolean isSecondRun = start > 0;
|
boolean isSecondRun = start > 0;
|
||||||
@@ -107,5 +114,9 @@ public class PrintSheet {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return cardsWithWeights.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,12 +29,13 @@ import com.google.common.base.Predicates;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import forge.Constant;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.BoosterGenerator;
|
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
import forge.card.CardRarity;
|
import forge.card.CardRarity;
|
||||||
import forge.card.FormatCollection;
|
import forge.card.FormatCollection;
|
||||||
import forge.card.SealedProductTemplate;
|
import forge.card.SealedProductTemplate;
|
||||||
|
import forge.card.UnOpenedProduct;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.deck.DeckSection;
|
import forge.deck.DeckSection;
|
||||||
import forge.item.BoosterPack;
|
import forge.item.BoosterPack;
|
||||||
@@ -120,11 +121,10 @@ public final class QuestUtilCards {
|
|||||||
landCode = "M10";
|
landCode = "M10";
|
||||||
}
|
}
|
||||||
|
|
||||||
pool.add(db.getCard("Forest", landCode), nBasic);
|
for(String landName : Constant.Color.BASIC_LANDS) {
|
||||||
pool.add(db.getCard("Mountain", landCode), nBasic);
|
pool.add(db.getCard(landName, landCode), nBasic);
|
||||||
pool.add(db.getCard("Swamp", landCode), nBasic);
|
}
|
||||||
pool.add(db.getCard("Island", landCode), nBasic);
|
|
||||||
pool.add(db.getCard("Plains", landCode), nBasic);
|
|
||||||
|
|
||||||
if (!snowLandCodes.isEmpty()) {
|
if (!snowLandCodes.isEmpty()) {
|
||||||
String snowLandCode = Aggregates.random(snowLandCodes);
|
String snowLandCode = Aggregates.random(snowLandCodes);
|
||||||
@@ -517,10 +517,7 @@ public final class QuestUtilCards {
|
|||||||
* Generate cards in shop.
|
* Generate cards in shop.
|
||||||
*/
|
*/
|
||||||
private void generateCardsInShop() {
|
private void generateCardsInShop() {
|
||||||
Iterable<CardPrinted> cardList = null;
|
|
||||||
if (qc.getFormat() != null) {
|
|
||||||
cardList = Iterables.filter(CardDb.instance().getAllCards(), qc.getFormat().getFilterPrinted());
|
|
||||||
}
|
|
||||||
|
|
||||||
int nLevel = this.qc.getAchievements().getLevel();
|
int nLevel = this.qc.getAchievements().getLevel();
|
||||||
|
|
||||||
@@ -537,12 +534,11 @@ public final class QuestUtilCards {
|
|||||||
final int totalPacks = Math.min(levelPacks + winPacks, maxPacks);
|
final int totalPacks = Math.min(levelPacks + winPacks, maxPacks);
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
SealedProductTemplate template = new SealedProductTemplate(Lists.newArrayList(
|
SealedProductTemplate tpl = new SealedProductTemplate(Lists.newArrayList( Pair.of("Common", common), Pair.of("Uncommon", uncommon), Pair.of("RareMythic", rare)));
|
||||||
Pair.of("Common", common), Pair.of("uncommon", uncommon), Pair.of("RareMythic", rare)
|
UnOpenedProduct unopened = qc.getFormat() == null ? new UnOpenedProduct( tpl ) : new UnOpenedProduct( tpl, qc.getFormat().getFilterPrinted());
|
||||||
));
|
|
||||||
|
|
||||||
for (int i = 0; i < totalPacks; i++) {
|
for (int i = 0; i < totalPacks; i++) {
|
||||||
this.qa.getShopList().addAllFlat(BoosterGenerator.getBoosterPack(template, cardList));
|
this.qa.getShopList().addAllFlat(unopened.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.generateBoostersInShop(totalPacks);
|
this.generateBoostersInShop(totalPacks);
|
||||||
|
|||||||
Reference in New Issue
Block a user