UnOpenedProduct now supports limited pools (when you define that there is a single card per cube)

This commit is contained in:
Maxmtg
2013-04-27 18:09:22 +00:00
parent 66154323a3
commit 59aea5375a
10 changed files with 100 additions and 81 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();

View File

@@ -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;
} }
} }

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();
} }
} }

View File

@@ -68,7 +68,7 @@ public abstract class OpenablePack implements InventoryItemFromSet {
} }
public int getTotalCards() { public int getTotalCards() {
return contents.getTotal(); return contents.getNumberOfCardsExpected();
} }
@Override @Override

View File

@@ -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();
}
} }

View File

@@ -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);