diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestPrefs.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestPrefs.java index f674a819ed7..473822e99d9 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestPrefs.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestPrefs.java @@ -379,6 +379,16 @@ public enum VSubmenuQuestPrefs implements IVSubmenu { pnlShop.add(new FLabel.Builder().text("Wins to Uncap Sale Price").fontAlign(SwingConstants.RIGHT).build(), labelConstraints); pnlShop.add(new PrefInput(QPref.SHOP_WINS_FOR_NO_SELL_LIMIT, QuestPreferencesErrType.SHOP), fieldConstraints); + FLabel extraCardsToKeep = new FLabel.Builder().text("Copies of Cards to Keep").fontAlign(SwingConstants.RIGHT).build(); + extraCardsToKeep.setToolTipText("The number of copies of cards to keep before selling extras."); + pnlShop.add(extraCardsToKeep, labelConstraints); + pnlShop.add(new PrefInput(QPref.SHOP_EXTRAS_TO_KEEP, QuestPreferencesErrType.DIFFICULTY), fieldConstraints + ", wrap"); + + FLabel extraLandsToKeep = new FLabel.Builder().text("Copies of Basic Lands to Keep").fontAlign(SwingConstants.RIGHT).build(); + extraLandsToKeep.setToolTipText("The number of copies of basic lands to keep before selling extras."); + pnlShop.add(extraLandsToKeep, labelConstraints); + pnlShop.add(new PrefInput(QPref.SHOP_EXTRA_BASIC_LANDS_TO_KEEP, QuestPreferencesErrType.DIFFICULTY), fieldConstraints + ", wrap"); + pnlShop.add(new FLabel.Builder().text("Item Level Restriction").fontAlign(SwingConstants.RIGHT).build(), labelConstraints); pnlShop.add(new PrefInput(QPref.ITEM_LEVEL_RESTRICTION, QuestPreferencesErrType.SHOP), fieldConstraints); diff --git a/forge-gui-mobile/src/forge/screens/quest/QuestPrefsScreen.java b/forge-gui-mobile/src/forge/screens/quest/QuestPrefsScreen.java index 069a803b428..5c8816ece5f 100644 --- a/forge-gui-mobile/src/forge/screens/quest/QuestPrefsScreen.java +++ b/forge-gui-mobile/src/forge/screens/quest/QuestPrefsScreen.java @@ -83,6 +83,8 @@ public class QuestPrefsScreen extends FScreen { scroller.add(new PrefsOption("Common Singles", QPref.SHOP_SINGLES_COMMON, PrefsGroup.SHOP)); scroller.add(new PrefsOption("Uncommon Singles", QPref.SHOP_SINGLES_UNCOMMON, PrefsGroup.SHOP)); scroller.add(new PrefsOption("Rare Singles", QPref.SHOP_SINGLES_RARE, PrefsGroup.SHOP)); + scroller.add(new PrefsOption("Copies of Cards to Keep", QPref.SHOP_EXTRAS_TO_KEEP, PrefsGroup.SHOP)); + scroller.add(new PrefsOption("Copies of Basic Lands to Keep", QPref.SHOP_EXTRA_BASIC_LANDS_TO_KEEP, PrefsGroup.SHOP)); //Difficulty Adjustments (All) scroller.add(new PrefsHeader("Difficulty Adjustments (All)", FSkinImage.QUEST_NOTES, PrefsGroup.DIFFICULTY_ALL)); diff --git a/forge-gui/src/main/java/forge/itemmanager/BooleanExpression.java b/forge-gui/src/main/java/forge/itemmanager/BooleanExpression.java index 9ec861f6f02..34eeeb87d97 100644 --- a/forge-gui/src/main/java/forge/itemmanager/BooleanExpression.java +++ b/forge-gui/src/main/java/forge/itemmanager/BooleanExpression.java @@ -13,25 +13,25 @@ public class BooleanExpression { private Stack operators = new Stack<>(); private Stack> operands = new Stack<>(); - + private StringTokenizer expression; - + private boolean inName, inType, inText, inCost; - private static enum Operator { + private enum Operator { AND("&", 0), OR("|", 0), NOT("!", 1), OPEN_PAREN("(", 2), CLOSE_PAREN(")", 2), ESCAPE("\\", -1); private final String token; private final int precedence; - private Operator(final String token, final int precedence) { + Operator(final String token, final int precedence) { this.token = token; this.precedence = precedence; } } - + public BooleanExpression(final String expression, final boolean inName, final boolean inType, final boolean inText, final boolean inCost) { this.expression = new StringTokenizer(expression); this.inName = inName; @@ -39,7 +39,7 @@ public class BooleanExpression { this.inText = inText; this.inCost = inCost; } - + public Predicate evaluate() { String currentValue = ""; @@ -68,17 +68,17 @@ public class BooleanExpression { if (operator == null) { currentValue += token; } else { - + if (escapeNext) { escapeNext = false; currentValue += token; continue; } - + if (!currentValue.trim().isEmpty()) { operands.push(valueOf(currentValue.trim())); } - + currentValue = ""; if (!operators.isEmpty() && operator.precedence < operators.peek().precedence) { @@ -88,11 +88,11 @@ public class BooleanExpression { while (!operators.isEmpty() && operators.peek() != Operator.OPEN_PAREN) { resolve(true); } - + } - + operators.push(operator); - + } } @@ -101,14 +101,14 @@ public class BooleanExpression { operands.push(valueOf(currentValue.trim())); } - while (operators.size() > 0) { + while (!operators.isEmpty()) { resolve(true); } - + return operands.get(0); - + } - + private void resolve(final boolean alwaysPopOperator) { Predicate right; @@ -138,11 +138,11 @@ public class BooleanExpression { } break; } - + } - + private Predicate valueOf(final String value) { - + List> predicates = new ArrayList<>(); if (inName) { predicates.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, value)); @@ -156,15 +156,15 @@ public class BooleanExpression { if (inCost) { predicates.add(CardRulesPredicates.cost(StringOp.CONTAINS_IC, value)); } - if (predicates.size() > 0) { + if (!predicates.isEmpty()) { return Predicates.or(predicates); } return Predicates.alwaysTrue(); - + } - + public static boolean isExpression(final String string) { return string.contains(Operator.AND.token) || string.contains(Operator.OR.token) || string.trim().startsWith(Operator.NOT.token); } - + } diff --git a/forge-gui/src/main/java/forge/quest/QuestSpellShop.java b/forge-gui/src/main/java/forge/quest/QuestSpellShop.java index 2007e518c84..d4f5cb71f52 100644 --- a/forge-gui/src/main/java/forge/quest/QuestSpellShop.java +++ b/forge-gui/src/main/java/forge/quest/QuestSpellShop.java @@ -10,6 +10,7 @@ import forge.itemmanager.IItemManager; import forge.itemmanager.SItemManagerUtil; import forge.model.FModel; import forge.properties.ForgePreferences.FPref; +import forge.quest.data.QuestPreferences.QPref; import forge.quest.io.ReadPriceList; import forge.util.ItemPool; import forge.util.gui.SOptionPane; @@ -27,10 +28,10 @@ public class QuestSpellShop { private static ItemPool decksUsingMyCards; public static Integer getCardValue(final InventoryItem card) { - String ns = null; + String ns; int value = 1337; // previously this was the returned default boolean foil = false; - int foilMultiplier = 1; + int foilMultiplier; if (card instanceof PaperCard) { ns = card.getName() + "|" + ((PaperCard) card).getEdition(); @@ -104,7 +105,7 @@ public class QuestSpellShop { value *= foilMultiplier; } - return Integer.valueOf(value); + return value; } public static final Function, Comparable> fnPriceCompare = new Function, Comparable>() { @@ -128,21 +129,20 @@ public class QuestSpellShop { public static final Function, Comparable> fnDeckCompare = new Function, Comparable>() { @Override public Comparable apply(final Entry from) { - final Integer iValue = decksUsingMyCards.count(from.getKey()); - return iValue == null ? Integer.valueOf(0) : iValue; + return decksUsingMyCards.count(from.getKey()); } }; public static final Function, Object> fnDeckGet = new Function, Object>() { @Override public Object apply(final Entry from) { final Integer iValue = decksUsingMyCards.count(from.getKey()); - return iValue == null ? "" : iValue.toString(); + return iValue.toString(); } }; public static void buy(Iterable> items, IItemManager shopManager, IItemManager inventoryManager, boolean confirmPurchase) { long totalCost = 0; - ItemPool itemsToBuy = new ItemPool(InventoryItem.class); + ItemPool itemsToBuy = new ItemPool<>(InventoryItem.class); for (Entry itemEntry : items) { final InventoryItem item = itemEntry.getKey(); if (item instanceof PaperCard || item instanceof SealedProduct || item instanceof PreconDeck) { @@ -169,7 +169,7 @@ public class QuestSpellShop { return; } - ItemPool itemsToAdd = new ItemPool(InventoryItem.class); + ItemPool itemsToAdd = new ItemPool<>(InventoryItem.class); for (Entry itemEntry : itemsToBuy) { final InventoryItem item = itemEntry.getKey(); @@ -197,6 +197,7 @@ public class QuestSpellShop { booster = (BoosterBox) ((BoosterBox) item).clone(); } FModel.getQuest().getCards().buyPack(booster, value); + assert booster != null; final List newCards = booster.getCards(); itemsToAdd.addAllFlat(newCards); @@ -219,7 +220,7 @@ public class QuestSpellShop { remainingCards.addAll(((BoxedProduct) booster).getExtraCards()); - if (remainingCards.size() > 0) { + if (!remainingCards.isEmpty()) { GuiBase.getInterface().showCardList(booster.getName(), "You have found the following cards inside:", remainingCards); } @@ -252,7 +253,7 @@ public class QuestSpellShop { public static void sell(Iterable> items, IItemManager shopManager, IItemManager inventoryManager, boolean confirmSale) { long totalReceived = 0; - ItemPool itemsToSell = new ItemPool(InventoryItem.class); + ItemPool itemsToSell = new ItemPool<>(InventoryItem.class); for (Entry itemEntry : items) { final InventoryItem item = itemEntry.getKey(); if (item instanceof PaperCard) { @@ -288,10 +289,11 @@ public class QuestSpellShop { } public static void sellExtras(IItemManager shopManager, IItemManager inventoryManager) { - List> cardsToRemove = new LinkedList>(); + List> cardsToRemove = new LinkedList<>(); for (Entry item : inventoryManager.getPool()) { PaperCard card = (PaperCard)item.getKey(); - int numToKeep = card.getRules().getType().isBasic() ? 50 : 4; + int numToKeep = card.getRules().getType().isBasic() ? + FModel.getQuestPreferences().getPrefInt(QPref.SHOP_EXTRA_BASIC_LANDS_TO_KEEP) : FModel.getQuestPreferences().getPrefInt(QPref.SHOP_EXTRAS_TO_KEEP); if ("Relentless Rats".equals(card.getName()) || "Shadowborn Apostle".equals(card.getName())) { numToKeep = Integer.MAX_VALUE; } @@ -316,7 +318,7 @@ public class QuestSpellShop { // fills number of decks using each card public static void updateDecksForEachCard() { - decksUsingMyCards = new ItemPool(InventoryItem.class); + decksUsingMyCards = new ItemPool<>(InventoryItem.class); for (final Deck deck : FModel.getQuest().getMyDecks()) { CardPool main = deck.getMain(); for (final Entry e : main) { diff --git a/forge-gui/src/main/java/forge/quest/data/QuestPreferences.java b/forge-gui/src/main/java/forge/quest/data/QuestPreferences.java index 97b5da46547..33a4e0589ba 100644 --- a/forge-gui/src/main/java/forge/quest/data/QuestPreferences.java +++ b/forge-gui/src/main/java/forge/quest/data/QuestPreferences.java @@ -154,6 +154,10 @@ public class QuestPreferences extends PreferencesStore i // Wins until the selling price limit is removed SHOP_WINS_FOR_NO_SELL_LIMIT("50"), + //The number of cards to keep before selling + SHOP_EXTRAS_TO_KEEP("4"), + SHOP_EXTRA_BASIC_LANDS_TO_KEEP("50"), + ITEM_LEVEL_RESTRICTION("1"); private final String strDefaultVal; @@ -250,54 +254,61 @@ public class QuestPreferences extends PreferencesStore i public String validatePreference(final QPref qpref, final int val) { switch (qpref) { - case STARTING_POOL_COLOR_BIAS: - if (val < 1) { - return "Bias value too small (minimum 1)."; - } else if (val > 100) { - return "Bias value too large (maximum 100)."; - } - break; + case STARTING_POOL_COLOR_BIAS: + if (val < 1) { + return "Bias value too small (minimum 1)."; + } else if (val > 100) { + return "Bias value too large (maximum 100)."; + } + break; - case ITEM_LEVEL_RESTRICTION: - if (val != 0 && val != 1) { - return "Only values 0 or 1 are acceptable; 1 for enabled, 0 for disabled."; - } - break; + case ITEM_LEVEL_RESTRICTION: + if (val != 0 && val != 1) { + return "Only values 0 or 1 are acceptable; 1 for enabled, 0 for disabled."; + } + break; - case SHOP_MAX_PACKS: - case SHOP_MAX_SELLING_PRICE: - case SHOP_WINS_FOR_ADDITIONAL_PACK: - case WINS_NEW_DRAFT: - case WINS_ROTATE_DRAFT: - case WINS_UNLOCK_SET: - if (val < 1) { - return "Value too small (minimum 1)."; - } - break; + case SHOP_EXTRA_BASIC_LANDS_TO_KEEP: + if (val < 10) { + return "Value too small (minimum 10)."; + } + break; - case BOOSTER_COMMONS: - case BOOSTER_UNCOMMONS: - case BOOSTER_RARES: - case STARTING_CREDITS_EASY: - case STARTING_CREDITS_MEDIUM: - case STARTING_CREDITS_HARD: - case STARTING_CREDITS_EXPERT: - case REWARDS_MILLED: - case REWARDS_MULLIGAN0: - case REWARDS_ALTERNATIVE: - case REWARDS_TURN5: - case REWARDS_TURN1: - case SHOP_MIN_PACKS: - case SHOP_STARTING_PACKS: - case SHOP_SINGLES_COMMON: - case SHOP_SINGLES_UNCOMMON: - case SHOP_SINGLES_RARE: - case SHOP_WINS_FOR_NO_SELL_LIMIT: - default: - if (val < 0) { - return "Value too small (minimum 0)."; - } - break; + case SHOP_MAX_PACKS: + case SHOP_MAX_SELLING_PRICE: + case SHOP_WINS_FOR_ADDITIONAL_PACK: + case SHOP_EXTRAS_TO_KEEP: + case WINS_NEW_DRAFT: + case WINS_ROTATE_DRAFT: + case WINS_UNLOCK_SET: + if (val < 1) { + return "Value too small (minimum 1)."; + } + break; + + case BOOSTER_COMMONS: + case BOOSTER_UNCOMMONS: + case BOOSTER_RARES: + case STARTING_CREDITS_EASY: + case STARTING_CREDITS_MEDIUM: + case STARTING_CREDITS_HARD: + case STARTING_CREDITS_EXPERT: + case REWARDS_MILLED: + case REWARDS_MULLIGAN0: + case REWARDS_ALTERNATIVE: + case REWARDS_TURN5: + case REWARDS_TURN1: + case SHOP_MIN_PACKS: + case SHOP_STARTING_PACKS: + case SHOP_SINGLES_COMMON: + case SHOP_SINGLES_UNCOMMON: + case SHOP_SINGLES_RARE: + case SHOP_WINS_FOR_NO_SELL_LIMIT: + default: + if (val < 0) { + return "Value too small (minimum 0)."; + } + break; } return null; }