From cc8c27ecb67ac6881826b584782a9d57b14913a7 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Sun, 13 Jan 2013 17:19:07 +0000 Subject: [PATCH] * Better sideboarding: decks have no extra fields for changed parts, they are copied on sideboarding, new deck composition moved outside of GuiChoose.java * Decks have no extra sections for variants (sideboard works in most cases) * Deck Format restrictions are in a separate class not related to GameType + DeckSection has its own toString overload + DualListBox operates CardPrinted properly (sideboarding dialog uses cardprinted instances) + ItemPool.remove method returns true if any elements were removed. --- .gitattributes | 1 + src/main/java/forge/deck/Deck.java | 114 +-------- src/main/java/forge/deck/DeckFormat.java | 212 ++++++++++++++++ src/main/java/forge/deck/DeckSection.java | 29 +++ src/main/java/forge/deck/DeckgenUtil.java | 4 +- .../java/forge/deck/io/DeckFileHeader.java | 13 +- .../java/forge/deck/io/OldDeckParser.java | 2 +- src/main/java/forge/game/GameNew.java | 77 +++--- src/main/java/forge/game/GameType.java | 238 +++--------------- src/main/java/forge/game/MatchController.java | 8 +- .../forge/game/PlayerStartConditions.java | 23 +- .../java/forge/game/player/HumanPlayer.java | 2 +- src/main/java/forge/gui/DualListBox.java | 3 + src/main/java/forge/gui/GuiChoose.java | 12 +- .../deckeditor/controllers/CEditorScheme.java | 2 +- .../gui/home/quest/SSubmenuQuestUtil.java | 2 +- .../home/sanctioned/CSubmenuConstructed.java | 3 +- .../gui/home/sanctioned/CSubmenuDraft.java | 3 +- .../gui/home/sanctioned/CSubmenuSealed.java | 4 +- .../gui/home/variant/CSubmenuArchenemy.java | 19 +- .../java/forge/gui/match/ControlWinLose.java | 5 +- .../java/forge/gui/match/QuestWinLose.java | 16 -- src/main/java/forge/item/ItemPool.java | 9 +- src/main/java/forge/quest/QuestUtilCards.java | 1 - src/main/java/forge/quest/io/QuestDataIO.java | 21 -- src/main/java/forge/util/FileSection.java | 2 +- 26 files changed, 395 insertions(+), 430 deletions(-) create mode 100644 src/main/java/forge/deck/DeckFormat.java diff --git a/.gitattributes b/.gitattributes index f1011fc1646..bb9f55a2fdb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13476,6 +13476,7 @@ src/main/java/forge/control/package-info.java -text src/main/java/forge/deck/CardCollections.java -text src/main/java/forge/deck/Deck.java svneol=native#text/plain src/main/java/forge/deck/DeckBase.java -text +src/main/java/forge/deck/DeckFormat.java -text src/main/java/forge/deck/DeckGroup.java -text src/main/java/forge/deck/DeckRecognizer.java -text src/main/java/forge/deck/DeckSection.java -text diff --git a/src/main/java/forge/deck/Deck.java b/src/main/java/forge/deck/Deck.java index 38a90172b92..4ff7fb1ccb8 100644 --- a/src/main/java/forge/deck/Deck.java +++ b/src/main/java/forge/deck/Deck.java @@ -59,17 +59,9 @@ public class Deck extends DeckBase { */ private static final long serialVersionUID = -7478025567887481994L; - private transient boolean isEdited = false; private final DeckSection main; - private final DeckSection sideboard; - private final DeckSection planes; - private final DeckSection schemes; - - private transient DeckSection mainEdited; - private transient DeckSection sideboardEdited; + private final DeckSection sideboard; // commander, planes or schemes are also stored here private CardPrinted avatar; - private CardPrinted commander; - // gameType is from Constant.GameType, like GameType.Regular /** @@ -90,12 +82,7 @@ public class Deck extends DeckBase { super(name0); this.main = new DeckSection(); this.sideboard = new DeckSection(); - this.mainEdited = new DeckSection(); - this.sideboardEdited = new DeckSection(); this.avatar = null; - this.commander = null; - this.planes = new DeckSection(); - this.schemes = new DeckSection(); } /** @@ -116,26 +103,13 @@ public class Deck extends DeckBase { return this.getName(); } - /** - *

- * Getter for the field main. - *

- * - * @return a {@link java.util.List} object. - */ public DeckSection getMain() { - return isEdited ? this.mainEdited : this.main; + return this.main; } - /** - *

- * Getter for the field sideboard. - *

- * - * @return a {@link java.util.List} object. - */ + // variants' extra deck sections used instead of sideboard (planes, commander, schemes) are here as well as usual sideboards public DeckSection getSideboard() { - return isEdited ? this.sideboardEdited : this.sideboard; + return this.sideboard; } /* @@ -145,7 +119,7 @@ public class Deck extends DeckBase { */ @Override public ItemPoolView getCardPool() { - return isEdited ? this.mainEdited : this.main; + return this.main; } /* (non-Javadoc) @@ -158,13 +132,6 @@ public class Deck extends DeckBase { result.main.addAll(this.main); result.sideboard.addAll(this.sideboard); result.avatar = this.avatar; - result.commander = this.commander; - - //This if clause is really only necessary when cloning decks that were - //around before schemes. - if (this.schemes != null) { - result.schemes.addAll(this.schemes); - } } /* @@ -219,14 +186,14 @@ public class Deck extends DeckBase { d.getMain().set(Deck.readCardList(sections.get("main"))); d.getSideboard().set(Deck.readCardList(sections.get("sideboard"))); - List cmd = Deck.readCardList(sections.get("commander")); - String cmdName = cmd.isEmpty() ? null : cmd.get(0); - d.commander = CardDb.instance().isCardSupported(cmdName) ? CardDb.instance().getCard(cmdName) : null; + // try also earlier deck formats + if ( d.getSideboard().isEmpty() ) { d.getSideboard().set(Deck.readCardList(sections.get("schemes"))); } + if ( d.getSideboard().isEmpty() ) { d.getSideboard().set(Deck.readCardList(sections.get("planes"))); } + if ( d.getSideboard().isEmpty() ) { d.getSideboard().set(Deck.readCardList(sections.get("commander"))); } + List av = Deck.readCardList(sections.get("avatar")); String avName = av.isEmpty() ? null : av.get(0); d.avatar = CardDb.instance().isCardSupported(avName) ? CardDb.instance().getCard(avName) : null; - d.getPlanes().set(Deck.readCardList(sections.get("planes"))); - d.getSchemes().set(Deck.readCardList(sections.get("schemes"))); return d; } @@ -303,20 +270,10 @@ public class Deck extends DeckBase { out.add(String.format("%s", "[sideboard]")); out.addAll(Deck.writeCardPool(this.getSideboard())); - if (getCommander() != null) { - out.add(String.format("%s", "[commander]")); - out.add(Deck.serializeSingleCard(getCommander(), 1)); - } if (getAvatar() != null) { out.add(String.format("%s", "[avatar]")); out.add(Deck.serializeSingleCard(getAvatar(), 1)); } - - out.add(String.format("%s", "[planes]")); - out.addAll(Deck.writeCardPool(this.getPlanes())); - - out.add(String.format("%s", "[schemes]")); - out.addAll(Deck.writeCardPool(this.getSchemes())); return out; } @@ -324,22 +281,9 @@ public class Deck extends DeckBase { * @return the commander */ public CardPrinted getCommander() { - return commander; + return sideboard != null && !sideboard.isEmpty() ? sideboard.get(0) : null; } - /** - * @return the planes - */ - public DeckSection getPlanes() { - return planes; - } - - /** - * @return the schemes - */ - public DeckSection getSchemes() { - return schemes; - } /** * @return the avatar @@ -354,40 +298,4 @@ public class Deck extends DeckBase { return arg1.getName(); } }; - - public void clearDeckEdits() { - isEdited = false; - if (mainEdited != null) { - mainEdited.clear(); - } else { - mainEdited = new DeckSection(); - } - if (sideboardEdited != null) { - sideboardEdited.clear(); - } else { - sideboardEdited = new DeckSection(); - } - } - - public void startDeckEdits() { - isEdited = true; - if (mainEdited.countAll() == 0) { - mainEdited.add(main.toFlatList()); - } - if (sideboardEdited.countAll() == 0) { - sideboardEdited.add(sideboard.toFlatList()); - } - } - - public DeckSection getOriginalMain() { - return this.main; - } - - public DeckSection getOriginalSideboard() { - return this.sideboard; - } - - public boolean isEditedDeck() { - return this.isEdited; - } } diff --git a/src/main/java/forge/deck/DeckFormat.java b/src/main/java/forge/deck/DeckFormat.java new file mode 100644 index 00000000000..19969f6529d --- /dev/null +++ b/src/main/java/forge/deck/DeckFormat.java @@ -0,0 +1,212 @@ +/* + * Forge: Play Magic: the Gathering. + * Copyright (C) 2011 Forge Team + * + * This program is free software: you can redistribute it and/or modify + * 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.deck; + +import java.util.Arrays; +import java.util.List; +import java.util.Map.Entry; + +import org.apache.commons.lang.math.IntRange; + +import forge.card.CardCoreType; +import forge.item.CardDb; +import forge.item.CardPrinted; +import forge.util.Aggregates; + +/** + * GameType is an enum to determine the type of current game. :) + */ +public enum DeckFormat { + + // Main board: allowed size SB: restriction Max distinct non basic cards + Constructed ( new IntRange(60, Integer.MAX_VALUE), new IntRange(15), 4), + Limited ( new IntRange(40, Integer.MAX_VALUE), null, Integer.MAX_VALUE), + Commander ( new IntRange(99 /* commndr in SB*/), new IntRange(1), 1), + Vanguard ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4), + Planechase ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4), + Archenemy ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4); + + private final IntRange mainRange; + private final IntRange sideRange; // null => no check + private final int maxCardCopies; + + + /** + * Instantiates a new game type. + * + * @param isLimited + * the is limited + */ + DeckFormat(IntRange main, IntRange side, int maxCopies) { + mainRange = main; + sideRange = side; + maxCardCopies = maxCopies; + } + + /** + * Smart value of. + * + * @param value the value + * @param defaultValue the default value + * @return the game type + */ + public static DeckFormat smartValueOf(final String value, DeckFormat defaultValue) { + if (null == value) { + return defaultValue; + } + + final String valToCompate = value.trim(); + for (final DeckFormat v : DeckFormat.values()) { + if (v.name().compareToIgnoreCase(valToCompate) == 0) { + return v; + } + } + + throw new IllegalArgumentException("No element named " + value + " in enum GameType"); + } + + + /** + * @return the sideRange + */ + public IntRange getSideRange() { + return sideRange; + } + + + /** + * @return the mainRange + */ + public IntRange getMainRange() { + return mainRange; + } + + + /** + * @return the maxCardCopies + */ + public int getMaxCardCopies() { + return maxCardCopies; + } + + + + @SuppressWarnings("incomplete-switch") + public String getDeckConformanceProblem(Deck deck) { + int deckSize = deck.getMain().countAll(); + + int min = getMainRange().getMinimumInteger(); + int max = getMainRange().getMaximumInteger(); + + if (deckSize < min) { + return String.format("should have a minimum of %d cards", min); + } + + if (deckSize > max) { + return String.format("should not exceed a maximum of %d cards", max); + } + + switch(this) { + case Commander: //Must contain exactly 1 legendary Commander and no sideboard. + + //TODO:Enforce color identity + if (null == deck.getCommander()) { + return "is missing a commander"; + } + if (!deck.getCommander().getCard().getType().isLegendary()) { + return "has a commander that is not a legendary creature"; + } + + //No sideboarding in Commander + if (!deck.getSideboard().isEmpty()) { + return "has sideboard"; + } + break; + + case Planechase: //Must contain at least 10 planes/phenomenons, but max 2 phenomenons. Singleton. + if (deck.getSideboard().countAll() < 10) { + return "should gave at least 10 planes"; + } + int phenoms = 0; + for (Entry cp : deck.getSideboard()) { + + if (cp.getKey().getCard().getType().typeContains(CardCoreType.Phenomenon)) { + phenoms++; + } + if (cp.getValue() > 1) { + return "must not contain multiple copies of any Phenomena"; + } + + } + if (phenoms > 2) { + return "must not contain more than 2 Phenomena"; + } + break; + + case Archenemy: //Must contain at least 20 schemes, max 2 of each. + if (deck.getSideboard().countAll() < 20) { + return "must contain at least 20 schemes"; + } + + for (Entry cp : deck.getSideboard()) { + if (cp.getValue() > 2) { + return "must not contain more than 2 copies of any Scheme"; + } + } + break; + } + + int maxCopies = getMaxCardCopies(); + if (maxCopies < Integer.MAX_VALUE) { + //Must contain no more than 4 of the same card + //shared among the main deck and sideboard, except + //basic lands and Relentless Rats + + DeckSection tmp = new DeckSection(deck.getMain()); + tmp.addAll(deck.getSideboard()); + if (null != deck.getCommander() && this == Commander) { + tmp.add(deck.getCommander()); + } + + List limitExceptions = Arrays.asList("Relentless Rats"); + + // should group all cards by name, so that different editions of same card are really counted as the same card + for (Entry cp : Aggregates.groupSumBy(tmp, CardPrinted.FN_GET_NAME)) { + + CardPrinted simpleCard = CardDb.instance().getCard(cp.getKey()); + boolean canHaveMultiple = simpleCard.getCard().getType().isBasicLand() || limitExceptions.contains(cp.getKey()); + + if (!canHaveMultiple && cp.getValue() > maxCopies) { + return String.format("must not contain more than %d of '%s' card", maxCopies, cp.getKey()); + } + } + + // The sideboard must contain either 0 or 15 cards + int sideboardSize = deck.getSideboard().countAll(); + IntRange sbRange = getSideRange(); + if (sbRange != null && sideboardSize > 0 && !sbRange.containsInteger(sideboardSize)) { + return sbRange.getMinimumInteger() == sbRange.getMaximumInteger() + ? String.format("must have a sideboard of %d cards or no sideboard at all", sbRange.getMaximumInteger()) + : String.format("must have a sideboard of %d to %d cards or no sideboard at all", sbRange.getMinimumInteger(), sbRange.getMaximumInteger()); + } + + } + + return null; + } +} diff --git a/src/main/java/forge/deck/DeckSection.java b/src/main/java/forge/deck/DeckSection.java index d24a0cf9530..73b46ac2f1d 100644 --- a/src/main/java/forge/deck/DeckSection.java +++ b/src/main/java/forge/deck/DeckSection.java @@ -128,4 +128,33 @@ public class DeckSection extends ItemPool { this.add(CardDb.instance().getCard(cardName)); } + /** + * returns n-th card from this DeckSection. LINEAR time. + * @param i + * @return + */ + public CardPrinted get(int n) { + for(Entry e : this) + { + n -= e.getValue(); + if ( n <= 0 ) return e.getKey(); + } + return null; + } + + @Override + public String toString() { + if (this.isEmpty()) return "[]"; + + boolean isFirst = true; + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (Entry e : this) { + if ( isFirst ) isFirst = false; + else sb.append(", "); + + sb.append(e.getValue()).append(" x ").append(e.getKey().getName()); + } + return sb.append(']').toString(); + } } diff --git a/src/main/java/forge/deck/DeckgenUtil.java b/src/main/java/forge/deck/DeckgenUtil.java index d75c18ebc28..0d324624366 100644 --- a/src/main/java/forge/deck/DeckgenUtil.java +++ b/src/main/java/forge/deck/DeckgenUtil.java @@ -320,9 +320,9 @@ public class DeckgenUtil { int attemptsLeft = 100; // to avoid endless loop while (schemesToAdd > 0 && attemptsLeft > 0) { CardPrinted cp = Aggregates.random(allSchemes); - int appearances = res.getSchemes().count(cp) + 1; + int appearances = res.getSideboard().count(cp) + 1; if (appearances < 2) { - res.getSchemes().add(cp); + res.getSideboard().add(cp); schemesToAdd--; } else { attemptsLeft--; diff --git a/src/main/java/forge/deck/io/DeckFileHeader.java b/src/main/java/forge/deck/io/DeckFileHeader.java index d1efb6a086a..10be4a542fc 100644 --- a/src/main/java/forge/deck/io/DeckFileHeader.java +++ b/src/main/java/forge/deck/io/DeckFileHeader.java @@ -17,7 +17,7 @@ */ package forge.deck.io; -import forge.game.GameType; +import forge.deck.DeckFormat; import forge.game.player.PlayerType; import forge.util.FileSection; @@ -39,7 +39,7 @@ public class DeckFileHeader { private static final String CSTM_POOL = "Custom Pool"; private static final String PLAYER_TYPE = "PlayerType"; - private final GameType deckType; + private final DeckFormat deckType; private final PlayerType playerType; private final boolean customPool; @@ -55,11 +55,10 @@ public class DeckFileHeader { public DeckFileHeader(final FileSection kvPairs) { this.name = kvPairs.get(DeckFileHeader.NAME); this.comment = kvPairs.get(DeckFileHeader.COMMENT); - this.deckType = GameType.smartValueOf(kvPairs.get(DeckFileHeader.DECK_TYPE), GameType.Constructed); + this.deckType = DeckFormat.smartValueOf(kvPairs.get(DeckFileHeader.DECK_TYPE), DeckFormat.Constructed); this.customPool = kvPairs.getBoolean(DeckFileHeader.CSTM_POOL); - this.playerType = "computer".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER)) - || "ai".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER_TYPE)) ? PlayerType.COMPUTER - : PlayerType.HUMAN; + boolean isForAi = "computer".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER)) || "ai".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER_TYPE)); + this.playerType = isForAi ? PlayerType.COMPUTER : PlayerType.HUMAN; } /** @@ -103,7 +102,7 @@ public class DeckFileHeader { * * @return the deck type */ - public final GameType getDeckType() { + public final DeckFormat getDeckType() { return this.deckType; } diff --git a/src/main/java/forge/deck/io/OldDeckParser.java b/src/main/java/forge/deck/io/OldDeckParser.java index 5ef7c16904d..83ed9e46270 100644 --- a/src/main/java/forge/deck/io/OldDeckParser.java +++ b/src/main/java/forge/deck/io/OldDeckParser.java @@ -214,7 +214,7 @@ public class OldDeckParser { } break; - case Sealed: + case Limited: final boolean isAi = dh.getPlayerType() == PlayerType.COMPUTER; name = name.startsWith("AI_") ? name.replace("AI_", "") : name; diff --git a/src/main/java/forge/game/GameNew.java b/src/main/java/forge/game/GameNew.java index 4cb1523a753..4261b9699bd 100644 --- a/src/main/java/forge/game/GameNew.java +++ b/src/main/java/forge/game/GameNew.java @@ -138,12 +138,6 @@ public class GameNew { final Random generator = MyRandom.getRandom(); boolean useAnte = Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_ANTE); - if (!Singletons.getModel().getMatch().getPlayedGames().isEmpty()) { - deck.startDeckEdits(); - sideboard(player, deck, canRandomFoil, generator, useAnte); - } else { - deck.clearDeckEdits(); - } prepareGameLibrary(player, deck, removedAnteCards, rAICards, canRandomFoil, generator, useAnte); // Shuffling @@ -157,42 +151,54 @@ public class GameNew { } } - private static boolean sideboard(final Player player, final Deck deck, boolean canRandomFoil, Random generator, boolean useAnte) { + private static Deck sideboard(final Player player, final Deck deck) { final GameType gameType = Singletons.getModel().getMatch().getGameType(); - boolean hasSideboard = (deck.getSideboard().countAll() > 0); + boolean deckHasSideboard = (deck.getSideboard().countAll() > 0); DeckSection sideboard = deck.getSideboard(); - int sideboardSize = (gameType == GameType.Draft || gameType == GameType.Sealed) ? -1 : sideboard.countAll(); - if (!hasSideboard) { - return false; + + if (!deckHasSideboard || !gameType.isSideboardingAllowed()) { + return deck; } - if (player.isComputer()) { + if (player.isComputer()) // Here is where the AI could sideboard, but needs to gather hints during the first game about what to SB + return deck; - return false; - } else { - // Human Sideboarding - boolean validDeck = false; - int deckMinSize = Math.min(deck.getMain().countAll(), gameType.getMainRange().getMinimumInteger()); + // Human Sideboarding - while (!validDeck) { - GuiChoose.getOrderChoices("Sideboard", "Main Deck", sideboardSize, - deck.getSideboard().toForgeCardList(), deck.getMain().toForgeCardList(), null, true, deck); + int deckMinSize = Math.min(deck.getMain().countAll(), gameType.getDecksFormat().getMainRange().getMinimumInteger()); + //IntRange sbRange = gameType.getDecksFormat().getSideRange(); + int sideboardSize = sideboard.countAll(); - if (deck.getMain().countAll() >= deckMinSize) { - validDeck = true; - } else { - StringBuilder errMsg = new StringBuilder("Too few cards in your main deck (minimum "); - errMsg.append(deckMinSize); - errMsg.append("), please make modifications to your deck again."); - JOptionPane.showMessageDialog(null, errMsg.toString(), "Invalid deck", JOptionPane.ERROR_MESSAGE); - } + DeckSection newSb = new DeckSection(); + List newMain = null; + + + while (newMain == null || newMain.size() < deckMinSize) { + + if ( newMain != null ) { + String errMsg = String.format("Too few cards in your main deck (minimum %d), please make modifications to your deck again.", deckMinSize); + JOptionPane.showMessageDialog(null, errMsg, "Invalid deck", JOptionPane.ERROR_MESSAGE); } - + + newMain = GuiChoose.getOrderChoices("Sideboard", "Main Deck", sideboardSize, deck.getSideboard().toFlatList(), deck.getMain().toFlatList(), null, true); } - return true; + + newSb.clear(); + newSb.addAll(deck.getMain()); + newSb.addAll(deck.getSideboard()); + for(CardPrinted c : newMain) + newSb.remove(c); + + Deck res = (Deck) deck.copyTo(deck.getName()); + res.getMain().clear(); + res.getMain().add(newMain); + res.getSideboard().clear(); + res.getSideboard().addAll(newSb); + return res; + } /** @@ -252,7 +258,16 @@ public class GameNew { } - prepareSingleLibrary(player, p.getValue().getDeck(), removedAnteCards, rAICards, canRandomFoil); + Deck toUse; + boolean isFirstGame = Singletons.getModel().getMatch().getPlayedGames().isEmpty(); + if (!isFirstGame) { + toUse = sideboard(player, p.getValue().getCurrentDeck()); + } else { + p.getValue().restoreOriginalDeck(); + toUse = p.getValue().getCurrentDeck(); + } + + prepareSingleLibrary(player, toUse, removedAnteCards, rAICards, canRandomFoil); player.updateObservers(); bf.updateObservers(); player.getZone(ZoneType.Hand).updateObservers(); diff --git a/src/main/java/forge/game/GameType.java b/src/main/java/forge/game/GameType.java index f1cb9018e18..1026c748523 100644 --- a/src/main/java/forge/game/GameType.java +++ b/src/main/java/forge/game/GameType.java @@ -1,229 +1,51 @@ -/* - * Forge: Play Magic: the Gathering. - * Copyright (C) 2011 Forge Team - * - * This program is free software: you can redistribute it and/or modify - * 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.game; -import java.util.Arrays; -import java.util.List; -import java.util.Map.Entry; +import forge.deck.DeckFormat; -import org.apache.commons.lang.math.IntRange; - -import forge.card.CardCoreType; -import forge.deck.Deck; -import forge.deck.DeckSection; -import forge.item.CardDb; -import forge.item.CardPrinted; -import forge.util.Aggregates; - -/** - * GameType is an enum to determine the type of current game. :) +/** + * TODO: Write javadoc for this type. + * */ public enum GameType { - // Limited Main board: allowed size SB: allowed size Max distinct non basic cards - Constructed ( false, new IntRange(60, Integer.MAX_VALUE), new IntRange(15), 4), - Sealed ( true, new IntRange(40, Integer.MAX_VALUE), null, Integer.MAX_VALUE), - Draft ( true, new IntRange(40, Integer.MAX_VALUE), null, Integer.MAX_VALUE), - Commander ( false, new IntRange(99 /* +cmndr aside */), new IntRange(0), 1), - Quest ( true, new IntRange(40, Integer.MAX_VALUE), new IntRange(15), 4), - Vanguard ( false, new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4), - Planechase ( false, new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4), - Archenemy ( false, new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4), - Gauntlet ( true, new IntRange(40, Integer.MAX_VALUE), null, Integer.MAX_VALUE); + // deck composition rules, isPoolRestricted, can sideboard between matches + Sealed ( DeckFormat.Limited, true, true ), + Draft ( DeckFormat.Limited, true, true ), + Gauntlet ( DeckFormat.Limited, true, true ), + Quest ( DeckFormat.Constructed, true, true ), + Constructed ( DeckFormat.Constructed, false, true ), + Archenemy ( DeckFormat.Archenemy, false, false ), + Planechase ( DeckFormat.Planechase, false, false ), + Vanguard ( DeckFormat.Vanguard, true, true ); - private final boolean bLimited; - private final IntRange mainRange; - private final IntRange sideRange; // null => no check - private final int maxCardCopies; - - - /** - * Checks if is limited. - * - * @return true, if is limited - */ - public final boolean isLimited() { - return this.bLimited; - } - - - /** - * Instantiates a new game type. - * - * @param isLimited - * the is limited - */ - GameType(final boolean isLimited, IntRange main, IntRange side, int maxCopies) { - this.bLimited = isLimited; - mainRange = main; - sideRange = side; - maxCardCopies = maxCopies; + private final DeckFormat decksFormat; + private final boolean bCardpoolLimited; + private final boolean canSideboard; + + GameType(DeckFormat formatType, boolean isDeckBuilderLimited, boolean sideboardingAllowed ) { + bCardpoolLimited = isDeckBuilderLimited; + decksFormat = formatType; + canSideboard = sideboardingAllowed; } /** - * Smart value of. - * - * @param value the value - * @param defaultValue the default value - * @return the game type + * @return the decksFormat */ - public static GameType smartValueOf(final String value, GameType defaultValue) { - if (null == value) { - return defaultValue; - } - - final String valToCompate = value.trim(); - for (final GameType v : GameType.values()) { - if (v.name().compareToIgnoreCase(valToCompate) == 0) { - return v; - } - } - - throw new IllegalArgumentException("No element named " + value + " in enum GameType"); + public DeckFormat getDecksFormat() { + return decksFormat; } - /** - * @return the sideRange + * @return the isCardpoolLimited */ - public IntRange getSideRange() { - return sideRange; + public boolean isCardpoolLimited() { + return bCardpoolLimited; } - /** - * @return the mainRange + * @return the canSideboard */ - public IntRange getMainRange() { - return mainRange; - } - - - /** - * @return the maxCardCopies - */ - public int getMaxCardCopies() { - return maxCardCopies; - } - - - - @SuppressWarnings("incomplete-switch") - public String getDeckConformanceProblem(Deck deck) { - int deckSize = deck.getMain().countAll(); - - int min = getMainRange().getMinimumInteger(); - int max = getMainRange().getMaximumInteger(); - - if (deckSize < min) { - return String.format("should have a minimum of %d cards", min); - } - - if (deckSize > max) { - return String.format("should not exceed a maximum of %d cards", max); - } - - switch(this) { - case Commander: //Must contain exactly 1 legendary Commander and no sideboard. - - //TODO:Enforce color identity - if (null == deck.getCommander()) { - return "is missing a commander"; - } - if (!deck.getCommander().getCard().getType().isLegendary()) { - return "has a commander that is not a legendary creature"; - } - - //No sideboarding in Commander - if (!deck.getSideboard().isEmpty()) { - return "has sideboard"; - } - break; - - case Planechase: //Must contain at least 10 planes/phenomenons, but max 2 phenomenons. Singleton. - if (deck.getPlanes().countAll() < 10) { - return "should gave at least 10 planes"; - } - int phenoms = 0; - for (Entry cp : deck.getPlanes()) { - - if (cp.getKey().getCard().getType().typeContains(CardCoreType.Phenomenon)) { - phenoms++; - } - if (cp.getValue() > 1) { - return "must not contain multiple copies of any Phenomena"; - } - - } - if (phenoms > 2) { - return "must not contain more than 2 Phenomena"; - } - break; - - case Archenemy: //Must contain at least 20 schemes, max 2 of each. - if (deck.getSchemes().countAll() < 20) { - return "must contain at least 20 schemes"; - } - - for (Entry cp : deck.getSchemes()) { - if (cp.getValue() > 2) { - return "must not contain more than 2 copies of any Scheme"; - } - } - break; - } - - int maxCopies = getMaxCardCopies(); - if (maxCopies < Integer.MAX_VALUE) { - //Must contain no more than 4 of the same card - //shared among the main deck and sideboard, except - //basic lands and Relentless Rats - - DeckSection tmp = new DeckSection(deck.getMain()); - tmp.addAll(deck.getSideboard()); - if (null != deck.getCommander()) { - tmp.add(deck.getCommander()); - } - - List limitExceptions = Arrays.asList("Relentless Rats"); - - // should group all cards by name, so that different editions of same card are really counted as the same card - for (Entry cp : Aggregates.groupSumBy(tmp, CardPrinted.FN_GET_NAME)) { - - CardPrinted simpleCard = CardDb.instance().getCard(cp.getKey()); - boolean canHaveMultiple = simpleCard.getCard().getType().isBasicLand() || limitExceptions.contains(cp.getKey()); - - if (!canHaveMultiple && cp.getValue() > maxCopies) { - return String.format("must not contain more than %d of '%s' card", maxCopies, cp.getKey()); - } - } - - // The sideboard must contain either 0 or 15 cards - int sideboardSize = deck.getSideboard().countAll(); - IntRange sbRange = getSideRange(); - if (sbRange != null && sideboardSize > 0 && !sbRange.containsInteger(sideboardSize)) { - return sbRange.getMinimumInteger() == sbRange.getMaximumInteger() - ? String.format("must have a sideboard of %d cards or no sideboard at all", sbRange.getMaximumInteger()) - : String.format("must have a sideboard of %d to %d cards or no sideboard at all", sbRange.getMinimumInteger(), sbRange.getMaximumInteger()); - } - - } - - return null; + public boolean isSideboardingAllowed() { + return canSideboard; } } diff --git a/src/main/java/forge/game/MatchController.java b/src/main/java/forge/game/MatchController.java index 9807d76d7e7..6ba911bf9d2 100644 --- a/src/main/java/forge/game/MatchController.java +++ b/src/main/java/forge/game/MatchController.java @@ -257,9 +257,15 @@ public class MatchController { */ public Deck getPlayersDeck(LobbyPlayer lobbyPlayer) { PlayerStartConditions cond = players.get(lobbyPlayer); - return cond == null ? null : cond.getDeck(); + return cond == null ? null : cond.getCurrentDeck(); } + public Deck getPlayersOriginalDeck(LobbyPlayer lobbyPlayer) { + PlayerStartConditions cond = players.get(lobbyPlayer); + return cond == null ? null : cond.getOriginalDeck(); + } + + public Map getPlayers() { return players; } diff --git a/src/main/java/forge/game/PlayerStartConditions.java b/src/main/java/forge/game/PlayerStartConditions.java index 464f72714a2..fe01f8fa79b 100644 --- a/src/main/java/forge/game/PlayerStartConditions.java +++ b/src/main/java/forge/game/PlayerStartConditions.java @@ -7,7 +7,9 @@ import forge.deck.Deck; public class PlayerStartConditions { - private final Deck deck; + private final Deck originalDeck; + private Deck currentDeck; + private int startingLife = 20; private int startingHand = 7; private Supplier> cardsOnBattlefield = null; @@ -15,12 +17,18 @@ public class PlayerStartConditions { private Supplier> schemes = null; public PlayerStartConditions(Deck deck0) { - deck = deck0; + originalDeck = deck0; + currentDeck = originalDeck; } - public final Deck getDeck() { - return deck; + public final Deck getOriginalDeck() { + return originalDeck; } + + public final Deck getCurrentDeck() { + return currentDeck; + } + public final int getStartingLife() { return startingLife; } @@ -78,5 +86,12 @@ public class PlayerStartConditions { this.schemes = s; } + /** + * TODO: Write javadoc for this method. + */ + public void restoreOriginalDeck() { + currentDeck = originalDeck; + } + } diff --git a/src/main/java/forge/game/player/HumanPlayer.java b/src/main/java/forge/game/player/HumanPlayer.java index 7bfb69acbb7..c90424f6083 100644 --- a/src/main/java/forge/game/player/HumanPlayer.java +++ b/src/main/java/forge/game/player/HumanPlayer.java @@ -24,8 +24,8 @@ import forge.Card; import forge.Singletons; import forge.card.spellability.SpellAbility; import forge.control.input.Input; -import forge.game.GameState; import forge.game.GameType; +import forge.game.GameState; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; import forge.gui.match.CMatchUI; diff --git a/src/main/java/forge/gui/DualListBox.java b/src/main/java/forge/gui/DualListBox.java index 4ec99f44578..77903042499 100644 --- a/src/main/java/forge/gui/DualListBox.java +++ b/src/main/java/forge/gui/DualListBox.java @@ -23,6 +23,7 @@ import forge.gui.toolbox.FList; import forge.gui.toolbox.FPanel; import forge.gui.toolbox.FScrollPane; import forge.gui.toolbox.FSkin; +import forge.item.CardPrinted; // An input box for handling the order of choices. // Left box has the original choices @@ -168,6 +169,8 @@ public class DualListBox extends FPanel { card = (Card) obj; } else if (obj instanceof SpellAbility) { card = ((SpellAbility) obj).getSourceCard(); + } else if (obj instanceof CardPrinted) { + card = ((CardPrinted) obj).toForgeCard(); } GuiUtils.clearPanelSelections(); diff --git a/src/main/java/forge/gui/GuiChoose.java b/src/main/java/forge/gui/GuiChoose.java index 96ebceb1a1a..8fc12c274bd 100644 --- a/src/main/java/forge/gui/GuiChoose.java +++ b/src/main/java/forge/gui/GuiChoose.java @@ -13,7 +13,6 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import forge.Card; -import forge.deck.Deck; import forge.gui.match.CMatchUI; import forge.item.InventoryItem; @@ -205,11 +204,11 @@ public class GuiChoose { public static List getOrderChoices(final String title, final String top, int remainingObjects, final List sourceChoices, List destChoices, Card referenceCard) { - return getOrderChoices(title, top, remainingObjects, sourceChoices, destChoices, referenceCard, false, null); + return getOrderChoices(title, top, remainingObjects, sourceChoices, destChoices, referenceCard, false); } public static List getOrderChoices(final String title, final String top, int remainingObjects, - final List sourceChoices, List destChoices, Card referenceCard, boolean sideboardingMode, Deck persistentDeck) { + final List sourceChoices, List destChoices, Card referenceCard, boolean sideboardingMode) { // An input box for handling the order of choices. final JFrame frame = new JFrame(); DualListBox dual = new DualListBox(remainingObjects, top, sourceChoices, destChoices, referenceCard, sideboardingMode); @@ -235,13 +234,6 @@ public class GuiChoose { List objects = dual.getOrderedList(); - if (sideboardingMode) { - persistentDeck.getMain().clear(); - persistentDeck.getMain().add((List) dual.getOrderedList()); - persistentDeck.getSideboard().clear(); - persistentDeck.getSideboard().add((List) dual.getRemainingSourceList()); - } - dialog.dispose(); GuiUtils.clearPanelSelections(); return objects; diff --git a/src/main/java/forge/gui/deckeditor/controllers/CEditorScheme.java b/src/main/java/forge/gui/deckeditor/controllers/CEditorScheme.java index f227356ab58..a19daa14db3 100644 --- a/src/main/java/forge/gui/deckeditor/controllers/CEditorScheme.java +++ b/src/main/java/forge/gui/deckeditor/controllers/CEditorScheme.java @@ -126,7 +126,7 @@ public final class CEditorScheme extends ACEditorBase { schemes.add(cp); } this.getTableCatalog().setDeck(ItemPool.createFrom(schemes, CardPrinted.class)); - this.getTableDeck().setDeck(this.controller.getModel().getSchemes()); + this.getTableDeck().setDeck(this.controller.getModel().getSideboard()); } /* diff --git a/src/main/java/forge/gui/home/quest/SSubmenuQuestUtil.java b/src/main/java/forge/gui/home/quest/SSubmenuQuestUtil.java index 99a93a8718f..c4073d3d329 100644 --- a/src/main/java/forge/gui/home/quest/SSubmenuQuestUtil.java +++ b/src/main/java/forge/gui/home/quest/SSubmenuQuestUtil.java @@ -337,7 +337,7 @@ public class SSubmenuQuestUtil { System.out.println(msg); return; } - String errorMessage = GameType.Quest.getDeckConformanceProblem(deck); + String errorMessage = GameType.Quest.getDecksFormat().getDeckConformanceProblem(deck); if (null != errorMessage) { JOptionPane.showMessageDialog(null, "Your deck " + errorMessage + " Please edit or choose a different deck.", "Invalid deck", JOptionPane.ERROR_MESSAGE); return; diff --git a/src/main/java/forge/gui/home/sanctioned/CSubmenuConstructed.java b/src/main/java/forge/gui/home/sanctioned/CSubmenuConstructed.java index 5a94b65e0d2..0767fa952b5 100644 --- a/src/main/java/forge/gui/home/sanctioned/CSubmenuConstructed.java +++ b/src/main/java/forge/gui/home/sanctioned/CSubmenuConstructed.java @@ -11,6 +11,7 @@ import forge.Command; import forge.Singletons; import forge.control.Lobby; import forge.deck.Deck; +import forge.deck.DeckFormat; import forge.game.GameType; import forge.game.MatchController; import forge.game.MatchStartHelper; @@ -98,7 +99,7 @@ public enum CSubmenuConstructed implements ICDoc { Deck humanDeck = VSubmenuConstructed.SINGLETON_INSTANCE.getDcHuman().getDeck(); if (Singletons.getModel().getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY)) { - String errorMessage = GameType.Constructed.getDeckConformanceProblem(humanDeck); + String errorMessage = DeckFormat.Constructed.getDeckConformanceProblem(humanDeck); if (null != errorMessage) { JOptionPane.showMessageDialog(null, "Your deck " + errorMessage, "Invalid deck", JOptionPane.ERROR_MESSAGE); return; diff --git a/src/main/java/forge/gui/home/sanctioned/CSubmenuDraft.java b/src/main/java/forge/gui/home/sanctioned/CSubmenuDraft.java index 550a693932b..cd29a2ed82e 100644 --- a/src/main/java/forge/gui/home/sanctioned/CSubmenuDraft.java +++ b/src/main/java/forge/gui/home/sanctioned/CSubmenuDraft.java @@ -14,6 +14,7 @@ import forge.Singletons; import forge.control.FControl; import forge.control.Lobby; import forge.deck.Deck; +import forge.deck.DeckFormat; import forge.deck.DeckGroup; import forge.game.GameType; import forge.game.MatchController; @@ -100,7 +101,7 @@ public enum CSubmenuDraft implements ICDoc { "No deck selected for human!\r\n(You may need to build a new deck.)", "No deck", JOptionPane.ERROR_MESSAGE); return; - } else if (null != GameType.Draft.getDeckConformanceProblem(humanDeck)) { + } else if (null != DeckFormat.Limited.getDeckConformanceProblem(humanDeck)) { JOptionPane.showMessageDialog(null, "The selected deck doesn't have enough cards to play (minimum 40)." + "\r\nUse the deck editor to choose the cards you want before starting.", diff --git a/src/main/java/forge/gui/home/sanctioned/CSubmenuSealed.java b/src/main/java/forge/gui/home/sanctioned/CSubmenuSealed.java index eead0f5ceb3..57c0cb114f3 100644 --- a/src/main/java/forge/gui/home/sanctioned/CSubmenuSealed.java +++ b/src/main/java/forge/gui/home/sanctioned/CSubmenuSealed.java @@ -19,6 +19,7 @@ import forge.Singletons; import forge.control.FControl; import forge.deck.Deck; import forge.deck.DeckBase; +import forge.deck.DeckFormat; import forge.deck.DeckGroup; import forge.game.limited.ReadDraftRankings; import forge.game.GameType; @@ -112,7 +113,7 @@ public enum CSubmenuSealed implements ICDoc { "Please build and/or select a deck for yourself.", "No deck", JOptionPane.ERROR_MESSAGE); return; - } else if (null != GameType.Sealed.getDeckConformanceProblem(human)) { + } else if (null != DeckFormat.Limited.getDeckConformanceProblem(human)) { JOptionPane.showMessageDialog(null, "The selected deck doesn't have enough cards to play (minimum 40)." + "\r\nUse the deck editor to choose the cards you want before starting.", @@ -125,7 +126,6 @@ public enum CSubmenuSealed implements ICDoc { Singletons.getModel().getGauntletMini().launch(matches, human, GameType.Sealed); } - /** */ @SuppressWarnings("unchecked") private void setupSealed() { diff --git a/src/main/java/forge/gui/home/variant/CSubmenuArchenemy.java b/src/main/java/forge/gui/home/variant/CSubmenuArchenemy.java index 0c8de763353..5cd063e39a5 100644 --- a/src/main/java/forge/gui/home/variant/CSubmenuArchenemy.java +++ b/src/main/java/forge/gui/home/variant/CSubmenuArchenemy.java @@ -4,13 +4,9 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; -import java.util.Random; - import javax.swing.SwingUtilities; import javax.swing.SwingWorker; -import com.google.common.collect.Iterables; - import forge.Command; import forge.GameActionUtil; import forge.Singletons; @@ -31,6 +27,7 @@ import forge.gui.toolbox.FDeckChooser; import forge.item.CardPrinted; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; +import forge.util.Aggregates; /** * Controls the constructed submenu in the home UI. @@ -42,7 +39,7 @@ public enum CSubmenuArchenemy implements ICDoc { /** */ SINGLETON_INSTANCE; private final VSubmenuArchenemy view = VSubmenuArchenemy.SINGLETON_INSTANCE; - + /* (non-Javadoc) * @see forge.gui.home.ICSubmenu#initialize() @@ -127,8 +124,6 @@ public enum CSubmenuArchenemy implements ICDoc { final SwingWorker worker = new SwingWorker() { @Override public Object doInBackground() { - Random rnd = new Random(); - String nl = System.getProperty("line.separator"); boolean usedDefaults = false; List playerDecks = new ArrayList(); @@ -147,12 +142,12 @@ public enum CSubmenuArchenemy implements ICDoc { Object obj = view.getArchenemySchemes().getSelectedValue(); boolean useDefault = VSubmenuArchenemy.SINGLETON_INSTANCE.getCbUseDefaultSchemes().isSelected(); - useDefault &= !playerDecks.get(0).getSchemes().isEmpty(); + useDefault &= !playerDecks.get(0).getSideboard().isEmpty(); System.out.println(useDefault); if (useDefault) { - schemes = playerDecks.get(0).getSchemes().toFlatList(); + schemes = playerDecks.get(0).getSideboard().toFlatList(); System.out.println(schemes.toString()); usedDefaults = true; @@ -162,14 +157,14 @@ public enum CSubmenuArchenemy implements ICDoc { String sel = (String) obj; if (sel.equals("Random")) { - schemes = Iterables.get(view.getAllSchemeDecks(), rnd.nextInt(Iterables.size(view.getAllSchemeDecks()))).getSchemes().toFlatList(); + schemes = Aggregates.random(view.getAllSchemeDecks()).getSideboard().toFlatList(); } else { //Generate - schemes = DeckgenUtil.generateSchemeDeck().getSchemes().toFlatList(); + schemes = DeckgenUtil.generateSchemeDeck().getSideboard().toFlatList(); } } else { - schemes = ((Deck) obj).getSchemes().toFlatList(); + schemes = ((Deck) obj).getSideboard().toFlatList(); } } if (schemes == null) { diff --git a/src/main/java/forge/gui/match/ControlWinLose.java b/src/main/java/forge/gui/match/ControlWinLose.java index ac793360dd1..6a64d1e3144 100644 --- a/src/main/java/forge/gui/match/ControlWinLose.java +++ b/src/main/java/forge/gui/match/ControlWinLose.java @@ -11,8 +11,8 @@ import forge.Card; import forge.Singletons; import forge.control.FControl; import forge.deck.Deck; -import forge.game.GameOutcome; import forge.game.GameType; +import forge.game.GameOutcome; import forge.game.MatchController; import forge.game.player.Player; import forge.game.zone.ZoneType; @@ -133,10 +133,13 @@ public class ControlWinLose { List compAntes = new ArrayList(loser.getCardsIn(ZoneType.Ante)); Deck cDeck = match.getPlayersDeck(loser.getLobbyPlayer()); + Deck oDeck = match.getPlayersOriginalDeck(loser.getLobbyPlayer()); for (Card c : compAntes) { CardPrinted toRemove = CardDb.instance().getCard(c); cDeck.getMain().remove(toRemove); + if ( cDeck != oDeck ) + oDeck.getMain().remove(toRemove); } } diff --git a/src/main/java/forge/gui/match/QuestWinLose.java b/src/main/java/forge/gui/match/QuestWinLose.java index d3bf19d9e63..3b44d079dfd 100644 --- a/src/main/java/forge/gui/match/QuestWinLose.java +++ b/src/main/java/forge/gui/match/QuestWinLose.java @@ -119,10 +119,6 @@ public class QuestWinLose extends ControlWinLose { qData.getCards().resetNewList(); QuestController qc = Singletons.getModel().getQuest(); - if (match.isMatchOver()) { - restoreQuestDeckEdits(); - } - LobbyPlayer questPlayer = Singletons.getControl().getLobby().getQuestPlayer(); if (isAnte) { //do per-game actions @@ -246,18 +242,6 @@ public class QuestWinLose extends ControlWinLose { new QuestWinLoseCardViewer(antesWon), QuestWinLose.CONSTRAINTS_CARDS); } - /** - *

- * restoreQuestDeckEdits - *

- * Reverts the persistent sideboard changes in quest decks. - */ - private void restoreQuestDeckEdits() { - for (LobbyPlayer p : Singletons.getModel().getMatch().getPlayers().keySet()) { - Singletons.getModel().getMatch().getPlayersDeck(p).clearDeckEdits(); - } - } - /** *

* actionOnQuit. diff --git a/src/main/java/forge/item/ItemPool.java b/src/main/java/forge/item/ItemPool.java index 3a90bf2e643..937fbdcea2d 100644 --- a/src/main/java/forge/item/ItemPool.java +++ b/src/main/java/forge/item/ItemPool.java @@ -187,8 +187,8 @@ public class ItemPool extends ItemPoolView { * @param card * a T */ - public void remove(final T card) { - this.remove(card, 1); + public boolean remove(final T card) { + return this.remove(card, 1); } /** @@ -200,10 +200,10 @@ public class ItemPool extends ItemPoolView { * @param amount * a int */ - public void remove(final T card, final int amount) { + public boolean remove(final T card, final int amount) { final int count = this.count(card); if ((count == 0) || (amount <= 0)) { - return; + return false; } if (count <= amount) { this.getCards().remove(card); @@ -211,6 +211,7 @@ public class ItemPool extends ItemPoolView { this.getCards().put(card, count - amount); } this.setListInSync(false); + return true; } /** diff --git a/src/main/java/forge/quest/QuestUtilCards.java b/src/main/java/forge/quest/QuestUtilCards.java index a87c9fbab4e..65b78433c5c 100644 --- a/src/main/java/forge/quest/QuestUtilCards.java +++ b/src/main/java/forge/quest/QuestUtilCards.java @@ -336,7 +336,6 @@ public final class QuestUtilCards { final int leftInPool = this.qa.getCardPool().count(card); // remove sold cards from all decks: for (final Deck deck : this.qc.getMyDecks()) { - deck.clearDeckEdits(); deck.getMain().remove(card, deck.getMain().count(card) - leftInPool); } } diff --git a/src/main/java/forge/quest/io/QuestDataIO.java b/src/main/java/forge/quest/io/QuestDataIO.java index dfb5315b680..c3facf0fffc 100644 --- a/src/main/java/forge/quest/io/QuestDataIO.java +++ b/src/main/java/forge/quest/io/QuestDataIO.java @@ -57,7 +57,6 @@ import forge.Singletons; import forge.card.CardEdition; import forge.deck.DeckSection; import forge.error.ErrorViewer; -import forge.game.GameType; import forge.quest.data.GameFormatQuest; import forge.item.BoosterPack; import forge.item.CardDb; @@ -99,7 +98,6 @@ public class QuestDataIO { final XStream xStream = isIgnoring ? new IgnoringXStream() : new XStream(); xStream.registerConverter(new ItemPoolToXml()); xStream.registerConverter(new DeckSectionToXml()); - xStream.registerConverter(new GameTypeToXml()); xStream.registerConverter(new GameFormatQuestToXml()); xStream.registerConverter(new QuestModeToXml()); xStream.autodetectAnnotations(true); @@ -447,25 +445,6 @@ public class QuestDataIO { } } - private static class GameTypeToXml implements Converter { - @SuppressWarnings("rawtypes") - @Override - public boolean canConvert(final Class clasz) { - return clasz.equals(GameType.class); - } - - @Override - public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) { - // not used - } - - @Override - public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) { - final String value = reader.getValue(); - return GameType.smartValueOf(value, GameType.Quest); - } - } - private static class QuestModeToXml implements Converter { @SuppressWarnings("rawtypes") @Override diff --git a/src/main/java/forge/util/FileSection.java b/src/main/java/forge/util/FileSection.java index 6cbb800a810..9da9d84d6b3 100644 --- a/src/main/java/forge/util/FileSection.java +++ b/src/main/java/forge/util/FileSection.java @@ -156,7 +156,7 @@ public class FileSection { */ @SuppressWarnings("unchecked") public static Map> parseSections(final List source) { - final Map> result = new HashMap>(); + final Map> result = new TreeMap>(String.CASE_INSENSITIVE_ORDER); String currentSection = ""; List currentList = null;