From f0f741ace4e57cdf49182b7b78312aab09727095 Mon Sep 17 00:00:00 2001 From: Krazy Date: Sat, 2 May 2015 00:39:34 +0000 Subject: [PATCH] Cleaned up and the new quest section for readability and added an option to allow duplicate cards in a quest's starting pool --- .../screens/home/quest/CSubmenuQuestData.java | 78 ++++---- .../screens/home/quest/VSubmenuQuestData.java | 174 +++++++++--------- .../forge/screens/quest/NewQuestScreen.java | 73 +++----- .../main/java/forge/quest/BoosterUtils.java | 74 ++++---- .../main/java/forge/quest/QuestSpellShop.java | 35 ++-- .../forge/quest/StartingPoolPreferences.java | 40 ++-- 6 files changed, 227 insertions(+), 247 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestData.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestData.java index 88ca50d2a60..f0bbc94b99e 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestData.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestData.java @@ -1,17 +1,5 @@ package forge.screens.home.quest; -import java.io.File; -import java.io.FilenameFilter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import javax.swing.SwingUtilities; - import forge.UiCommand; import forge.deck.Deck; import forge.deck.DeckSection; @@ -20,18 +8,19 @@ import forge.gui.framework.ICDoc; import forge.item.PaperCard; import forge.model.FModel; import forge.properties.ForgeConstants; -import forge.quest.QuestController; -import forge.quest.QuestMode; -import forge.quest.QuestUtil; -import forge.quest.QuestWorld; -import forge.quest.StartingPoolPreferences; -import forge.quest.StartingPoolType; +import forge.quest.*; import forge.quest.data.GameFormatQuest; import forge.quest.data.QuestData; import forge.quest.data.QuestPreferences.QPref; import forge.quest.io.QuestDataIO; import forge.toolbox.FOptionPane; +import javax.swing.*; +import java.io.File; +import java.io.FilenameFilter; +import java.util.*; +import java.util.Map.Entry; + /** * Controls the quest data submenu in the home UI. * @@ -80,27 +69,33 @@ public enum CSubmenuQuestData implements ICDoc { unselectableSets.add("ARC"); unselectableSets.add("PC2"); - view.getBtnCustomFormat().setCommand(new UiCommand() { @Override public void run() { - final DialogChooseSets dialog = new DialogChooseSets(customFormatCodes, unselectableSets, false); - dialog.setOkCallback(new Runnable() { - @Override - public void run() { - customFormatCodes.clear(); - customFormatCodes.addAll(dialog.getSelectedSets()); - } - }); - } }); + view.getBtnCustomFormat().setCommand(new UiCommand() { + @Override + public void run() { + final DialogChooseSets dialog = new DialogChooseSets(customFormatCodes, unselectableSets, false); + dialog.setOkCallback(new Runnable() { + @Override + public void run() { + customFormatCodes.clear(); + customFormatCodes.addAll(dialog.getSelectedSets()); + } + }); + } + }); - view.getBtnPrizeCustomFormat().setCommand(new UiCommand() { @Override public void run() { - final DialogChooseSets dialog = new DialogChooseSets(customPrizeFormatCodes, unselectableSets, false); - dialog.setOkCallback(new Runnable() { - @Override - public void run() { - customPrizeFormatCodes.clear(); - customPrizeFormatCodes.addAll(dialog.getSelectedSets()); - } - }); - } }); + view.getBtnPrizeCustomFormat().setCommand(new UiCommand() { + @Override + public void run() { + final DialogChooseSets dialog = new DialogChooseSets(customPrizeFormatCodes, unselectableSets, false); + dialog.setOkCallback(new Runnable() { + @Override + public void run() { + customPrizeFormatCodes.clear(); + customPrizeFormatCodes.addAll(dialog.getSelectedSets()); + } + }); + } + }); } /* (non-Javadoc) @@ -152,7 +147,10 @@ public enum CSubmenuQuestData implements ICDoc { view.getLstQuests().setEditCommand(cmdQuestUpdate); SwingUtilities.invokeLater(new Runnable() { - @Override public void run() { view.getBtnEmbark().requestFocusInWindow(); } + @Override + public void run() { + view.getBtnEmbark().requestFocusInWindow(); + } }); } @@ -253,7 +251,7 @@ public enum CSubmenuQuestData implements ICDoc { // } else { // fmtPrizes = worldFormat; // } - final StartingPoolPreferences userPrefs = new StartingPoolPreferences(view.randomizeColorDistribution(), view.getPreferredColor(), view.startWithCompleteSet()); + final StartingPoolPreferences userPrefs = new StartingPoolPreferences(view.randomizeColorDistribution(), view.getPreferredColor(), view.startWithCompleteSet(), view.allowDuplicateCards()); String questName; while (true) { diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestData.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestData.java index 3e3165942fa..ca73483b50e 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestData.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestData.java @@ -1,20 +1,5 @@ package forge.screens.home.quest; -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.HashMap; -import java.util.Map; - -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import javax.swing.plaf.basic.BasicComboBoxRenderer; - -import net.miginfocom.swing.MigLayout; - -import org.apache.commons.lang3.text.WordUtils; - import forge.card.MagicColor; import forge.deck.Deck; import forge.deck.DeckGroup; @@ -32,29 +17,32 @@ import forge.quest.StartingPoolType; import forge.screens.home.EMenuGroup; import forge.screens.home.IVSubmenu; import forge.screens.home.VHomeUI; -import forge.toolbox.FCheckBox; -import forge.toolbox.FComboBoxWrapper; -import forge.toolbox.FLabel; -import forge.toolbox.FRadioButton; -import forge.toolbox.FScrollPane; -import forge.toolbox.FSkin; -import forge.toolbox.JXButtonPanel; +import forge.toolbox.*; import forge.util.storage.IStorage; +import net.miginfocom.swing.MigLayout; +import org.apache.commons.lang3.text.WordUtils; + +import javax.swing.*; +import javax.swing.plaf.basic.BasicComboBoxRenderer; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.HashMap; +import java.util.Map; /** * Assembles Swing components of quest data submenu singleton. * *

(V at beginning of class name denotes a view class.) */ +@SuppressWarnings("FieldCanBeLocal") public enum VSubmenuQuestData implements IVSubmenu { - /** */ SINGLETON_INSTANCE; // Fields used with interface IVDoc private DragCell parentCell; private final DragTab tab = new DragTab("Quest Data"); - /** */ private final FLabel lblTitle = new FLabel.Builder() .text("Load Quest Data").fontAlign(SwingConstants.CENTER) .opaque(true).fontSize(16).build(); @@ -70,50 +58,52 @@ public enum VSubmenuQuestData implements IVSubmenu { private final FScrollPane scrQuests = new FScrollPane(lstQuests, false); private final JPanel pnlOptions = new JPanel(); - /* Fist column */ + /* First column */ private final FRadioButton radEasy = new FRadioButton("Easy"); private final FRadioButton radMedium = new FRadioButton("Medium"); private final FRadioButton radHard = new FRadioButton("Hard"); private final FRadioButton radExpert = new FRadioButton("Expert"); private final FCheckBox boxFantasy = new FCheckBox("Fantasy Mode"); - private final FCheckBox boxCompleteSet = new FCheckBox("Start with all cards in selected sets"); private final FLabel lblStartingWorld = new FLabel.Builder().text("Starting world:").build(); - private final FComboBoxWrapper cbxStartingWorld = new FComboBoxWrapper(); - - private final FLabel lblPreferredColor = new FLabel.Builder().text("Starting pool colors:").build(); - private final FComboBoxWrapper cbxPreferredColor = new FComboBoxWrapper(); - private final String stringBalancedDistribution = new String("balanced distribution"); - private final String stringRandomizedDistribution = new String("randomized distribution"); - private final String stringBias = new String(" bias"); + private final FComboBoxWrapper cbxStartingWorld = new FComboBoxWrapper<>(); /* Second column */ - private final FLabel lblStartingPool = new FLabel.Builder().text("Starting pool:").build(); - private final FComboBoxWrapper cbxStartingPool = new FComboBoxWrapper(); + private final FComboBoxWrapper cbxStartingPool = new FComboBoxWrapper<>(); private final FLabel lblUnrestricted = new FLabel.Builder().text("All cards will be available to play.").build(); private final FLabel lblPreconDeck = new FLabel.Builder().text("Starter/Event deck:").build(); - private final FComboBoxWrapper cbxPreconDeck = new FComboBoxWrapper(); + private final FComboBoxWrapper cbxPreconDeck = new FComboBoxWrapper<>(); private final FLabel lblFormat = new FLabel.Builder().text("Sanctioned format:").build(); - private final FComboBoxWrapper cbxFormat = new FComboBoxWrapper(); + private final FComboBoxWrapper cbxFormat = new FComboBoxWrapper<>(); private final FLabel lblCustomDeck = new FLabel.Builder().text("Custom deck:").build(); - private final FComboBoxWrapper cbxCustomDeck = new FComboBoxWrapper(); + private final FComboBoxWrapper cbxCustomDeck = new FComboBoxWrapper<>(); private final FLabel btnDefineCustomFormat = new FLabel.Builder().opaque(true).hoverable(true).text("Define custom format").build(); + + private final FCheckBox boxCompleteSet = new FCheckBox("Start with all cards in selected sets"); + private final FCheckBox boxAllowDuplicates = new FCheckBox("Allow duplicate cards"); + + private final FLabel lblPreferredColor = new FLabel.Builder().text("Starting pool colors:").build(); + private final FComboBoxWrapper cbxPreferredColor = new FComboBoxWrapper<>(); + private final String stringBalancedDistribution = "balanced distribution"; + private final String stringRandomizedDistribution = "randomized distribution"; + private final String stringBias = " bias"; + private final FLabel btnPrizeDefineCustomFormat = new FLabel.Builder().opaque(true).hoverable(true).text("Define custom format").build(); private final FLabel lblPrizedCards = new FLabel.Builder().text("Prized cards:").build(); - private final FComboBoxWrapper cbxPrizedCards = new FComboBoxWrapper(); + private final FComboBoxWrapper cbxPrizedCards = new FComboBoxWrapper<>(); private final FLabel lblPrizeFormat = new FLabel.Builder().text("Sanctioned format:").build(); - private final FComboBoxWrapper cbxPrizeFormat = new FComboBoxWrapper(); + private final FComboBoxWrapper cbxPrizeFormat = new FComboBoxWrapper<>(); private final FLabel lblPrizeUnrestricted = new FLabel.Builder().text("All cards will be available to win.").build(); - private final FLabel lblPrizeSameAsStarting = new FLabel.Builder().text("Only sets found in starting pool will be available.").build(); + private final FLabel lblPrizeSameAsStarting = new FLabel.Builder().text("Only sets in starting pool will be available.").build(); private final FCheckBox cboAllowUnlocks = new FCheckBox("Allow unlock of additional editions"); @@ -145,15 +135,15 @@ public enum VSubmenuQuestData implements IVSubmenu { cbxCustomDeck.removeAllItems(); final CardCollections decks = FModel.getDecks(); switch (newVal) { - case SealedDeck: - for (final DeckGroup d : decks.getSealed()) { cbxCustomDeck.addItem(d.getHumanDeck()); } - break; - case DraftDeck: - for (final DeckGroup d : decks.getDraft()) { cbxCustomDeck.addItem(d.getHumanDeck()); } - break; - case Cube: - for (final Deck d : decks.getCubes()) { cbxCustomDeck.addItem(d); } - break; + case SealedDeck: + for (final DeckGroup d : decks.getSealed()) { cbxCustomDeck.addItem(d.getHumanDeck()); } + break; + case DraftDeck: + for (final DeckGroup d : decks.getDraft()) { cbxCustomDeck.addItem(d.getHumanDeck()); } + break; + case Cube: + for (final Deck d : decks.getCubes()) { cbxCustomDeck.addItem(d); } + break; } } } @@ -202,12 +192,13 @@ public enum VSubmenuQuestData implements IVSubmenu { * Constructor. */ @SuppressWarnings("unchecked") - private VSubmenuQuestData() { + VSubmenuQuestData() { + lblTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); lblTitleNew.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); final JXButtonPanel difficultyPanel = new JXButtonPanel(); - final String difficulty_constraints = "h 27px!, gapbottom 5"; + final String difficulty_constraints = "h 25px!, gapbottom 5"; difficultyPanel.add(radEasy, difficulty_constraints); difficultyPanel.add(radMedium, difficulty_constraints); difficultyPanel.add(radHard, difficulty_constraints); @@ -215,6 +206,7 @@ public enum VSubmenuQuestData implements IVSubmenu { radEasy.setSelected(true); boxCompleteSet.setToolTipText("You will start the quest with 4 of each card in the sets you have selected."); + boxAllowDuplicates.setToolTipText("When your starting pool is generated duplicates of cards may be included."); cbxStartingPool.addItem(StartingPoolType.Complete); cbxStartingPool.addItem(StartingPoolType.Rotating); @@ -261,7 +253,7 @@ public enum VSubmenuQuestData implements IVSubmenu { cboAllowUnlocks.setSelected(true); - final Map preconDescriptions = new HashMap(); + final Map preconDescriptions = new HashMap<>(); final IStorage preconDecks = QuestController.getPrecons(); for (final PreconDeck preconDeck : preconDecks) { @@ -297,6 +289,7 @@ public enum VSubmenuQuestData implements IVSubmenu { boxFantasy.setSelected(true); boxFantasy.setEnabled(true); boxCompleteSet.setEnabled(true); + boxAllowDuplicates.setEnabled(true); cbxPreferredColor.setEnabled(true); @@ -305,60 +298,59 @@ public enum VSubmenuQuestData implements IVSubmenu { final JPanel pnlDifficultyMode = new JPanel(new MigLayout("insets 0, gap 1%, flowy")); pnlDifficultyMode.add(difficultyPanel, "gapright 4%"); - pnlDifficultyMode.add(boxFantasy, difficulty_constraints + ", gapright 4%"); + pnlDifficultyMode.add(boxFantasy, "h 27px!, gapbottom 15, gapright 4%"); + pnlDifficultyMode.add(lblStartingWorld, "h 27px!, hidemode 3"); + cbxStartingWorld.addTo(pnlDifficultyMode, "h 27px!, w 40%, pushx, hidemode 3"); pnlDifficultyMode.setOpaque(false); pnlOptions.add(pnlDifficultyMode, "w 40%"); final JPanel pnlRestrictions = new JPanel(); - final String constraints = "h 27px!, "; - final String lblWidth = "w 40%, "; + final String constraints = "h 25px!, "; final String hidemode = "hidemode 3, "; - final String lblWidthStart = lblWidth + hidemode; - final String cboWidth = "pushx, "; + final String cboWidth = "w 240px!, pushx, "; final String cboWidthStart = cboWidth + hidemode; + final String btnStartingCustomFormatWidth = "w " + (4 + cbxStartingPool.getAutoSizeWidth()) + "px!, "; - pnlRestrictions.setLayout(new MigLayout("insets 0, gap 0, wrap 2", "[120, al right][240, fill]", "[|]12[|]6[]")); + pnlRestrictions.setLayout(new MigLayout("insets 0, gap 10", "[right][left]")); - pnlRestrictions.add(lblStartingPool, constraints + lblWidthStart); - cbxStartingPool.addTo(pnlRestrictions, constraints + cboWidthStart); + pnlRestrictions.add(lblStartingPool, "h 15px!, cell 0 0"); + cbxStartingPool.addTo(pnlRestrictions, constraints + cboWidthStart + " cell 1 0"); - /* out of these 3 groups only one will be visible */ - pnlRestrictions.add(lblUnrestricted, constraints + hidemode + "spanx 2"); + /* --vvv-- out of these 3 groups only one will be visible --vvv-- */ + pnlRestrictions.add(lblUnrestricted, constraints + hidemode + " cell 1 1, "); - pnlRestrictions.add(lblPreconDeck, constraints + lblWidthStart); - cbxPreconDeck.addTo(pnlRestrictions, constraints + cboWidthStart); + pnlRestrictions.add(lblPreconDeck, constraints + hidemode + " cell 0 1"); + cbxPreconDeck.addTo(pnlRestrictions, constraints + cboWidthStart + " cell 1 1"); - pnlRestrictions.add(lblCustomDeck, constraints + lblWidthStart); - cbxCustomDeck.addTo(pnlRestrictions, constraints + cboWidthStart); // , skip 1 + pnlRestrictions.add(lblCustomDeck, constraints + hidemode + " cell 0 1"); + cbxCustomDeck.addTo(pnlRestrictions, constraints + cboWidthStart + " cell 1 1"); + /* --^^^-- out of these 3 groups only one will be visible --^^^-- */ - pnlRestrictions.add(lblFormat, constraints + lblWidthStart); - cbxFormat.addTo(pnlRestrictions, constraints + cboWidthStart); // , skip 1 + pnlRestrictions.add(lblFormat, constraints + hidemode + " cell 0 1"); + cbxFormat.addTo(pnlRestrictions, constraints + cboWidthStart + " cell 1 1"); - pnlRestrictions.add(btnDefineCustomFormat, constraints + hidemode + "spanx 2, w 240px"); + pnlRestrictions.add(btnDefineCustomFormat, btnStartingCustomFormatWidth + constraints + hidemode + " cell 1 1"); + + pnlRestrictions.add(boxAllowDuplicates, "h 15px!, cell 1 2"); + pnlRestrictions.add(boxCompleteSet, "h 15px!, cell 1 3"); + + pnlRestrictions.add(lblPreferredColor, constraints + hidemode + "cell 0 4"); + cbxPreferredColor.addTo(pnlRestrictions, constraints + cboWidthStart + "cell 1 4"); // Prized cards options - pnlRestrictions.add(lblPrizedCards, constraints + lblWidth); - cbxPrizedCards.addTo(pnlRestrictions, constraints + cboWidth); + pnlRestrictions.add(lblPrizedCards, constraints + " cell 0 5"); + cbxPrizedCards.addTo(pnlRestrictions, constraints + cboWidth + " cell 1 5"); - pnlRestrictions.add(lblPrizeFormat, constraints + lblWidthStart); - cbxPrizeFormat.addTo(pnlRestrictions, constraints + cboWidthStart); // , skip 1 - pnlRestrictions.add(btnPrizeDefineCustomFormat, constraints + hidemode + "spanx 2, w 240px"); - pnlRestrictions.add(lblPrizeSameAsStarting, constraints + hidemode + "spanx 2"); - pnlRestrictions.add(lblPrizeUnrestricted, constraints + hidemode + "spanx 2"); + pnlRestrictions.add(lblPrizeFormat, constraints + hidemode + "cell 0 6"); + cbxPrizeFormat.addTo(pnlRestrictions, constraints + cboWidthStart + "cell 1 6"); // , skip 1 + pnlRestrictions.add(btnPrizeDefineCustomFormat, constraints + hidemode + "cell 1 6"); + pnlRestrictions.add(lblPrizeSameAsStarting, constraints + hidemode + "cell 1 6"); + pnlRestrictions.add(lblPrizeUnrestricted, constraints + hidemode + "cell 1 6"); - pnlRestrictions.add(cboAllowUnlocks, constraints + "spanx 2, ax right"); - pnlRestrictions.add(boxCompleteSet, constraints + "spanx 2, ax right"); + pnlRestrictions.add(cboAllowUnlocks, constraints + "cell 1 7"); - - pnlRestrictions.add(lblPreferredColor, constraints + lblWidthStart); - cbxPreferredColor.addTo(pnlRestrictions, constraints + cboWidthStart + ", wrap"); - - pnlRestrictions.add(lblStartingWorld, constraints + lblWidthStart); - cbxStartingWorld.addTo(pnlRestrictions, constraints + cboWidthStart); - - // cboAllowUnlocks.setOpaque(false); pnlRestrictions.setOpaque(false); pnlOptions.add(pnlRestrictions, "pushx, ay top"); @@ -477,12 +469,12 @@ public enum VSubmenuQuestData implements IVSubmenu { } public String getSelectedPrecon() { - return cbxPreconDeck.getSelectedItem().toString(); + return cbxPreconDeck.getSelectedItem(); } public Deck getSelectedDeck() { final Object sel = cbxCustomDeck.getSelectedItem(); - return sel instanceof Deck ? (Deck) sel : null; + return sel != null ? (Deck) sel : null; } public boolean isUnlockSetsAllowed() { @@ -510,6 +502,10 @@ public enum VSubmenuQuestData implements IVSubmenu { return boxCompleteSet.isSelected(); } + public boolean allowDuplicateCards() { + return boxAllowDuplicates.isSelected(); + } + public boolean randomizeColorDistribution() { return stringRandomizedDistribution.equals(cbxPreferredColor.getSelectedItem()); } diff --git a/forge-gui-mobile/src/forge/screens/quest/NewQuestScreen.java b/forge-gui-mobile/src/forge/screens/quest/NewQuestScreen.java index 565f7902bd6..47b27d26f93 100644 --- a/forge-gui-mobile/src/forge/screens/quest/NewQuestScreen.java +++ b/forge-gui-mobile/src/forge/screens/quest/NewQuestScreen.java @@ -1,17 +1,6 @@ package forge.screens.quest; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; - -import org.apache.commons.lang3.text.WordUtils; - import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment; - import forge.FThreads; import forge.assets.FSkinFont; import forge.assets.FSkinImage; @@ -25,38 +14,31 @@ import forge.item.PreconDeck; import forge.model.CardCollections; import forge.model.FModel; import forge.properties.ForgeConstants; -import forge.quest.QuestController; -import forge.quest.QuestMode; -import forge.quest.QuestUtil; -import forge.quest.QuestWorld; -import forge.quest.StartingPoolPreferences; -import forge.quest.StartingPoolType; +import forge.quest.*; import forge.quest.data.GameFormatQuest; import forge.quest.data.QuestPreferences.QPref; import forge.screens.FScreen; import forge.screens.LoadingOverlay; import forge.screens.home.NewGameMenu; import forge.screens.quest.QuestMenu.LaunchReason; -import forge.toolbox.FCheckBox; -import forge.toolbox.FComboBox; -import forge.toolbox.FDisplayObject; -import forge.toolbox.FEvent; +import forge.toolbox.*; import forge.toolbox.FEvent.FEventHandler; -import forge.toolbox.FLabel; -import forge.toolbox.FOptionPane; -import forge.toolbox.FScrollPane; import forge.util.FileUtil; import forge.util.ThreadUtil; import forge.util.Utils; import forge.util.gui.SOptionPane; import forge.util.storage.IStorage; +import org.apache.commons.lang3.text.WordUtils; + +import java.util.*; +import java.util.Map.Entry; public class NewQuestScreen extends FScreen { private static final float EMBARK_BTN_HEIGHT = 2 * Utils.AVG_FINGER_HEIGHT; private static final float PADDING = FOptionPane.PADDING; - private final List customFormatCodes = new ArrayList(); - private final List customPrizeFormatCodes = new ArrayList(); + private final List customFormatCodes = new ArrayList<>(); + private final List customPrizeFormatCodes = new ArrayList<>(); private final FScrollPane scroller = add(new FScrollPane() { @Override @@ -99,15 +81,15 @@ public class NewQuestScreen extends FScreen { @SuppressWarnings("unused") private final FLabel lblDifficulty = scroller.add(new FLabel.Builder().text("Difficulty:").build()); - private final FComboBox cbxDifficulty = scroller.add(new FComboBox(new String[]{ "Easy", "Medium", "Hard", "Expert" })); + private final FComboBox cbxDifficulty = scroller.add(new FComboBox<>(new String[]{ "Easy", "Medium", "Hard", "Expert" })); @SuppressWarnings("unused") private final FLabel lblPreferredColor = scroller.add(new FLabel.Builder().text("Starting pool colors:").build()); private final FComboBox cbxPreferredColor = scroller.add(new FComboBox()); - private final String stringBalancedDistribution = new String("balanced distribution"); - private final String stringRandomizedDistribution = new String("randomized distribution"); - private final String stringBias = new String(" bias"); - + private final String stringBalancedDistribution = "balanced distribution"; + private final String stringRandomizedDistribution = "randomized distribution"; + private final String stringBias = " bias"; + @SuppressWarnings("unused") private final FLabel lblStartingPool = scroller.add(new FLabel.Builder().text("Starting pool:").build()); private final FComboBox cbxStartingPool = scroller.add(new FComboBox()); @@ -127,7 +109,7 @@ public class NewQuestScreen extends FScreen { @SuppressWarnings("unused") private final FLabel lblPrizedCards = scroller.add(new FLabel.Builder().text("Prized cards:").build()); - private final FComboBox cbxPrizedCards = scroller.add(new FComboBox()); + private final FComboBox cbxPrizedCards = scroller.add(new FComboBox<>()); private final FLabel lblPrizeFormat = scroller.add(new FLabel.Builder().text("Sanctioned format:").build()); private final FComboBox cbxPrizeFormat = scroller.add(new FComboBox()); @@ -138,6 +120,7 @@ public class NewQuestScreen extends FScreen { private final FCheckBox cbAllowUnlocks = scroller.add(new FCheckBox("Allow unlock of additional editions")); private final FCheckBox cbCompleteSet = scroller.add(new FCheckBox("Start with all cards in selected sets")); + private final FCheckBox cbDuplicateCards = scroller.add(new FCheckBox("Allow duplicates in starting pool")); private final FCheckBox cbFantasy = scroller.add(new FCheckBox("Fantasy Mode")); private final FLabel btnEmbark = add(new FLabel.ButtonBuilder() @@ -218,7 +201,7 @@ public class NewQuestScreen extends FScreen { cbAllowUnlocks.setSelected(true); - final Map preconDescriptions = new HashMap(); + final Map preconDescriptions = new HashMap<>(); IStorage preconDecks = QuestController.getPrecons(); for (PreconDeck preconDeck : preconDecks) { @@ -237,7 +220,7 @@ public class NewQuestScreen extends FScreen { btnPrizeDefineCustomFormat.setEnabled(false); // disable the very powerful sets -- they can be unlocked later for a high price - final List unselectableSets = new ArrayList(); + final List unselectableSets = new ArrayList<>(); unselectableSets.add("LEA"); unselectableSets.add("LEB"); unselectableSets.add("MBP"); @@ -359,12 +342,12 @@ public class NewQuestScreen extends FScreen { } public String getSelectedPrecon() { - return cbxPreconDeck.getSelectedItem().toString(); + return cbxPreconDeck.getSelectedItem(); } public Deck getSelectedDeck() { Object sel = cbxCustomDeck.getSelectedItem(); - return sel instanceof Deck ? (Deck) sel : null; + return sel != null ? (Deck) sel : null; } public boolean isUnlockSetsAllowed() { @@ -375,8 +358,12 @@ public class NewQuestScreen extends FScreen { return cbCompleteSet.isSelected(); } + public boolean allowDuplicateCards() { + return cbDuplicateCards.isSelected(); + } + public StartingPoolType getStartingPoolType() { - return (StartingPoolType) cbxStartingPool.getSelectedItem(); + return cbxStartingPool.getSelectedItem(); } public StartingPoolType getPrizedPoolType() { @@ -405,11 +392,11 @@ public class NewQuestScreen extends FScreen { } public GameFormat getRotatingFormat() { - return (GameFormat) cbxFormat.getSelectedItem(); + return cbxFormat.getSelectedItem(); } public GameFormat getPrizedRotatingFormat() { - return (GameFormat) cbxPrizeFormat.getSelectedItem(); + return cbxPrizeFormat.getSelectedItem(); } @Override @@ -468,7 +455,7 @@ public class NewQuestScreen extends FScreen { fmtStartPool = worldFormat; } - GameFormat fmtPrizes = null; + GameFormat fmtPrizes; // The starting QuestWorld format should NOT affect what you get if you travel to a world that doesn't have one... // if (worldFormat == null) { @@ -476,7 +463,7 @@ public class NewQuestScreen extends FScreen { if (null == prizedPoolType) { fmtPrizes = fmtStartPool; if (null == fmtPrizes && dckStartPool != null) { // build it form deck - Set sets = new HashSet(); + Set sets = new HashSet<>(); for (Entry c : dckStartPool.getMain()) { sets.add(c.getKey().getEdition()); } @@ -500,7 +487,7 @@ public class NewQuestScreen extends FScreen { return; } } - fmtPrizes = customPrizeFormatCodes.isEmpty() ? null : new GameFormat("Custom Prizes", customPrizeFormatCodes, null); // chosen sets and no banend cards + fmtPrizes = customPrizeFormatCodes.isEmpty() ? null : new GameFormat("Custom Prizes", customPrizeFormatCodes, null); // chosen sets and no banned cards break; case Rotating: fmtPrizes = getPrizedRotatingFormat(); @@ -539,7 +526,7 @@ public class NewQuestScreen extends FScreen { @Override public void run() { final QuestMode mode = isFantasy() ? QuestMode.Fantasy : QuestMode.Classic; - final StartingPoolPreferences userPrefs = new StartingPoolPreferences(randomizeColorDistribution(), getPreferredColor(), startWithCompleteSet()); + final StartingPoolPreferences userPrefs = new StartingPoolPreferences(randomizeColorDistribution(), getPreferredColor(), startWithCompleteSet(), allowDuplicateCards()); QuestController qc = FModel.getQuest(); qc.newGame(questName, getSelectedDifficulty(), mode, fmtPrizes, isUnlockSetsAllowed(), dckStartPool, fmtStartPool, getStartingWorldName(), userPrefs); qc.save(); diff --git a/forge-gui/src/main/java/forge/quest/BoosterUtils.java b/forge-gui/src/main/java/forge/quest/BoosterUtils.java index 793bd73d6b0..fdf4134c695 100644 --- a/forge-gui/src/main/java/forge/quest/BoosterUtils.java +++ b/forge-gui/src/main/java/forge/quest/BoosterUtils.java @@ -6,12 +6,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -39,12 +39,11 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -// The BoosterPack generates cards for the Card Pool in Quest Mode /** *

- * QuestBoosterPack class. + * QuestBoosterPack class. Generates cards for the Card Pool in Quest Mode *

- * + * * @author Forge * @version $Id$ */ @@ -52,7 +51,7 @@ public final class BoosterUtils { /** * Gets the quest starter deck. - * + * * @param filter * the filter * @param numCommon @@ -68,13 +67,13 @@ public final class BoosterUtils { public static List getQuestStarterDeck(final Predicate filter, final int numCommon, final int numUncommon, final int numRare, final StartingPoolPreferences userPrefs) { - final ArrayList cards = new ArrayList(); + final ArrayList cards = new ArrayList<>(); // Each color should have around the same amount of monocolored cards // There should be 3 Colorless cards for every 4 cards in a single color // There should be 1 Multicolor card for every 4 cards in a single color - final List> colorFilters = new ArrayList>(); + final List> colorFilters = new ArrayList<>(); final boolean preferred = (userPrefs != null && userPrefs.getPreferredColor() != MagicColor.ALL_COLORS); final boolean randomized = userPrefs != null && userPrefs.useRandomPool(); final int colorBias = (preferred && !randomized) ? FModel.getQuestPreferences().getPrefInt(QPref.STARTING_POOL_COLOR_BIAS) : 0; @@ -108,23 +107,24 @@ public final class BoosterUtils { // This will save CPU time when sets are limited final List cardpool = Lists.newArrayList(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), filter)); - if (userPrefs.grantCompleteSet()) { - for (PaperCard card : cardpool) { - cards.add(card); - cards.add(card); - cards.add(card); - cards.add(card); - } - return cards; - } - + assert userPrefs != null; + if (userPrefs.grantCompleteSet()) { + for (PaperCard card : cardpool) { + cards.add(card); + cards.add(card); + cards.add(card); + cards.add(card); + } + return cards; + } + final Predicate pCommon = IPaperCard.Predicates.Presets.IS_COMMON; - cards.addAll(BoosterUtils.generateDefinetlyColouredCards(cardpool, pCommon, biasAdjustedCommons, colorFilters)); + cards.addAll(BoosterUtils.generateCards(cardpool, pCommon, biasAdjustedCommons, colorFilters, userPrefs.allowDuplicates())); final Predicate pUncommon = IPaperCard.Predicates.Presets.IS_UNCOMMON; - cards.addAll(BoosterUtils.generateDefinetlyColouredCards(cardpool, pUncommon, biasAdjustedUncommons, colorFilters)); + cards.addAll(BoosterUtils.generateCards(cardpool, pUncommon, biasAdjustedUncommons, colorFilters, userPrefs.allowDuplicates())); - int nRares = biasAdjustedRares, nMythics = 0; + int nRares = biasAdjustedRares, nMythics = 0; final Predicate filterMythics = IPaperCard.Predicates.Presets.IS_MYTHIC_RARE; final boolean haveMythics = Iterables.any(cardpool, filterMythics); for (int iSlot = 0; haveMythics && (iSlot < numRare); iSlot++) { @@ -136,16 +136,16 @@ public final class BoosterUtils { } final Predicate pRare = IPaperCard.Predicates.Presets.IS_RARE; - cards.addAll(BoosterUtils.generateDefinetlyColouredCards(cardpool, pRare, nRares, colorFilters)); + cards.addAll(BoosterUtils.generateCards(cardpool, pRare, nRares, colorFilters, false)); if (nMythics > 0) { - cards.addAll(BoosterUtils.generateDefinetlyColouredCards(cardpool, filterMythics, nMythics, colorFilters)); + cards.addAll(BoosterUtils.generateCards(cardpool, filterMythics, nMythics, colorFilters, userPrefs.allowDuplicates())); } return cards; } /** * Create the list of card names at random from the given pool. - * + * * @param source * an Iterable * @param filter @@ -154,12 +154,16 @@ public final class BoosterUtils { * an int * @param allowedColors * a List> + * @param allowDuplicates + * If true, multiple copies of the same card will be allowed to be generated. * @return a list of card names */ - private static ArrayList generateDefinetlyColouredCards(final Iterable source, - final Predicate filter, final int cntNeeded, final List> allowedColors) { + private static ArrayList generateCards( + final Iterable source, final Predicate filter, final int cntNeeded, + final List> allowedColors, final boolean allowDuplicates) { + // If color is null, use colorOrder progression to grab cards - final ArrayList result = new ArrayList(); + final ArrayList result = new ArrayList<>(); final int size = allowedColors == null ? 0 : allowedColors.size(); if (allowedColors != null) { @@ -169,8 +173,7 @@ public final class BoosterUtils { int cntMade = 0, iAttempt = 0; // This will prevent endless loop @ wh - int allowedMisses = (2 + size + 2) * cntNeeded; // lol, 2+2 is not magic - // constant! + int allowedMisses = (size + 4) * cntNeeded; // lol, 2+2 is not magic constant! while ((cntMade < cntNeeded) && (allowedMisses > 0)) { PaperCard card = null; @@ -188,7 +191,7 @@ public final class BoosterUtils { card = Aggregates.random(Iterables.filter(source, filter)); } - if ((card != null) && !result.contains(card)) { + if ((card != null) && (allowDuplicates || !result.contains(card))) { result.add(card); cntMade++; } else { @@ -206,7 +209,7 @@ public final class BoosterUtils { * @param input * String, the limitation as text. * @return Predicate the text parsed into a CardRules predicate. - * + * */ public static Predicate parseRulesLimitation(final String input) { if (null == input || "random".equalsIgnoreCase(input)) { @@ -240,18 +243,19 @@ public final class BoosterUtils { private static List parseReward(final String s) { String[] temp = s.split(" "); - List rewards = new ArrayList(); + List rewards = new ArrayList<>(); // last word starts with 'rare' ignore case if (temp.length > 1 && temp[temp.length - 1].regionMatches(true, 0, "rare", 0, 4)) { // Type 1: 'n [color] rares' final int qty = Integer.parseInt(temp[0]); - List> preds = new ArrayList>(); + List> preds = new ArrayList<>(); preds.add(IPaperCard.Predicates.Presets.IS_RARE_OR_MYTHIC); // Determine rarity if (temp.length > 2) { Predicate cr = parseRulesLimitation(temp[1]); + //noinspection RedundantCast if (Predicates.alwaysTrue() != (Object) cr) { // guava has a single instance for always-const predicates preds.add(Predicates.compose(cr, PaperCard.FN_GET_RULES)); } @@ -295,7 +299,7 @@ public final class BoosterUtils { * generateCardRewardList. *

* Takes a reward list string, parses, and returns list of cards rewarded. - * + * * @param s * Properties string of reward (97 multicolor rares) * @return List @@ -307,7 +311,7 @@ public final class BoosterUtils { } final String[] items = s.split(";"); - final List rewards = new ArrayList(); + final List rewards = new ArrayList<>(); for (final String item : items) { diff --git a/forge-gui/src/main/java/forge/quest/QuestSpellShop.java b/forge-gui/src/main/java/forge/quest/QuestSpellShop.java index 84fcbc437a8..2007e518c84 100644 --- a/forge-gui/src/main/java/forge/quest/QuestSpellShop.java +++ b/forge-gui/src/main/java/forge/quest/QuestSpellShop.java @@ -1,29 +1,11 @@ package forge.quest; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.commons.lang3.tuple.Pair; - import com.google.common.base.Function; - import forge.GuiBase; import forge.deck.CardPool; import forge.deck.Deck; import forge.deck.DeckSection; -import forge.item.BoosterBox; -import forge.item.BoosterPack; -import forge.item.BoxedProduct; -import forge.item.FatPack; -import forge.item.IPaperCard; -import forge.item.InventoryItem; -import forge.item.PaperCard; -import forge.item.PreconDeck; -import forge.item.SealedProduct; -import forge.item.TournamentPack; +import forge.item.*; import forge.itemmanager.IItemManager; import forge.itemmanager.SItemManagerUtil; import forge.model.FModel; @@ -31,6 +13,13 @@ import forge.properties.ForgePreferences.FPref; import forge.quest.io.ReadPriceList; import forge.util.ItemPool; import forge.util.gui.SOptionPane; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; public class QuestSpellShop { private static Map mapPrices; @@ -211,9 +200,9 @@ public class QuestSpellShop { final List newCards = booster.getCards(); itemsToAdd.addAllFlat(newCards); - + if (booster instanceof BoxedProduct && FModel.getPreferences().getPrefBoolean(FPref.UI_OPEN_PACKS_INDIV)) { - + int totalPacks = ((BoxedProduct) booster).boosterPacksRemaining(); boolean skipTheRest = false; final List remainingCards = new ArrayList<>(); @@ -233,7 +222,7 @@ public class QuestSpellShop { if (remainingCards.size() > 0) { GuiBase.getInterface().showCardList(booster.getName(), "You have found the following cards inside:", remainingCards); } - + } else { GuiBase.getInterface().showCardList(booster.getName(), "You have found the following cards inside:", newCards); @@ -279,7 +268,7 @@ public class QuestSpellShop { String suffix = SItemManagerUtil.getItemDisplayString(itemFlatList, 1, true); String displayList = SItemManagerUtil.buildDisplayList(itemsToSell); String title = "Sell " + suffix; - + if (!SOptionPane.showConfirmDialog("Sell the following " + suffix.toLowerCase() + " for " + totalReceived + " credit" + (totalReceived != 1 ? "s" : "") + "?\n" + displayList, title, "Sell", "Cancel")) { return; diff --git a/forge-gui/src/main/java/forge/quest/StartingPoolPreferences.java b/forge-gui/src/main/java/forge/quest/StartingPoolPreferences.java index b37101251d8..db67207e968 100644 --- a/forge-gui/src/main/java/forge/quest/StartingPoolPreferences.java +++ b/forge-gui/src/main/java/forge/quest/StartingPoolPreferences.java @@ -6,18 +6,18 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package forge.quest; -/** +/** * This class is used to store the Quest starting pool preferences. * (It could be expanded to store other Quest starting preferences as well, * in order to reduce the number of parameters that need to be passed to @@ -28,20 +28,22 @@ public final class StartingPoolPreferences { private final boolean randomPool; private final byte preferredColor; - private final boolean completeSet; + private final boolean completeSet; + private final boolean allowDuplicates; /** - * The constructor. - * @param random - * true = use completely random pool without filter restrictions - * (Note that this does NOT bypass card rarity restrictions!) - * @param preference - * preferred color/COLORLESS (ALL_COLORS = no preference) + * Creates a new StartingPoolPreferences instance. + * @param random If true, a completely random pool will be generated without filter restrictions. This does not + * bypass rarity restrictions. + * @param preference Preferred color or colorless. All colors == no preference. See {@link forge.card.MagicColor}. + * @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. */ - public StartingPoolPreferences(final boolean random, final byte preference, final boolean completeSet) { + public StartingPoolPreferences(final boolean random, final byte preference, final boolean completeSet, final boolean allowDuplicates) { randomPool = random; preferredColor = preference; - this.completeSet = completeSet; + this.completeSet = completeSet; + this.allowDuplicates = allowDuplicates; } /** @@ -60,9 +62,13 @@ public final class StartingPoolPreferences { public byte getPreferredColor() { return preferredColor; } - - public boolean grantCompleteSet() { - return completeSet; - } - + + public boolean grantCompleteSet() { + return completeSet; + } + + public boolean allowDuplicates() { + return allowDuplicates; + } + }