Add new booster pack quest starting pool generation, fix a card duplication bug in the quest shop, and improve the way the card shop generates singles

This commit is contained in:
Krazy
2017-05-25 06:13:04 +00:00
parent 5195b9c5b5
commit 3953610b56
12 changed files with 449 additions and 280 deletions

View File

@@ -52,6 +52,7 @@ public enum CSubmenuQuestData implements ICDoc {
private List<Byte> preferredColors = new ArrayList<>(); private List<Byte> preferredColors = new ArrayList<>();
private PoolType poolType = PoolType.BALANCED; private PoolType poolType = PoolType.BALANCED;
private boolean includeArtifacts = true; private boolean includeArtifacts = true;
private int numberOfBoosters = 0;
@Override @Override
public void register() { public void register() {
@@ -112,6 +113,7 @@ public enum CSubmenuQuestData implements ICDoc {
preferredColors = colorChooser.getPreferredColors(); preferredColors = colorChooser.getPreferredColors();
poolType = colorChooser.getPoolType(); poolType = colorChooser.getPoolType();
includeArtifacts = colorChooser.includeArtifacts(); includeArtifacts = colorChooser.includeArtifacts();
numberOfBoosters = colorChooser.getNumberOfBoosters();
} }
}); });
} }
@@ -270,7 +272,7 @@ public enum CSubmenuQuestData implements ICDoc {
} }
} }
final StartingPoolPreferences userPrefs = new StartingPoolPreferences(poolType, preferredColors, includeArtifacts, view.startWithCompleteSet(), view.allowDuplicateCards()); final StartingPoolPreferences userPrefs = new StartingPoolPreferences(poolType, preferredColors, includeArtifacts, view.startWithCompleteSet(), view.allowDuplicateCards(), numberOfBoosters);
String questName; String questName;
while (true) { while (true) {

View File

@@ -30,6 +30,9 @@ public class DialogChooseColors {
private final FRadioButton radBalanced = new FRadioButton("Balanced"); private final FRadioButton radBalanced = new FRadioButton("Balanced");
private final FRadioButton radRandom = new FRadioButton("Random"); private final FRadioButton radRandom = new FRadioButton("Random");
private final FRadioButton radSurpriseMe = new FRadioButton("Surprise Me"); private final FRadioButton radSurpriseMe = new FRadioButton("Surprise Me");
private final FRadioButton radBoosters = new FRadioButton("Boosters");
private final FTextField numberOfBoostersField = new FTextField.Builder().text("0").maxLength(10).build();
private final FButton btnOk = new FButton("OK"); private final FButton btnOk = new FButton("OK");
@@ -68,16 +71,25 @@ public class DialogChooseColors {
radBalanced.setSelected(true); radBalanced.setSelected(true);
radRandom.setSelected(false); radRandom.setSelected(false);
radSurpriseMe.setSelected(false); radSurpriseMe.setSelected(false);
radBoosters.setSelected(false);
break; break;
case RANDOM: case RANDOM:
radBalanced.setSelected(false); radBalanced.setSelected(false);
radRandom.setSelected(true); radRandom.setSelected(true);
radSurpriseMe.setSelected(false); radSurpriseMe.setSelected(false);
radBoosters.setSelected(false);
break; break;
case RANDOM_BALANCED: case RANDOM_BALANCED:
radBalanced.setSelected(false); radBalanced.setSelected(false);
radRandom.setSelected(false); radRandom.setSelected(false);
radSurpriseMe.setSelected(true); radSurpriseMe.setSelected(true);
radBoosters.setSelected(false);
break;
case BOOSTERS:
radBalanced.setSelected(false);
radRandom.setSelected(false);
radSurpriseMe.setSelected(false);
radBoosters.setSelected(true);
break; break;
} }
@@ -122,6 +134,7 @@ public class DialogChooseColors {
poolTypePanel.add(radBalanced, radioConstraints); poolTypePanel.add(radBalanced, radioConstraints);
poolTypePanel.add(radRandom, radioConstraints); poolTypePanel.add(radRandom, radioConstraints);
poolTypePanel.add(radSurpriseMe, radioConstraints); poolTypePanel.add(radSurpriseMe, radioConstraints);
poolTypePanel.add(radBoosters, radioConstraints);
ActionListener radioButtonListener = new ActionListener() { ActionListener radioButtonListener = new ActionListener() {
@Override @Override
@@ -133,7 +146,8 @@ public class DialogChooseColors {
cbxRed.setEnabled(radBalanced.isSelected()); cbxRed.setEnabled(radBalanced.isSelected());
cbxWhite.setEnabled(radBalanced.isSelected()); cbxWhite.setEnabled(radBalanced.isSelected());
cbxColorless.setEnabled(radBalanced.isSelected()); cbxColorless.setEnabled(radBalanced.isSelected());
cbxArtifacts.setEnabled(!radSurpriseMe.isSelected()); cbxArtifacts.setEnabled(!radSurpriseMe.isSelected() && !radBoosters.isSelected());
numberOfBoostersField.setEnabled(radBoosters.isSelected());
} }
}; };
@@ -144,19 +158,23 @@ public class DialogChooseColors {
cbxRed.setEnabled(radBalanced.isSelected()); cbxRed.setEnabled(radBalanced.isSelected());
cbxWhite.setEnabled(radBalanced.isSelected()); cbxWhite.setEnabled(radBalanced.isSelected());
cbxColorless.setEnabled(radBalanced.isSelected()); cbxColorless.setEnabled(radBalanced.isSelected());
cbxArtifacts.setEnabled(!radSurpriseMe.isSelected()); cbxArtifacts.setEnabled(!radSurpriseMe.isSelected() && !radBoosters.isSelected());
numberOfBoostersField.setEnabled(radBoosters.isSelected());
radBalanced.setToolTipText("A balanced distribution will provide a roughly equal number of cards in each selected color."); radBalanced.setToolTipText("A balanced distribution will provide a roughly equal number of cards in each selected color.");
radRandom.setToolTipText("A random distribution will be almost entirely randomly selected. This ignores any color selections."); radRandom.setToolTipText("A random distribution will be almost entirely randomly selected. This ignores any color selections.");
radSurpriseMe.setToolTipText("This is the same as a balanced distribution, except the colors picked will be random and you will not be told what they are."); radSurpriseMe.setToolTipText("This is the same as a balanced distribution, except the colors picked will be random and you will not be told what they are.");
radBoosters.setToolTipText("This ignores all color settings and instead generates a card pool out of a specified number of booster packs.");
cbxArtifacts.setToolTipText("When selected, artifacts will be included in your pool regardless of color selections. This mimics the old card pool behavior."); cbxArtifacts.setToolTipText("When selected, artifacts will be included in your pool regardless of color selections. This mimics the old card pool behavior.");
radBalanced.addActionListener(radioButtonListener); radBalanced.addActionListener(radioButtonListener);
radRandom.addActionListener(radioButtonListener); radRandom.addActionListener(radioButtonListener);
radSurpriseMe.addActionListener(radioButtonListener); radSurpriseMe.addActionListener(radioButtonListener);
radBoosters.addActionListener(radioButtonListener);
left.add(poolTypePanel, "gaptop 15"); left.add(poolTypePanel, "gaptop 15");
left.add(cbxArtifacts, "gaptop 25"); left.add(cbxArtifacts, "gaptop 25");
left.add(numberOfBoostersField, "w 100px!, gaptop 15");
//Add Bottom and Panels //Add Bottom and Panels
mainPanel.add(left); mainPanel.add(left);
@@ -234,6 +252,8 @@ public class DialogChooseColors {
return PoolType.RANDOM; return PoolType.RANDOM;
} else if (radSurpriseMe.isSelected()) { } else if (radSurpriseMe.isSelected()) {
return PoolType.RANDOM_BALANCED; return PoolType.RANDOM_BALANCED;
} else if (radBoosters.isSelected()) {
return PoolType.BOOSTERS;
} }
return PoolType.BALANCED; return PoolType.BALANCED;
@@ -244,4 +264,12 @@ public class DialogChooseColors {
return cbxArtifacts.isSelected(); return cbxArtifacts.isSelected();
} }
public int getNumberOfBoosters() {
try {
return Integer.valueOf(numberOfBoostersField.getText());
} catch (NumberFormatException e) {
return 0;
}
}
} }

View File

@@ -1,12 +1,10 @@
package forge.toolbox; package forge.toolbox;
import java.util.Date;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import forge.interfaces.IProgressBar; import forge.interfaces.IProgressBar;
import javax.swing.*;
import java.util.Date;
/** /**
* A simple progress bar component using the Forge skin. * A simple progress bar component using the Forge skin.
*/ */
@@ -47,8 +45,8 @@ public class FProgressBar extends JProgressBar implements IProgressBar {
}; };
@Override @Override
public void setValue(final int value0) { public void setValue(final int progress) {
super.setValue(value0); super.setValue(progress);
// String.format leads to StringBuilder anyway. Direct calls will be faster // String.format leads to StringBuilder anyway. Direct calls will be faster
final StringBuilder sb = new StringBuilder(desc); final StringBuilder sb = new StringBuilder(desc);
@@ -56,15 +54,15 @@ public class FProgressBar extends JProgressBar implements IProgressBar {
sb.append(" "); sb.append(" ");
final int maximum = getMaximum(); final int maximum = getMaximum();
if (percentMode) { if (percentMode) {
sb.append(100 * value0 / maximum).append("%"); sb.append(100 * progress / maximum).append("%");
} }
else { else {
sb.append(value0).append(" of ").append(maximum); sb.append(progress).append(" of ").append(maximum);
} }
} }
if (showETA) { if (showETA) {
calculateETA(value0); calculateETA(progress);
sb.append(", ETA").append(String.format("%02d:%02d:%02d", etaSecs / 3600, (etaSecs % 3600) / 60, etaSecs % 60 + 1)); sb.append(", ETA").append(String.format("%02d:%02d:%02d", etaSecs / 3600, (etaSecs % 3600) / 60, etaSecs % 60 + 1));
} }
setString(sb.toString()); setString(sb.toString());

View File

@@ -605,7 +605,7 @@ public class NewQuestScreen extends FScreen {
public void run() { public void run() {
final QuestMode mode = isFantasy() ? QuestMode.Fantasy : QuestMode.Classic; final QuestMode mode = isFantasy() ? QuestMode.Fantasy : QuestMode.Classic;
final StartingPoolPreferences userPrefs = final StartingPoolPreferences userPrefs =
new StartingPoolPreferences(getPoolType(), getPreferredColors(), cbIncludeArtifacts.isSelected(), startWithCompleteSet(), allowDuplicateCards()); new StartingPoolPreferences(getPoolType(), getPreferredColors(), cbIncludeArtifacts.isSelected(), startWithCompleteSet(), allowDuplicateCards(), 0);
QuestController qc = FModel.getQuest(); QuestController qc = FModel.getQuest();
qc.newGame(questName, getSelectedDifficulty(), mode, fmtPrizes, isUnlockSetsAllowed(), dckStartPool, fmtStartPool, getStartingWorldName(), userPrefs); qc.newGame(questName, getSelectedDifficulty(), mode, fmtPrizes, isUnlockSetsAllowed(), dckStartPool, fmtStartPool, getStartingWorldName(), userPrefs);
qc.save(); qc.save();

View File

@@ -1,18 +1,16 @@
package forge.toolbox; package forge.toolbox;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment; import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
import forge.Graphics; import forge.Graphics;
import forge.assets.FSkinFont; import forge.assets.FSkinFont;
import forge.interfaces.IProgressBar; import forge.interfaces.IProgressBar;
import forge.util.Utils; import forge.util.Utils;
import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class FProgressBar extends FDisplayObject implements IProgressBar { public class FProgressBar extends FDisplayObject implements IProgressBar {
public static Color BACK_COLOR, FORE_COLOR, SEL_BACK_COLOR, SEL_FORE_COLOR; public static Color BACK_COLOR, FORE_COLOR, SEL_BACK_COLOR, SEL_FORE_COLOR;
@@ -47,8 +45,8 @@ public class FProgressBar extends FDisplayObject implements IProgressBar {
} }
/** Increments bar. */ /** Increments bar. */
public void setValue(int value0) { public void setValue(int progress) {
value = value0; value = progress;
setShowProgressTrail(false); //can't show progress trail if value set setShowProgressTrail(false); //can't show progress trail if value set
// String.format leads to StringBuilder anyway. Direct calls will be faster // String.format leads to StringBuilder anyway. Direct calls will be faster

View File

@@ -19,3 +19,9 @@ This release contains a new way to generate random Standard or Modern decks that
- User created quest worlds - - User created quest worlds -
If you have created some of your own quest worlds and don't want them to be overwritten when Forge updates, you can move the world folders to the user quest folder (in USER_FOLDER/quest/worlds) - you will also need to add the world definitions to a customworlds.txt file in that same folder If you have created some of your own quest worlds and don't want them to be overwritten when Forge updates, you can move the world folders to the user quest folder (in USER_FOLDER/quest/worlds) - you will also need to add the world definitions to a customworlds.txt file in that same folder
- Quest Shop Singles Update -
The quest shop will now generate singles using the full availability of cards in a set, including things like Amonkhet Invocations and Kaladesh Inventions. The rarity of these additional cards is unchanged and it may take some time for them to finally appear.
- Booster Pack Quest Starting Pool -
Quests can now use booster packs as a starting pool. A number of random packs will be opened and used instead of the normal card generation. You can find this option in the "Choose Colors" section when creating a new quest. This will override any other starting pool settings.

View File

@@ -2,7 +2,7 @@ package forge.interfaces;
public interface IProgressBar { public interface IProgressBar {
void setDescription(String s0); void setDescription(String s0);
void setValue(int value0); void setValue(int progress);
void reset(); void reset();
void setShowETA(boolean b0); void setShowETA(boolean b0);
void setShowCount(boolean b0); void setShowCount(boolean b0);

View File

@@ -21,11 +21,8 @@ import com.google.common.base.Predicate;
import com.google.common.base.Predicates; 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.card.*;
import forge.card.CardRules; import forge.game.GameFormat;
import forge.card.CardRulesPredicates;
import forge.card.MagicColor;
import forge.card.PrintSheet;
import forge.item.*; import forge.item.*;
import forge.item.IPaperCard.Predicates.Presets; import forge.item.IPaperCard.Predicates.Presets;
import forge.model.FModel; import forge.model.FModel;
@@ -33,7 +30,6 @@ import forge.quest.data.QuestPreferences.QPref;
import forge.util.Aggregates; import forge.util.Aggregates;
import forge.util.MyRandom; import forge.util.MyRandom;
import forge.util.PredicateString.StringOp; import forge.util.PredicateString.StringOp;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
@@ -41,6 +37,8 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import static forge.quest.QuestUtilCards.isLegalInQuestFormat;
/** /**
* <p> * <p>
* QuestBoosterPack class. Generates cards for the Card Pool in Quest Mode * QuestBoosterPack class. Generates cards for the Card Pool in Quest Mode
@@ -60,6 +58,22 @@ public final class BoosterUtils {
1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6
}; };
private static final GameFormat.Collection formats = FModel.getFormats();
private static final Predicate<CardEdition> filterExt = formats.getExtended().editionLegalPredicate;
/** The filter t2booster. */
private static final Predicate<CardEdition> filterT2booster = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER,
formats.getStandard().editionLegalPredicate);
/** The filter ext but t2. */
private static final Predicate<CardEdition> filterExtButT2 = Predicates.and(
CardEdition.Predicates.CAN_MAKE_BOOSTER,
Predicates.and(filterExt, formats.getStandard().editionLegalPredicate));
/** The filter not ext. */
private static final Predicate<CardEdition> filterNotExt = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER,
Predicates.not(filterExt));
/** /**
* Gets the quest starter deck. * Gets the quest starter deck.
* *
@@ -76,7 +90,7 @@ public final class BoosterUtils {
* @return the quest starter deck * @return the quest starter deck
*/ */
public static List<PaperCard> getQuestStarterDeck(final Predicate<PaperCard> filter, final int numCommons, public static List<PaperCard> getQuestStarterDeck(final Predicate<PaperCard> filter, final int numCommons,
final int numUncommons, final int numRares, final StartingPoolPreferences userPrefs) { final int numUncommons, final int numRares, final StartingPoolPreferences userPrefs, final QuestController questController) {
if (possibleColors.isEmpty()) { if (possibleColors.isEmpty()) {
possibleColors.add(MagicColor.BLACK); possibleColors.add(MagicColor.BLACK);
@@ -90,6 +104,16 @@ public final class BoosterUtils {
final List<PaperCard> cardPool = Lists.newArrayList(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), filter)); final List<PaperCard> cardPool = Lists.newArrayList(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), filter));
final List<PaperCard> cards = new ArrayList<>(); final List<PaperCard> cards = new ArrayList<>();
if (userPrefs != null && userPrefs.getPoolType() == StartingPoolPreferences.PoolType.BOOSTERS) {
for (InventoryItem inventoryItem : generateRandomBoosterPacks(userPrefs.getNumberOfBoosters(), questController)) {
cards.addAll(((BoosterPack) inventoryItem).getCards());
}
return cards;
}
if (userPrefs != null && userPrefs.grantCompleteSet()) { if (userPrefs != null && userPrefs.grantCompleteSet()) {
for (PaperCard card : cardPool) { for (PaperCard card : cardPool) {
cards.add(card); cards.add(card);
@@ -119,6 +143,44 @@ public final class BoosterUtils {
} }
/**
* Generates a number of booster packs from random editions using the current quest's prize pool format.
* @param quantity The number of booster packs to generate
* @return A list containing the booster packs
*/
public static List<InventoryItem> generateRandomBoosterPacks(final int quantity, final QuestController questController) {
List<InventoryItem> output = new ArrayList<>();
for (int i = 0; i < quantity; i++) {
final int rollD100 = MyRandom.getRandom().nextInt(100);
Predicate<CardEdition> filter = rollD100 < 40 ? filterT2booster : (rollD100 < 75 ? filterExtButT2 : filterNotExt);
if (questController.getFormat() != null) {
filter = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER, isLegalInQuestFormat(questController.getFormat()));
}
Iterable<CardEdition> rightEditions = Iterables.filter(FModel.getMagicDb().getEditions(), filter);
if (!rightEditions.iterator().hasNext()) {
continue;
}
CardEdition edition = Aggregates.random(rightEditions);
BoosterPack pack = BoosterPack.FN_FROM_SET.apply(edition);
if (pack != null) {
output.add(pack);
} else {
System.err.println("Could not create booster of edition: " + edition);
}
}
return output;
}
private static List<Predicate<CardRules>> getColorFilters(final StartingPoolPreferences userPrefs, final List<PaperCard> cardPool) { private static List<Predicate<CardRules>> getColorFilters(final StartingPoolPreferences userPrefs, final List<PaperCard> cardPool) {
final List<Predicate<CardRules>> colorFilters = new ArrayList<>(); final List<Predicate<CardRules>> colorFilters = new ArrayList<>();

View File

@@ -17,19 +17,10 @@
*/ */
package forge.quest; package forge.quest;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
import forge.card.CardEdition; import forge.card.CardEdition;
import forge.deck.Deck; import forge.deck.Deck;
import forge.deck.DeckGroup; import forge.deck.DeckGroup;
@@ -54,6 +45,9 @@ import forge.quest.io.QuestChallengeReader;
import forge.util.storage.IStorage; import forge.util.storage.IStorage;
import forge.util.storage.StorageBase; import forge.util.storage.StorageBase;
import java.io.File;
import java.util.*;
/** /**
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
* *
@@ -284,7 +278,7 @@ public class QuestController {
if (formatStartingPool != null) { if (formatStartingPool != null) {
filter = formatStartingPool.getFilterPrinted(); filter = formatStartingPool.getFilterPrinted();
} }
this.myCards.setupNewGameCardPool(filter, difficulty, userPrefs); this.myCards.setupNewGameCardPool(filter, difficulty, userPrefs, this);
} }
this.getAssets().setCredits(FModel.getQuestPreferences().getPrefInt(DifficultyPrefs.STARTING_CREDITS, difficulty)); this.getAssets().setCredits(FModel.getQuestPreferences().getPrefInt(DifficultyPrefs.STARTING_CREDITS, difficulty));

View File

@@ -282,9 +282,12 @@ public class QuestSpellShop {
} }
public static void sell(Iterable<Entry<InventoryItem, Integer>> items, IItemManager<InventoryItem> shopManager, IItemManager<InventoryItem> inventoryManager, boolean confirmSale) { public static void sell(Iterable<Entry<InventoryItem, Integer>> items, IItemManager<InventoryItem> shopManager, IItemManager<InventoryItem> inventoryManager, boolean confirmSale) {
long totalReceived = 0; long totalReceived = 0;
int sellPriceLimit = FModel.getQuest().getCards().getSellPriceLimit(); int sellPriceLimit = FModel.getQuest().getCards().getSellPriceLimit();
ItemPool<InventoryItem> itemsToSell = new ItemPool<>(InventoryItem.class); ItemPool<InventoryItem> itemsToSell = new ItemPool<>(InventoryItem.class);
for (Entry<InventoryItem, Integer> itemEntry : items) { for (Entry<InventoryItem, Integer> itemEntry : items) {
final InventoryItem item = itemEntry.getKey(); final InventoryItem item = itemEntry.getKey();
if (item instanceof PaperCard) { if (item instanceof PaperCard) {
@@ -293,7 +296,10 @@ public class QuestSpellShop {
totalReceived += qty * Math.min((int) (multiplier * getCardValue(item)), sellPriceLimit); totalReceived += qty * Math.min((int) (multiplier * getCardValue(item)), sellPriceLimit);
} }
} }
if (itemsToSell.isEmpty()) { return; }
if (itemsToSell.isEmpty()) {
return;
}
if (confirmSale) { if (confirmSale) {
List<InventoryItem> itemFlatList = itemsToSell.toFlatList(); List<InventoryItem> itemFlatList = itemsToSell.toFlatList();
@@ -308,24 +314,27 @@ public class QuestSpellShop {
} }
for (Entry<InventoryItem, Integer> itemEntry : itemsToSell) { for (Entry<InventoryItem, Integer> itemEntry : itemsToSell) {
final PaperCard card = (PaperCard) itemEntry.getKey();
final int qty = itemEntry.getValue();
final int price = Math.min((int) (multiplier * getCardValue(card)), FModel.getQuest().getCards().getSellPriceLimit());
FModel.getQuest().getCards().sellCard(card, qty, price); final PaperCard card = (PaperCard) itemEntry.getKey();
final int pricePerCard = Math.min((int) (multiplier * getCardValue(card)), FModel.getQuest().getCards().getSellPriceLimit());
sellCard(card, itemEntry.getValue(), pricePerCard);
} }
inventoryManager.removeItems(itemsToSell); inventoryManager.removeItems(itemsToSell);
shopManager.addItems(itemsToSell); shopManager.addItems(itemsToSell);
} }
public static void sellExtras(IItemManager<InventoryItem> shopManager, IItemManager<InventoryItem> inventoryManager) { public static void sellExtras(IItemManager<InventoryItem> shopManager, IItemManager<InventoryItem> inventoryManager) {
List<Entry<InventoryItem, Integer>> cardsToRemove = new LinkedList<>(); List<Entry<InventoryItem, Integer>> cardsToRemove = new LinkedList<>();
for (Entry<InventoryItem, Integer> item : inventoryManager.getPool()) { for (Entry<InventoryItem, Integer> item : inventoryManager.getPool()) {
PaperCard card = (PaperCard)item.getKey(); PaperCard card = (PaperCard)item.getKey();
int numToKeep = card.getRules().getType().isBasic() ? int numToKeep = card.getRules().getType().isBasic() ?
FModel.getQuestPreferences().getPrefInt(QPref.PLAYSET_BASIC_LAND_SIZE) : FModel.getQuestPreferences().getPrefInt(QPref.PLAYSET_SIZE); FModel.getQuestPreferences().getPrefInt(QPref.PLAYSET_BASIC_LAND_SIZE) : FModel.getQuestPreferences().getPrefInt(QPref.PLAYSET_SIZE);
if ("Relentless Rats".equals(card.getName()) || "Shadowborn Apostle".equals(card.getName())) { if (card.getName().equals("Relentless Rats") || card.getName().equals("Shadowborn Apostle")) {
numToKeep = FModel.getQuestPreferences().getPrefInt(QPref.PLAYSET_ANY_NUMBER_SIZE); numToKeep = FModel.getQuestPreferences().getPrefInt(QPref.PLAYSET_ANY_NUMBER_SIZE);
} }
if (numToKeep < item.getValue()) { if (numToKeep < item.getValue()) {
@@ -337,14 +346,23 @@ public class QuestSpellShop {
shopManager.addItems(cardsToRemove); shopManager.addItems(cardsToRemove);
for (Entry<InventoryItem, Integer> item : cardsToRemove) { for (Entry<InventoryItem, Integer> item : cardsToRemove) {
if (!(item.getKey() instanceof PaperCard)) { if (!(item.getKey() instanceof PaperCard)) {
continue; continue;
} }
PaperCard card = (PaperCard)item.getKey(); PaperCard card = (PaperCard)item.getKey();
final int price = Math.min((int) (multiplier * getCardValue(card)), final int pricePerCard = Math.min((int) (multiplier * getCardValue(card)), FModel.getQuest().getCards().getSellPriceLimit());
FModel.getQuest().getCards().getSellPriceLimit());
FModel.getQuest().getCards().sellCard(card, item.getValue(), price); sellCard(card, item.getValue(), pricePerCard);
} }
}
private static void sellCard(final PaperCard card, final int quantity, final int pricePerCard) {
FModel.getQuest().getCards().removeCard(card, quantity);
FModel.getQuest().getAssets().addCredits(pricePerCard * quantity);
} }
// fills number of decks using each card // fills number of decks using each card

View File

@@ -42,9 +42,7 @@ import forge.util.ItemPool;
import forge.util.MyRandom; import forge.util.MyRandom;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
/** /**
@@ -52,20 +50,21 @@ import java.util.Map.Entry;
* created to decrease complexity of questData class * created to decrease complexity of questData class
*/ */
public final class QuestUtilCards { public final class QuestUtilCards {
private final QuestController qc;
private final QuestPreferences qpref;
private final QuestAssets qa;
/** private static final Predicate<PaperCard> COMMON_PREDICATE = IPaperCard.Predicates.Presets.IS_COMMON;
* Instantiates a new quest util cards. private static final Predicate<PaperCard> UNCOMMON_PREDICATE = IPaperCard.Predicates.Presets.IS_UNCOMMON;
* private static final Predicate<PaperCard> RARE_PREDICATE = IPaperCard.Predicates.Presets.IS_RARE_OR_MYTHIC;
* @param qd private static final Predicate<PaperCard> ONLY_RARE_PREDICATE = IPaperCard.Predicates.Presets.IS_RARE;
* the qd private static final Predicate<PaperCard> MYTHIC_PREDICATE = IPaperCard.Predicates.Presets.IS_MYTHIC_RARE;
*/
public QuestUtilCards(final QuestController qd) { private final QuestController questController;
this.qc = qd; private final QuestPreferences questPreferences;
this.qa = qc.getAssets(); private final QuestAssets questAssets;
this.qpref = FModel.getQuestPreferences();
public QuestUtilCards(final QuestController questController) {
this.questController = questController;
questAssets = questController.getAssets();
questPreferences = FModel.getQuestPreferences();
} }
/** /**
@@ -77,6 +76,7 @@ public final class QuestUtilCards {
* @return the item pool view * @return the item pool view
*/ */
public static ItemPool<PaperCard> generateBasicLands(final int nBasic, final int nSnow, final GameFormatQuest usedFormat) { public static ItemPool<PaperCard> generateBasicLands(final int nBasic, final int nSnow, final GameFormatQuest usedFormat) {
final ICardDatabase db = FModel.getMagicDb().getCommonCards(); final ICardDatabase db = FModel.getMagicDb().getCommonCards();
final ItemPool<PaperCard> pool = new ItemPool<>(PaperCard.class); final ItemPool<PaperCard> pool = new ItemPool<>(PaperCard.class);
@@ -150,6 +150,7 @@ public final class QuestUtilCards {
} }
return pool; return pool;
} }
/** /**
@@ -162,8 +163,7 @@ public final class QuestUtilCards {
* @return the array list * @return the array list
*/ */
public List<PaperCard> generateQuestBooster(final Predicate<PaperCard> fSets) { public List<PaperCard> generateQuestBooster(final Predicate<PaperCard> fSets) {
UnOpenedProduct unopened = new UnOpenedProduct(getBoosterTemplate(), fSets); return new UnOpenedProduct(getBoosterTemplate(), fSets).get();
return unopened.get();
} }
/** /**
@@ -174,7 +174,7 @@ public final class QuestUtilCards {
*/ */
public void addAllCards(final Iterable<PaperCard> newCards) { public void addAllCards(final Iterable<PaperCard> newCards) {
for (final PaperCard card : newCards) { for (final PaperCard card : newCards) {
this.addSingleCard(card, 1); addSingleCard(card, 1);
} }
} }
@@ -187,19 +187,12 @@ public final class QuestUtilCards {
* quantity * quantity
*/ */
public void addSingleCard(final PaperCard card, int qty) { public void addSingleCard(final PaperCard card, int qty) {
this.qa.getCardPool().add(card, qty); questAssets.getCardPool().add(card, qty);
// register card into that list so that it would appear as a new one. // register card into that list so that it would appear as a new one.
this.qa.getNewCardList().add(card, qty); questAssets.getNewCardList().add(card, qty);
} }
private static final Predicate<PaperCard> COMMON_PREDICATE = IPaperCard.Predicates.Presets.IS_COMMON;
private static final Predicate<PaperCard> UNCOMMON_PREDICATE = IPaperCard.Predicates.Presets.IS_UNCOMMON;
private static final Predicate<PaperCard> RARE_PREDICATE = IPaperCard.Predicates.Presets.IS_RARE_OR_MYTHIC;
private static final Predicate<PaperCard> ONLY_RARE_PREDICATE = IPaperCard.Predicates.Presets.IS_RARE;
private static final Predicate<PaperCard> MYTHIC_PREDICATE = IPaperCard.Predicates.Presets.IS_MYTHIC_RARE;
/** /**
* A predicate that takes into account the Quest Format (if any). * A predicate that takes into account the Quest Format (if any).
* @param source * @param source
@@ -207,7 +200,7 @@ public final class QuestUtilCards {
* @return the composite predicate. * @return the composite predicate.
*/ */
public Predicate<PaperCard> applyFormatFilter(Predicate<PaperCard> source) { public Predicate<PaperCard> applyFormatFilter(Predicate<PaperCard> source) {
return qc.getFormat() == null ? source : Predicates.and(source, qc.getFormat().getFilterPrinted()); return questController.getFormat() == null ? source : Predicates.and(source, questController.getFormat().getFilterPrinted());
} }
/** /**
@@ -220,7 +213,7 @@ public final class QuestUtilCards {
final Predicate<PaperCard> myFilter = applyFormatFilter(QuestUtilCards.RARE_PREDICATE); final Predicate<PaperCard> myFilter = applyFormatFilter(QuestUtilCards.RARE_PREDICATE);
final PaperCard card = Aggregates.random(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), myFilter)); final PaperCard card = Aggregates.random(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), myFilter));
this.addSingleCard(card, 1); addSingleCard(card, 1);
return card; return card;
} }
@@ -233,7 +226,7 @@ public final class QuestUtilCards {
public List<PaperCard> addRandomCommon(final int n) { public List<PaperCard> addRandomCommon(final int n) {
final Predicate<PaperCard> myFilter = applyFormatFilter(QuestUtilCards.COMMON_PREDICATE); final Predicate<PaperCard> myFilter = applyFormatFilter(QuestUtilCards.COMMON_PREDICATE);
final List<PaperCard> newCards = Aggregates.random(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), myFilter), n); final List<PaperCard> newCards = Aggregates.random(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), myFilter), n);
this.addAllCards(newCards); addAllCards(newCards);
return newCards; return newCards;
} }
@@ -246,7 +239,7 @@ public final class QuestUtilCards {
public List<PaperCard> addRandomUncommon(final int n) { public List<PaperCard> addRandomUncommon(final int n) {
final Predicate<PaperCard> myFilter = applyFormatFilter(QuestUtilCards.UNCOMMON_PREDICATE); final Predicate<PaperCard> myFilter = applyFormatFilter(QuestUtilCards.UNCOMMON_PREDICATE);
final List<PaperCard> newCards = Aggregates.random(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), myFilter), n); final List<PaperCard> newCards = Aggregates.random(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), myFilter), n);
this.addAllCards(newCards); addAllCards(newCards);
return newCards; return newCards;
} }
@@ -261,7 +254,7 @@ public final class QuestUtilCards {
final Predicate<PaperCard> myFilter = applyFormatFilter(QuestUtilCards.RARE_PREDICATE); final Predicate<PaperCard> myFilter = applyFormatFilter(QuestUtilCards.RARE_PREDICATE);
final List<PaperCard> newCards = Aggregates.random(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), myFilter), n); final List<PaperCard> newCards = Aggregates.random(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), myFilter), n);
this.addAllCards(newCards); addAllCards(newCards);
return newCards; return newCards;
} }
@@ -276,7 +269,7 @@ public final class QuestUtilCards {
final Predicate<PaperCard> myFilter = applyFormatFilter(QuestUtilCards.ONLY_RARE_PREDICATE); final Predicate<PaperCard> myFilter = applyFormatFilter(QuestUtilCards.ONLY_RARE_PREDICATE);
final List<PaperCard> newCards = Aggregates.random(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), myFilter), n); final List<PaperCard> newCards = Aggregates.random(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), myFilter), n);
this.addAllCards(newCards); addAllCards(newCards);
return newCards; return newCards;
} }
@@ -297,7 +290,7 @@ public final class QuestUtilCards {
} }
final List<PaperCard> newCards = Aggregates.random(cardPool, n); final List<PaperCard> newCards = Aggregates.random(cardPool, n);
this.addAllCards(newCards); addAllCards(newCards);
return newCards; return newCards;
} }
@@ -312,12 +305,14 @@ public final class QuestUtilCards {
* @param userPrefs * @param userPrefs
* user preferences * user preferences
*/ */
public void setupNewGameCardPool(final Predicate<PaperCard> filter, final int idxDifficulty, final StartingPoolPreferences userPrefs) { public void setupNewGameCardPool(final Predicate<PaperCard> filter, final int idxDifficulty, final StartingPoolPreferences userPrefs, final QuestController questController) {
final int nC = this.qpref.getPrefInt(DifficultyPrefs.STARTING_COMMONS, idxDifficulty);
final int nU = this.qpref.getPrefInt(DifficultyPrefs.STARTING_UNCOMMONS, idxDifficulty); final int nC = questPreferences.getPrefInt(DifficultyPrefs.STARTING_COMMONS, idxDifficulty);
final int nR = this.qpref.getPrefInt(DifficultyPrefs.STARTING_RARES, idxDifficulty); final int nU = questPreferences.getPrefInt(DifficultyPrefs.STARTING_UNCOMMONS, idxDifficulty);
final int nR = questPreferences.getPrefInt(DifficultyPrefs.STARTING_RARES, idxDifficulty);
addAllCards(BoosterUtils.getQuestStarterDeck(filter, nC, nU, nR, userPrefs, questController));
this.addAllCards(BoosterUtils.getQuestStarterDeck(filter, nC, nU, nR, userPrefs));
} }
/** /**
@@ -332,9 +327,9 @@ public final class QuestUtilCards {
*/ */
public void buyCard(final PaperCard card, int qty, final int value) { public void buyCard(final PaperCard card, int qty, final int value) {
int totalCost = qty * value; int totalCost = qty * value;
if (this.qa.getCredits() >= totalCost) { if (questAssets.getCredits() >= totalCost) {
this.qa.setCredits(this.qa.getCredits() - totalCost); questAssets.setCredits(questAssets.getCredits() - totalCost);
this.addSingleCard(card, qty); addSingleCard(card, qty);
} }
} }
@@ -347,9 +342,9 @@ public final class QuestUtilCards {
* the value * the value
*/ */
public void buyPack(final SealedProduct booster, final int value) { public void buyPack(final SealedProduct booster, final int value) {
if (this.qa.getCredits() >= value) { if (questAssets.getCredits() >= value) {
this.qa.setCredits(this.qa.getCredits() - value); questAssets.setCredits(questAssets.getCredits() - value);
this.addAllCards(booster.getCards()); addAllCards(booster.getCards());
} }
} }
@@ -362,9 +357,9 @@ public final class QuestUtilCards {
* the value * the value
*/ */
public void buyPreconDeck(final PreconDeck precon, final int value) { public void buyPreconDeck(final PreconDeck precon, final int value) {
if (this.qa.getCredits() >= value) { if (questAssets.getCredits() >= value) {
this.qa.setCredits(this.qa.getCredits() - value); questAssets.subtractCredits(value);
this.addDeck(precon.getDeck()); addDeck(precon.getDeck());
} }
} }
@@ -378,59 +373,53 @@ public final class QuestUtilCards {
if (fromDeck == null) { if (fromDeck == null) {
return; return;
} }
this.qc.getMyDecks().add(fromDeck); questController.getMyDecks().add(fromDeck);
this.addAllCards(fromDeck.getMain().toFlatList()); addAllCards(fromDeck.getMain().toFlatList());
if (fromDeck.has(DeckSection.Sideboard)) { if (fromDeck.has(DeckSection.Sideboard)) {
this.addAllCards(fromDeck.get(DeckSection.Sideboard).toFlatList()); addAllCards(fromDeck.get(DeckSection.Sideboard).toFlatList());
} }
} }
/** /**
* Sell card. * Removes the list of cards from the card pool and returns them to the card shop if Cash Stakes are owned.
* * @param cards The cards to lose.
* @param card
* the card
* @param qty
* quantity
* @param pricePerCard
* the price per card
*/
public void sellCard(final PaperCard card, int qty, final int pricePerCard) {
this.sellCard(card, qty, pricePerCard, true);
}
/**
* Lose card.
* @param cards The cards to lose
*/ */
public void loseCards(final List<PaperCard> cards) { public void loseCards(final List<PaperCard> cards) {
for(PaperCard pc: cards)
this.sellCard(pc, 1, 0, this.qc.getAssets().getItemLevel(QuestItemType.CASH_STAKES) > 0); for(PaperCard card : cards) {
removeCard(card, 1);
if (questAssets.getItemLevel(QuestItemType.CASH_STAKES) > 0) {
addCardToShop(card);
}
}
}
public void addCardToShop(final PaperCard card) {
questAssets.getShopList().add(card);
} }
/** /**
* Sell card. * This removes a card from the quest pool and any decks that use it.
* @param card The card to sell. * @param card The card to remove.
* @param qty The quantity of the card to sell. * @param qty The quantity of the card to remove.
* @param pricePerCard The price of each card.
* @param addToShop If true, this adds the sold cards to the shop's inventory.
*/ */
private void sellCard(final PaperCard card, int qty, final int pricePerCard, final boolean addToShop) { public void removeCard(final PaperCard card, int qty) {
if (pricePerCard > 0) {
this.qa.setCredits(this.qa.getCredits() + (qty * pricePerCard)); questAssets.getCardPool().remove(card, qty);
}
this.qa.getCardPool().remove(card, qty); final int leftInPool = questAssets.getCardPool().count(card);
if (addToShop) {
this.qa.getShopList().add(card, qty);
}
// remove card being sold from all decks
final int leftInPool = this.qa.getCardPool().count(card);
// remove sold cards from all decks: // remove sold cards from all decks:
for (final Deck deck : this.qc.getMyDecks()) { for (final Deck deck : questController.getMyDecks()) {
int cntInMain = deck.getMain().count(card); int cntInMain = deck.getMain().count(card);
int cntInSb = deck.has(DeckSection.Sideboard) ? deck.get(DeckSection.Sideboard).count(card) : 0; int cntInSb = deck.has(DeckSection.Sideboard) ? deck.get(DeckSection.Sideboard).count(card) : 0;
int nToRemoveFromThisDeck = cntInMain + cntInSb - leftInPool; int nToRemoveFromThisDeck = cntInMain + cntInSb - leftInPool;
if (nToRemoveFromThisDeck <= 0) { if (nToRemoveFromThisDeck <= 0) {
continue; // this is not the deck you are looking for continue; // this is not the deck you are looking for
} }
@@ -439,21 +428,23 @@ public final class QuestUtilCards {
if (nToRemoveFromSb > 0) { if (nToRemoveFromSb > 0) {
deck.get(DeckSection.Sideboard).remove(card, nToRemoveFromSb); deck.get(DeckSection.Sideboard).remove(card, nToRemoveFromSb);
nToRemoveFromThisDeck -= nToRemoveFromSb; nToRemoveFromThisDeck -= nToRemoveFromSb;
if (0 >= nToRemoveFromThisDeck) { if (nToRemoveFromThisDeck <= 0) {
continue; // done here continue; // done here
} }
} }
deck.getMain().remove(card, nToRemoveFromThisDeck); deck.getMain().remove(card, nToRemoveFromThisDeck);
} }
} }
/** /**
* Clear shop list. * Clear shop list.
*/ */
public void clearShopList() { public void clearShopList() {
if (null != this.qa.getShopList()) { if (questAssets.getShopList() != null) {
this.qa.getShopList().clear(); questAssets.getShopList().clear();
} }
} }
@@ -463,31 +454,33 @@ public final class QuestUtilCards {
* @return the sell mutliplier * @return the sell mutliplier
*/ */
public double getSellMultiplier() { public double getSellMultiplier() {
double baseMultiplier = Double.parseDouble(this.qpref.getPref(QPref.SHOP_SELLING_PERCENTAGE_BASE))/100.0;
double maxMultiplier = Double.parseDouble(this.qpref.getPref(QPref.SHOP_SELLING_PERCENTAGE_MAX))/100.0;
double baseMultiplier = Double.parseDouble(questPreferences.getPref(QPref.SHOP_SELLING_PERCENTAGE_BASE))/100.0;
double maxMultiplier = Double.parseDouble(questPreferences.getPref(QPref.SHOP_SELLING_PERCENTAGE_MAX))/100.0;
double multi = baseMultiplier + (0.001 * this.qc.getAchievements().getWin()); double multi = baseMultiplier + (0.001 * questController.getAchievements().getWin());
if (maxMultiplier > 0 && multi > maxMultiplier) { if (maxMultiplier > 0 && multi > maxMultiplier) {
multi = maxMultiplier; multi = maxMultiplier;
} }
final int lvlEstates = this.qc.getMode() == QuestMode.Fantasy ? this.qa.getItemLevel(QuestItemType.ESTATES) : 0; final int lvlEstates = questController.getMode() == QuestMode.Fantasy ? questAssets.getItemLevel(QuestItemType.ESTATES) : 0;
switch (lvlEstates) { switch (lvlEstates) {
case 1: case 1:
multi += 0.01; multi += 0.01;
break; break;
case 2: case 2:
multi += 0.0175; multi += 0.0175;
break; break;
case 3: case 3:
multi += 0.025; multi += 0.025;
break; break;
default: default:
break; break;
} }
return multi; return multi;
} }
/** /**
@@ -496,30 +489,28 @@ public final class QuestUtilCards {
* @return the sell price limit * @return the sell price limit
*/ */
public int getSellPriceLimit() { public int getSellPriceLimit() {
int winsNoLimit = FModel.getQuestPreferences().getPrefInt(QPref.SHOP_WINS_FOR_NO_SELL_LIMIT); int winsNoLimit = questPreferences.getPrefInt(QPref.SHOP_WINS_FOR_NO_SELL_LIMIT);
int maxPrice = FModel.getQuestPreferences().getPrefInt(QPref.SHOP_MAX_SELLING_PRICE); int maxPrice = questPreferences.getPrefInt(QPref.SHOP_MAX_SELLING_PRICE);
return this.qc.getAchievements().getWin() < winsNoLimit ? maxPrice : Integer.MAX_VALUE; return questController.getAchievements().getWin() < winsNoLimit ? maxPrice : Integer.MAX_VALUE;
} }
/** /**
* Generate cards in shop. * Generate cards in shop.
*/ */
private final GameFormat.Collection formats = FModel.getFormats(); private final GameFormat.Collection formats = FModel.getFormats();
private final Predicate<CardEdition> filterExt = this.formats.getExtended().editionLegalPredicate; private final Predicate<CardEdition> filterExt = formats.getExtended().editionLegalPredicate;
/** The filter t2booster. */ /** The filter t2booster. */
private final Predicate<CardEdition> filterT2booster = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER, private final Predicate<CardEdition> filterT2booster = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER, formats.getStandard().editionLegalPredicate);
this.formats.getStandard().editionLegalPredicate);
/** The filter ext but t2. */ /** The filter ext but t2. */
private final Predicate<CardEdition> filterExtButT2 = Predicates.and( private final Predicate<CardEdition> filterExtButT2 = Predicates.and(
CardEdition.Predicates.CAN_MAKE_BOOSTER, CardEdition.Predicates.CAN_MAKE_BOOSTER,
Predicates.and(this.filterExt, this.formats.getStandard().editionLegalPredicate)); Predicates.and(filterExt, formats.getStandard().editionLegalPredicate));
/** The filter not ext. */ /** The filter not ext. */
private final Predicate<CardEdition> filterNotExt = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER, private final Predicate<CardEdition> filterNotExt = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER, Predicates.not(filterExt));
Predicates.not(this.filterExt));
/** /**
* Helper predicate for shops: is legal in quest format. * Helper predicate for shops: is legal in quest format.
@@ -532,34 +523,105 @@ public final class QuestUtilCards {
return GameFormatQuest.Predicates.isLegalInFormatQuest(qFormat); return GameFormatQuest.Predicates.isLegalInFormatQuest(qFormat);
} }
/**
* Generates a number of special booster packs from random editions using the current quest's prize pool format.
* @param quantity The number of booster packs to generate
* @return A list containing the booster packs
*/
private List<InventoryItem> generateRandomSpecialBoosterPacks(final int quantity) {
List<InventoryItem> output = new ArrayList<>();
for (String color : SealedProduct.specialSets) {
for (int i = 0; i < quantity; i++) {
output.add(new BoosterPack(color, getColoredBoosterTemplate(color)));
}
}
return output;
}
/** /**
* Generate boosters in shop. * Generate boosters in shop.
* *
* @param count * @param quantity the count
* the count
*/ */
private void generateBoostersInShop(final int count) { private void generateBoostersInShop(final int quantity) {
for (int i = 0; i < count; i++) {
final int rollD100 = MyRandom.getRandom().nextInt(100); questAssets.getShopList().addAllFlat(BoosterUtils.generateRandomBoosterPacks(quantity, questController));
Predicate<CardEdition> filter = rollD100 < 40 ? this.filterT2booster
: (rollD100 < 75 ? this.filterExtButT2 : this.filterNotExt); if (questPreferences.getPrefInt(QPref.SPECIAL_BOOSTERS) == 1) {
if (qc.getFormat() != null) { questAssets.getShopList().addAllFlat(generateRandomSpecialBoosterPacks(quantity));
filter = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER, isLegalInQuestFormat(qc.getFormat()));
}
Iterable<CardEdition> rightEditions = Iterables.filter(FModel.getMagicDb().getEditions(), filter);
if (!rightEditions.iterator().hasNext()) {
continue;
}
this.qa.getShopList().add(BoosterPack.FN_FROM_SET.apply(Aggregates.random(rightEditions)));
} }
if (qpref.getPrefInt(QPref.SPECIAL_BOOSTERS) == 1) { }
for (String color : SealedProduct.specialSets) {
for (int i = 0; i < count; i++) { /**
this.qa.getShopList().add(new BoosterPack(color, getColoredBoosterTemplate(color))); * Generate boosters in shop.
} *
} * @param quantity the count
} */
private void generateOpenedBoostersInShop(final int quantity) {
if (questController.getFormat() == null) {
SealedProduct.Template boosterTemplate = getShopBoosterTemplate();
for (int i = 0; i < quantity; i++) {
questAssets.getShopList().addAllOfTypeFlat(new UnOpenedProduct(boosterTemplate).get());
}
return;
}
int commons = questPreferences.getPrefInt(QPref.SHOP_SINGLES_COMMON) * quantity;
int uncommons = questPreferences.getPrefInt(QPref.SHOP_SINGLES_COMMON) * quantity;
int rareOrMythics = questPreferences.getPrefInt(QPref.SHOP_SINGLES_COMMON) * quantity;
int attempts = commons + uncommons + rareOrMythics + 50;
List<PaperCard> toAdd = new ArrayList<>();
do {
List<PaperCard> cards = ((BoosterPack) BoosterUtils.generateRandomBoosterPacks(1, questController).get(0)).getCards();
if (commons > 0) {
commons = getRandomCardFromBooster(cards, COMMON_PREDICATE, toAdd, commons);
} else if (uncommons > 0) {
uncommons = getRandomCardFromBooster(cards, UNCOMMON_PREDICATE, toAdd, uncommons);
} else if (rareOrMythics > 0) {
rareOrMythics = getRandomCardFromBooster(cards, RARE_PREDICATE, toAdd, rareOrMythics);
} else {
break;
}
} while (commons + uncommons + rareOrMythics > 0 && attempts-- > 0);
questAssets.getShopList().addAllOfTypeFlat(toAdd);
}
private static int getRandomCardFromBooster(final List<PaperCard> cards, final Predicate<PaperCard> predicate, final List<PaperCard> toAddTo, final int amount) {
if (amount <= 0) {
return 0;
}
//TODO Replace me with Java 8 streams and filters
List<PaperCard> temp = new ArrayList<>();
for (PaperCard card : cards) {
if (predicate.apply(card)) {
temp.add(card);
}
}
if (!temp.isEmpty()) {
toAddTo.add(temp.get((int) (Math.random() * temp.size())));
return amount - 1;
}
return amount;
} }
@@ -571,11 +633,11 @@ public final class QuestUtilCards {
*/ */
private void generateTournamentsInShop(final int count) { private void generateTournamentsInShop(final int count) {
Predicate<CardEdition> formatFilter = CardEdition.Predicates.HAS_TOURNAMENT_PACK; Predicate<CardEdition> formatFilter = CardEdition.Predicates.HAS_TOURNAMENT_PACK;
if (qc.getFormat() != null) { if (questController.getFormat() != null) {
formatFilter = Predicates.and(formatFilter, isLegalInQuestFormat(qc.getFormat())); formatFilter = Predicates.and(formatFilter, isLegalInQuestFormat(questController.getFormat()));
} }
Iterable<CardEdition> rightEditions = Iterables.filter(FModel.getMagicDb().getEditions(), formatFilter); Iterable<CardEdition> rightEditions = Iterables.filter(FModel.getMagicDb().getEditions(), formatFilter);
this.qa.getShopList().addAllOfTypeFlat(Aggregates.random(Iterables.transform(rightEditions, TournamentPack.FN_FROM_SET), count)); questAssets.getShopList().addAllOfTypeFlat(Aggregates.random(Iterables.transform(rightEditions, TournamentPack.FN_FROM_SET), count));
} }
/** /**
@@ -586,11 +648,11 @@ public final class QuestUtilCards {
*/ */
private void generateFatPacksInShop(final int count) { private void generateFatPacksInShop(final int count) {
Predicate<CardEdition> formatFilter = CardEdition.Predicates.HAS_FAT_PACK; Predicate<CardEdition> formatFilter = CardEdition.Predicates.HAS_FAT_PACK;
if (qc.getFormat() != null) { if (questController.getFormat() != null) {
formatFilter = Predicates.and(formatFilter, isLegalInQuestFormat(qc.getFormat())); formatFilter = Predicates.and(formatFilter, isLegalInQuestFormat(questController.getFormat()));
} }
Iterable<CardEdition> rightEditions = Iterables.filter(FModel.getMagicDb().getEditions(), formatFilter); Iterable<CardEdition> rightEditions = Iterables.filter(FModel.getMagicDb().getEditions(), formatFilter);
this.qa.getShopList().addAllOfTypeFlat(Aggregates.random(Iterables.transform(rightEditions, FatPack.FN_FROM_SET), count)); questAssets.getShopList().addAllOfTypeFlat(Aggregates.random(Iterables.transform(rightEditions, FatPack.FN_FROM_SET), count));
} }
private void generateBoosterBoxesInShop(final int count) { private void generateBoosterBoxesInShop(final int count) {
@@ -600,8 +662,8 @@ public final class QuestUtilCards {
} }
Predicate<CardEdition> formatFilter = CardEdition.Predicates.HAS_BOOSTER_BOX; Predicate<CardEdition> formatFilter = CardEdition.Predicates.HAS_BOOSTER_BOX;
if (qc.getFormat() != null) { if (questController.getFormat() != null) {
formatFilter = Predicates.and(formatFilter, isLegalInQuestFormat(qc.getFormat())); formatFilter = Predicates.and(formatFilter, isLegalInQuestFormat(questController.getFormat()));
} }
Iterable<CardEdition> rightEditions = Iterables.filter(FModel.getMagicDb().getEditions(), formatFilter); Iterable<CardEdition> rightEditions = Iterables.filter(FModel.getMagicDb().getEditions(), formatFilter);
@@ -625,7 +687,7 @@ public final class QuestUtilCards {
output.add(BoosterBox.FN_FROM_SET.apply(e)); output.add(BoosterBox.FN_FROM_SET.apply(e));
} }
this.qa.getShopList().addAllOfTypeFlat(output); questAssets.getShopList().addAllOfTypeFlat(output);
} }
@@ -638,28 +700,28 @@ public final class QuestUtilCards {
private void generatePreconsInShop(final int count) { private void generatePreconsInShop(final int count) {
final List<PreconDeck> meetRequirements = new ArrayList<>(); final List<PreconDeck> meetRequirements = new ArrayList<>();
for (final PreconDeck deck : QuestController.getPrecons()) { for (final PreconDeck deck : QuestController.getPrecons()) {
if (QuestController.getPreconDeals(deck).meetsRequiremnts(this.qc.getAchievements()) if (QuestController.getPreconDeals(deck).meetsRequiremnts(questController.getAchievements())
&& (null == qc.getFormat() || qc.getFormat().isSetLegal(deck.getEdition()))) { && (null == questController.getFormat() || questController.getFormat().isSetLegal(deck.getEdition()))) {
meetRequirements.add(deck); meetRequirements.add(deck);
} }
} }
this.qa.getShopList().addAllOfTypeFlat(Aggregates.random(meetRequirements, count)); questAssets.getShopList().addAllOfTypeFlat(Aggregates.random(meetRequirements, count));
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private SealedProduct.Template getShopBoosterTemplate() { private SealedProduct.Template getShopBoosterTemplate() {
return new SealedProduct.Template(Lists.newArrayList( return new SealedProduct.Template(Lists.newArrayList(
Pair.of(BoosterSlots.COMMON, this.qpref.getPrefInt(QPref.SHOP_SINGLES_COMMON)), Pair.of(BoosterSlots.COMMON, questPreferences.getPrefInt(QPref.SHOP_SINGLES_COMMON)),
Pair.of(BoosterSlots.UNCOMMON, this.qpref.getPrefInt(QPref.SHOP_SINGLES_UNCOMMON)), Pair.of(BoosterSlots.UNCOMMON, questPreferences.getPrefInt(QPref.SHOP_SINGLES_UNCOMMON)),
Pair.of(BoosterSlots.RARE_MYTHIC, this.qpref.getPrefInt(QPref.SHOP_SINGLES_RARE)) Pair.of(BoosterSlots.RARE_MYTHIC, questPreferences.getPrefInt(QPref.SHOP_SINGLES_RARE))
)); ));
} }
private SealedProduct.Template getBoosterTemplate() { private SealedProduct.Template getBoosterTemplate() {
return new SealedProduct.Template(ImmutableList.of( return new SealedProduct.Template(ImmutableList.of(
Pair.of(BoosterSlots.COMMON, this.qpref.getPrefInt(QPref.BOOSTER_COMMONS)), Pair.of(BoosterSlots.COMMON, questPreferences.getPrefInt(QPref.BOOSTER_COMMONS)),
Pair.of(BoosterSlots.UNCOMMON, this.qpref.getPrefInt(QPref.BOOSTER_UNCOMMONS)), Pair.of(BoosterSlots.UNCOMMON, questPreferences.getPrefInt(QPref.BOOSTER_UNCOMMONS)),
Pair.of(BoosterSlots.RARE_MYTHIC, this.qpref.getPrefInt(QPref.BOOSTER_RARES)) Pair.of(BoosterSlots.RARE_MYTHIC, questPreferences.getPrefInt(QPref.BOOSTER_RARES))
)); ));
} }
@@ -672,18 +734,18 @@ public final class QuestUtilCards {
Pair.of(BoosterSlots.LAND + ":color(\"" + color + "\")", 1)) Pair.of(BoosterSlots.LAND + ":color(\"" + color + "\")", 1))
); );
} else { } else {
String restrictions = ""; StringBuilder restrictions = new StringBuilder();
List<String> allowedSetCodes = FModel.getQuest().getFormat().getAllowedSetCodes(); List<String> allowedSetCodes = FModel.getQuest().getFormat().getAllowedSetCodes();
if (allowedSetCodes.isEmpty()) { if (allowedSetCodes.isEmpty()) {
for (String restrictedCard : FModel.getQuest().getFormat().getRestrictedCards()) { for (String restrictedCard : FModel.getQuest().getFormat().getRestrictedCards()) {
restrictions += ":!name(\"" + restrictedCard + "\")"; restrictions.append(":!name(\"").append(restrictedCard).append("\")");
} }
} else { } else {
restrictions += ":fromSets(\""; restrictions.append(":fromSets(\"");
for (String set : allowedSetCodes) { for (String set : allowedSetCodes) {
restrictions += set + ","; restrictions.append(set).append(",");
} }
restrictions += ")"; restrictions.append(")");
} }
return new Template("?", ImmutableList.of( return new Template("?", ImmutableList.of(
Pair.of(BoosterSlots.COMMON + ":color(\"" + color + "\"):!" + BoosterSlots.LAND + restrictions, 11), Pair.of(BoosterSlots.COMMON + ":color(\"" + color + "\"):!" + BoosterSlots.LAND + restrictions, 11),
@@ -698,35 +760,31 @@ public final class QuestUtilCards {
* Generate cards in shop. * Generate cards in shop.
*/ */
private void generateCardsInShop() { private void generateCardsInShop() {
// Preferences
final int startPacks = this.qpref.getPrefInt(QPref.SHOP_STARTING_PACKS);
final int winsForPack = this.qpref.getPrefInt(QPref.SHOP_WINS_FOR_ADDITIONAL_PACK);
final int maxPacks = this.qpref.getPrefInt(QPref.SHOP_MAX_PACKS);
final int minPacks = this.qpref.getPrefInt(QPref.SHOP_MIN_PACKS);
int level = this.qc.getAchievements().getLevel(); // Preferences
final int startPacks = questPreferences.getPrefInt(QPref.SHOP_STARTING_PACKS);
final int winsForPack = questPreferences.getPrefInt(QPref.SHOP_WINS_FOR_ADDITIONAL_PACK);
final int maxPacks = questPreferences.getPrefInt(QPref.SHOP_MAX_PACKS);
final int minPacks = questPreferences.getPrefInt(QPref.SHOP_MIN_PACKS);
int level = questController.getAchievements().getLevel();
final int levelPacks = level > 0 ? startPacks / level : startPacks; final int levelPacks = level > 0 ? startPacks / level : startPacks;
final int winPacks = this.qc.getAchievements().getWin() / winsForPack; final int winPacks = questController.getAchievements().getWin() / winsForPack;
final int totalPacks = Math.min(Math.max(levelPacks + winPacks, minPacks), maxPacks); final int totalPacks = Math.min(Math.max(levelPacks + winPacks, minPacks), maxPacks);
SealedProduct.Template tpl = getShopBoosterTemplate(); generateOpenedBoostersInShop(totalPacks);
UnOpenedProduct unopened = qc.getFormat() == null ? new UnOpenedProduct(tpl) : new UnOpenedProduct(tpl, qc.getFormat().getFilterPrinted());
for (int i = 0; i < totalPacks; i++) { generateBoostersInShop(totalPacks);
this.qa.getShopList().addAllOfTypeFlat(unopened.get()); generatePreconsInShop(totalPacks);
generateTournamentsInShop(totalPacks);
generateFatPacksInShop(totalPacks);
generateBoosterBoxesInShop(totalPacks);
if (questController.getFormat() == null || questController.getFormat().hasSnowLands()) {
// Spell shop no longer sells basic lands (we use "Add Basic Lands" instead)
questAssets.getShopList().addAllOfType(generateBasicLands(0, 5, questController.getFormat()));
} }
this.generateBoostersInShop(totalPacks);
this.generatePreconsInShop(totalPacks);
this.generateTournamentsInShop(totalPacks);
this.generateFatPacksInShop(totalPacks);
this.generateBoosterBoxesInShop(totalPacks);
int numberSnowLands = 5;
if (qc.getFormat() != null && !qc.getFormat().hasSnowLands()) {
numberSnowLands = 0;
}
// Spell shop no longer sells basic lands (we use "Add Basic Lands" instead)
this.qa.getShopList().addAllOfType(QuestUtilCards.generateBasicLands(/*10*/0, numberSnowLands, qc.getFormat()));
} }
/** /**
@@ -735,7 +793,7 @@ public final class QuestUtilCards {
* @return the cardpool * @return the cardpool
*/ */
public ItemPool<PaperCard> getCardpool() { public ItemPool<PaperCard> getCardpool() {
return this.qa.getCardPool(); return questAssets.getCardPool();
} }
/** /**
@@ -744,10 +802,10 @@ public final class QuestUtilCards {
* @return the shop list * @return the shop list
*/ */
public ItemPool<InventoryItem> getShopList() { public ItemPool<InventoryItem> getShopList() {
if (this.qa.getShopList().isEmpty()) { if (questAssets.getShopList().isEmpty()) {
this.generateCardsInShop(); generateCardsInShop();
} }
return this.qa.getShopList(); return questAssets.getShopList();
} }
/** /**
@@ -756,26 +814,26 @@ public final class QuestUtilCards {
* @return the new cards * @return the new cards
*/ */
public ItemPool<InventoryItem> getNewCards() { public ItemPool<InventoryItem> getNewCards() {
return this.qa.getNewCardList(); return questAssets.getNewCardList();
} }
/** /**
* Reset new list. * Reset new list.
*/ */
public void resetNewList() { public void resetNewList() {
this.qa.getNewCardList().clear(); questAssets.getNewCardList().clear();
} }
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnNewCompare() { public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnNewCompare() {
return this.fnNewCompare; return fnNewCompare;
} }
public Function<Entry<? extends InventoryItem, Integer>, Object> getFnNewGet() { public Function<Entry<? extends InventoryItem, Integer>, Object> getFnNewGet() {
return this.fnNewGet; return fnNewGet;
} }
public boolean isNew(InventoryItem item) { public boolean isNew(InventoryItem item) {
return qa.getNewCardList().contains(item); return questAssets.getNewCardList().contains(item);
} }
// These functions provide a way to sort and compare cards in a table // These functions provide a way to sort and compare cards in a table
@@ -784,8 +842,7 @@ public final class QuestUtilCards {
// deck editors // deck editors
// Maybe we should consider doing so later // Maybe we should consider doing so later
/** The fn new compare. */ /** The fn new compare. */
private final Function<Entry<InventoryItem, Integer>, Comparable<?>> fnNewCompare = private final Function<Entry<InventoryItem, Integer>, Comparable<?>> fnNewCompare = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override @Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) { public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return isNew(from.getKey()) ? Integer.valueOf(1) : Integer.valueOf(0); return isNew(from.getKey()) ? Integer.valueOf(1) : Integer.valueOf(0);
@@ -793,8 +850,7 @@ public final class QuestUtilCards {
}; };
/** The fn new get. */ /** The fn new get. */
private final Function<Entry<? extends InventoryItem, Integer>, Object> fnNewGet = private final Function<Entry<? extends InventoryItem, Integer>, Object> fnNewGet = new Function<Entry<? extends InventoryItem, Integer>, Object>() {
new Function<Entry<? extends InventoryItem, Integer>, Object>() {
@Override @Override
public Object apply(final Entry<? extends InventoryItem, Integer> from) { public Object apply(final Entry<? extends InventoryItem, Integer> from) {
return isNew(from.getKey()) ? "NEW" : ""; return isNew(from.getKey()) ? "NEW" : "";
@@ -802,11 +858,11 @@ public final class QuestUtilCards {
}; };
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnOwnedCompare() { public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnOwnedCompare() {
return this.fnOwnedCompare; return fnOwnedCompare;
} }
public Function<Entry<? extends InventoryItem, Integer>, Object> getFnOwnedGet() { public Function<Entry<? extends InventoryItem, Integer>, Object> getFnOwnedGet() {
return this.fnOwnedGet; return fnOwnedGet;
} }
public int getCompletionPercent(String edition) { public int getCompletionPercent(String edition) {
@@ -825,7 +881,7 @@ public final class QuestUtilCards {
Predicate<PaperCard> filter = IPaperCard.Predicates.printedInSet(edition); Predicate<PaperCard> filter = IPaperCard.Predicates.printedInSet(edition);
Iterable<PaperCard> editionCards = Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), filter); Iterable<PaperCard> editionCards = Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), filter);
ItemPool<PaperCard> ownedCards = qa.getCardPool(); ItemPool<PaperCard> ownedCards = questAssets.getCardPool();
// 100% means at least one of every basic land and at least 4 of every other card in the set // 100% means at least one of every basic land and at least 4 of every other card in the set
int completeCards = 0; int completeCards = 0;
int numOwnedCards = 0; int numOwnedCards = 0;
@@ -837,16 +893,16 @@ public final class QuestUtilCards {
} }
return (numOwnedCards * 100) / completeCards; return (numOwnedCards * 100) / completeCards;
} }
// These functions provide a way to sort and compare items in the spell shop according to how many are already owned // These functions provide a way to sort and compare items in the spell shop according to how many are already owned
private final Function<Entry<InventoryItem, Integer>, Comparable<?>> fnOwnedCompare = private final Function<Entry<InventoryItem, Integer>, Comparable<?>> fnOwnedCompare = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override @Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) { public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
InventoryItem i = from.getKey(); InventoryItem i = from.getKey();
if (i instanceof PaperCard) { if (i instanceof PaperCard) {
return QuestUtilCards.this.qa.getCardPool().count((PaperCard) i); return questAssets.getCardPool().count((PaperCard) i);
} else if (i instanceof PreconDeck) { } else if (i instanceof PreconDeck) {
PreconDeck pDeck = (PreconDeck) i; PreconDeck pDeck = (PreconDeck) i;
return FModel.getQuest().getMyDecks().contains(pDeck.getName()) ? -1 : -2; return FModel.getQuest().getMyDecks().contains(pDeck.getName()) ? -1 : -2;
@@ -858,13 +914,12 @@ public final class QuestUtilCards {
} }
}; };
private final Function<Entry<? extends InventoryItem, Integer>, Object> fnOwnedGet = private final Function<Entry<? extends InventoryItem, Integer>, Object> fnOwnedGet = new Function<Entry<? extends InventoryItem, Integer>, Object>() {
new Function<Entry<? extends InventoryItem, Integer>, Object>() {
@Override @Override
public Object apply(final Entry<? extends InventoryItem, Integer> from) { public Object apply(final Entry<? extends InventoryItem, Integer> from) {
InventoryItem i = from.getKey(); InventoryItem i = from.getKey();
if (i instanceof PaperCard) { if (i instanceof PaperCard) {
return QuestUtilCards.this.qa.getCardPool().count((PaperCard) i); return questAssets.getCardPool().count((PaperCard) i);
} else if (i instanceof PreconDeck) { } else if (i instanceof PreconDeck) {
PreconDeck pDeck = (PreconDeck) i; PreconDeck pDeck = (PreconDeck) i;
return FModel.getQuest().getMyDecks().contains(pDeck.getName()) ? "YES" : "NO"; return FModel.getQuest().getMyDecks().contains(pDeck.getName()) ? "YES" : "NO";

View File

@@ -34,7 +34,9 @@ public final class StartingPoolPreferences {
/** Anything goes. Selected colors are ignored and what goes in the pool is almost entirely random. */ /** Anything goes. Selected colors are ignored and what goes in the pool is almost entirely random. */
RANDOM, RANDOM,
/** Same as BALANCED, except this picks colors for you without telling you what they are. */ /** Same as BALANCED, except this picks colors for you without telling you what they are. */
RANDOM_BALANCED RANDOM_BALANCED,
/** Opens a number of booster packs to create the initial card pool. */
BOOSTERS
} }
private final PoolType poolType; private final PoolType poolType;
@@ -42,6 +44,7 @@ public final class StartingPoolPreferences {
private final boolean includeArtifacts; private final boolean includeArtifacts;
private final boolean completeSet; private final boolean completeSet;
private final boolean allowDuplicates; private final boolean allowDuplicates;
private final int numberOfPacks;
/** /**
* Creates a new StartingPoolPreferences instance. * Creates a new StartingPoolPreferences instance.
@@ -53,12 +56,13 @@ public final class StartingPoolPreferences {
* @param completeSet If true, four of each card in the starting pool will be generated. * @param completeSet If true, four of each card in the starting pool will be generated.
* @param allowDuplicates If true, multiples of each card will be allowed to be generated. * @param allowDuplicates If true, multiples of each card will be allowed to be generated.
*/ */
public StartingPoolPreferences(final PoolType poolType, final List<Byte> preferredColors, final boolean includeArtifacts, final boolean completeSet, final boolean allowDuplicates) { public StartingPoolPreferences(final PoolType poolType, final List<Byte> preferredColors, final boolean includeArtifacts, final boolean completeSet, final boolean allowDuplicates, final int numberOfPacks) {
this.poolType = poolType; this.poolType = poolType;
this.preferredColors = preferredColors; this.preferredColors = preferredColors;
this.includeArtifacts = includeArtifacts; this.includeArtifacts = includeArtifacts;
this.completeSet = completeSet; this.completeSet = completeSet;
this.allowDuplicates = allowDuplicates; this.allowDuplicates = allowDuplicates;
this.numberOfPacks = numberOfPacks;
} }
/** /**
@@ -87,4 +91,8 @@ public final class StartingPoolPreferences {
return allowDuplicates; return allowDuplicates;
} }
public int getNumberOfBoosters() {
return numberOfPacks;
}
} }