From e04b64f7be33330d20f44869ba45b812a9ffd800 Mon Sep 17 00:00:00 2001
From: Sol
Date: Thu, 5 Jun 2014 02:39:48 +0000
Subject: [PATCH] - Initial checkin for Winston Draft mode. The menu item for
Winston Draft is currently commented out, but it should be functional even
though the AI is randomnly taking piles based on pile size.
---
.gitattributes | 5 +
.../src/main/java/forge/game/GameType.java | 1 +
.../main/java/forge/gui/framework/EDocID.java | 2 +
.../java/forge/itemmanager/DeckManager.java | 4 +
.../controllers/CEditorWinstonProcess.java | 394 ++++++++++++++++++
.../java/forge/screens/home/EMenuItem.java | 1 +
.../main/java/forge/screens/home/VHomeUI.java | 2 +
.../home/sanctioned/CSubmenuDraft.java | 2 +-
.../home/sanctioned/CSubmenuWinston.java | 162 +++++++
.../home/sanctioned/VSubmenuWinston.java | 177 ++++++++
.../src/test/java/forge/BoosterDraftTest.java | 5 +
.../src/main/java/forge/deck/DeckProxy.java | 9 +
.../forge/itemmanager/ItemManagerConfig.java | 2 +
.../main/java/forge/limited/BoosterDraft.java | 64 +--
.../java/forge/limited/BoosterDraftAI.java | 8 +-
.../main/java/forge/limited/DeckColors.java | 10 +
.../java/forge/limited/IBoosterDraft.java | 2 +
.../main/java/forge/limited/WinstonDraft.java | 178 ++++++++
.../java/forge/limited/WinstonDraftAI.java | 114 +++++
.../java/forge/model/CardCollections.java | 7 +-
.../java/forge/properties/ForgeConstants.java | 1 +
21 files changed, 1117 insertions(+), 33 deletions(-)
create mode 100644 forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorWinstonProcess.java
create mode 100644 forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuWinston.java
create mode 100644 forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuWinston.java
create mode 100644 forge-gui/src/main/java/forge/limited/WinstonDraft.java
create mode 100644 forge-gui/src/main/java/forge/limited/WinstonDraftAI.java
diff --git a/.gitattributes b/.gitattributes
index 70d86008c4f..e1133c8ec6a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -826,6 +826,7 @@ forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQues
forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestDraftingProcess.java -text
forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestLimited.java -text
forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorVariant.java -text
+forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorWinstonProcess.java -text
forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CProbabilities.java -text
forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CStatistics.java -text
forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/DeckController.java -text
@@ -886,10 +887,12 @@ forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/AvatarSelector.jav
forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuConstructed.java -text
forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuDraft.java -text
forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuSealed.java -text
+forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuWinston.java -text
forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/ConstructedGameMenu.java -text
forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuConstructed.java -text
forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuDraft.java -text
forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuSealed.java -text
+forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuWinston.java -text
forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/package-info.java -text
forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuAvatars.java -text
forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuDownloaders.java -text
@@ -16407,6 +16410,8 @@ forge-gui/src/main/java/forge/limited/LimitedPoolType.java -text
forge-gui/src/main/java/forge/limited/ReadDraftRankings.java -text
forge-gui/src/main/java/forge/limited/SealedCardPoolGenerator.java svneol=native#text/plain
forge-gui/src/main/java/forge/limited/SealedDeckBuilder.java svneol=native#text/plain
+forge-gui/src/main/java/forge/limited/WinstonDraft.java -text
+forge-gui/src/main/java/forge/limited/WinstonDraftAI.java -text
forge-gui/src/main/java/forge/limited/package-info.java svneol=native#text/plain
forge-gui/src/main/java/forge/match/MatchConstants.java -text
forge-gui/src/main/java/forge/match/input/ButtonUtil.java -text
diff --git a/forge-game/src/main/java/forge/game/GameType.java b/forge-game/src/main/java/forge/game/GameType.java
index 203a082f1f0..3186b2c9283 100644
--- a/forge-game/src/main/java/forge/game/GameType.java
+++ b/forge-game/src/main/java/forge/game/GameType.java
@@ -11,6 +11,7 @@ public enum GameType {
// deck composition rules, isPoolRestricted, can sideboard between matches
Sealed (DeckFormat.Limited, true, true, true, "Sealed"),
Draft (DeckFormat.Limited, true, true, true, "Draft"),
+ Winston (DeckFormat.Limited, true, true, true, "Winston"),
Gauntlet (DeckFormat.Limited, true, true, true, "Gauntlet"),
Quest (DeckFormat.QuestDeck, true, true, false, "Quest"),
QuestDraft (DeckFormat.Limited, true, true, true, "Quest Draft"),
diff --git a/forge-gui-desktop/src/main/java/forge/gui/framework/EDocID.java b/forge-gui-desktop/src/main/java/forge/gui/framework/EDocID.java
index 987e78bc41f..f8371e0fff7 100644
--- a/forge-gui-desktop/src/main/java/forge/gui/framework/EDocID.java
+++ b/forge-gui-desktop/src/main/java/forge/gui/framework/EDocID.java
@@ -12,6 +12,7 @@ import forge.screens.home.quest.*;
import forge.screens.home.sanctioned.VSubmenuConstructed;
import forge.screens.home.sanctioned.VSubmenuDraft;
import forge.screens.home.sanctioned.VSubmenuSealed;
+import forge.screens.home.sanctioned.VSubmenuWinston;
import forge.screens.home.settings.VSubmenuAvatars;
import forge.screens.home.settings.VSubmenuDownloaders;
import forge.screens.home.settings.VSubmenuPreferences;
@@ -59,6 +60,7 @@ public enum EDocID { /** */
HOME_CONSTRUCTED (VSubmenuConstructed.SINGLETON_INSTANCE), /** */
HOME_DRAFT (VSubmenuDraft.SINGLETON_INSTANCE), /** */
HOME_SEALED (VSubmenuSealed.SINGLETON_INSTANCE), /** */
+ HOME_WINSTON (VSubmenuWinston.SINGLETON_INSTANCE), /** */
HOME_RELEASE_NOTES (VSubmenuReleaseNotes.SINGLETON_INSTANCE),
REPORT_MESSAGE (VPrompt.SINGLETON_INSTANCE), /** */
diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/DeckManager.java b/forge-gui-desktop/src/main/java/forge/itemmanager/DeckManager.java
index c5978b4065f..6cb6470eb40 100644
--- a/forge-gui-desktop/src/main/java/forge/itemmanager/DeckManager.java
+++ b/forge-gui-desktop/src/main/java/forge/itemmanager/DeckManager.java
@@ -237,6 +237,10 @@ public final class DeckManager extends ItemManager {
screen = FScreen.DECK_EDITOR_DRAFT;
editorCtrl = new CEditorLimited(FModel.getDecks().getDraft(), screen);
break;
+ case Winston:
+ screen = FScreen.DECK_EDITOR_DRAFT;
+ editorCtrl = new CEditorLimited(FModel.getDecks().getWinston(), screen);
+ break;
default:
return;
diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorWinstonProcess.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorWinstonProcess.java
new file mode 100644
index 00000000000..2e7fd713ec3
--- /dev/null
+++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorWinstonProcess.java
@@ -0,0 +1,394 @@
+/*
+ * 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.screens.deckeditor.controllers;
+
+import forge.Singletons;
+import forge.UiCommand;
+import forge.card.MagicColor;
+import forge.deck.CardPool;
+import forge.deck.Deck;
+import forge.deck.DeckGroup;
+import forge.deck.DeckSection;
+import forge.model.FModel;
+import forge.screens.deckeditor.CDeckEditorUI;
+import forge.screens.deckeditor.views.VAllDecks;
+import forge.screens.deckeditor.views.VCurrentDeck;
+import forge.screens.deckeditor.views.VDeckgen;
+import forge.gui.framework.DragCell;
+import forge.gui.framework.FScreen;
+import forge.screens.home.sanctioned.CSubmenuWinston;
+import forge.toolbox.FOptionPane;
+import forge.itemmanager.CardManager;
+import forge.itemmanager.ItemManagerConfig;
+import forge.item.PaperCard;
+import forge.limited.BoosterDraft;
+import forge.limited.IBoosterDraft;
+import forge.limited.WinstonDraft;
+import forge.properties.ForgePreferences.FPref;
+import forge.util.ItemPool;
+import forge.util.MyRandom;
+
+import java.util.Map.Entry;
+
+/**
+ * Updates the deck editor UI as necessary draft selection mode.
+ *
+ *
(C at beginning of class name denotes a control class.)
+ *
+ * @author Forge
+ * @version $Id: CEditorDraftingProcess.java 24872 2014-02-17 07:35:47Z drdev $
+ */
+public class CEditorWinstonProcess extends ACEditorBase {
+ private IBoosterDraft boosterDraft;
+
+ private String ccAddLabel = "Add card";
+ private String ccAdd4Label = "Add card";
+ private Runnable ccAddCommand = null;
+ private Runnable ccAdd4Command = null;
+
+ private String ccTakeLabel = "Take pile";
+ private String ccPassLabel = "Pass pile";
+
+ private DragCell allDecksParent = null;
+ private DragCell deckGenParent = null;
+ private boolean saved = false;
+
+ //========== Constructor
+
+ /**
+ * Updates the deck editor UI as necessary draft selection mode.
+ */
+ public CEditorWinstonProcess() {
+ super(FScreen.DRAFTING_PROCESS);
+
+ final CardManager catalogManager = new CardManager(false);
+ final CardManager deckManager = new CardManager(false);
+
+ //hide filters and options panel so more of pack is visible by default
+ catalogManager.setHideViewOptions(1, true);
+
+ deckManager.setCaption("Draft Picks");
+
+ catalogManager.setAlwaysNonUnique(true);
+ deckManager.setAlwaysNonUnique(true);
+
+ this.setCatalogManager(catalogManager);
+ this.setDeckManager(deckManager);
+ }
+
+ /**
+ * Show gui.
+ *
+ * @param inBoosterDraft
+ * the in_booster draft
+ */
+ public final void showGui(final IBoosterDraft inBoosterDraft) {
+ this.boosterDraft = inBoosterDraft;
+ }
+
+ /* (non-Javadoc)
+ * @see forge.gui.deckeditor.ACEditorBase#onAddItems()
+ */
+ @Override
+ protected void onAddItems(Iterable> items, boolean toAlternate) {
+ // This doesn't actually do anything, need to use buttons to interact
+ }
+
+ /* (non-Javadoc)
+ * @see forge.gui.deckeditor.ACEditorBase#onRemoveItems()
+ */
+ @Override
+ protected void onRemoveItems(Iterable> items, boolean toAlternate) {
+ }
+
+ @Override
+ protected void buildAddContextMenu(EditorContextMenuBuilder cmb) {
+ cmb.addMoveItems("Draft", null);
+ }
+
+ @Override
+ protected void buildRemoveContextMenu(EditorContextMenuBuilder cmb) {
+ // no valid remove options
+ }
+
+ /**
+ *
+ * showChoices.
+ *
+ *
+ * @param list
+ * a {@link ItemPool} object.
+ */
+ private void showChoices(final ItemPool list) {
+ int packNumber = ((BoosterDraft) boosterDraft).getCurrentBoosterIndex() + 1;
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("Remaining: ");
+ sb.append(((WinstonDraft)boosterDraft).getDeckSize());
+ sb.append(" AI Cards: ");
+ sb.append(((WinstonDraft)boosterDraft).getAIDraftSize());
+ sb.append(" Pile");
+ sb.append(" ");
+ sb.append(packNumber);
+ sb.append(" - Cards");
+
+ this.getCatalogManager().setCaption(sb.toString());
+ this.getCatalogManager().setPool(list);
+
+ this.getDeckManager().refresh();
+ } // showChoices()
+
+ /**
+ *
+ * getPlayersDeck.
+ *
+ *
+ * @return a {@link forge.deck.Deck} object.
+ */
+ private Deck getPlayersDeck() {
+ final Deck deck = new Deck();
+
+ // add sideboard to deck
+ deck.getOrCreate(DeckSection.Sideboard).addAll(this.getDeckManager().getPool());
+
+ final String landSet = IBoosterDraft.LAND_SET_CODE[0].getCode();
+ final boolean isZendikarSet = landSet.equals("ZEN"); // we want to generate one kind of Zendikar lands at a time only
+ final boolean zendikarSetMode = MyRandom.getRandom().nextBoolean();
+
+ final int landsCount = 10;
+
+ for(String landName : MagicColor.Constant.BASIC_LANDS) {
+ int numArt = FModel.getMagicDb().getCommonCards().getArtCount(landName, landSet);
+ int minArtIndex = isZendikarSet ? (zendikarSetMode ? 1 : 5) : 1;
+ int maxArtIndex = isZendikarSet ? minArtIndex + 3 : numArt;
+
+ if (FModel.getPreferences().getPrefBoolean(FPref.UI_RANDOM_ART_IN_POOLS)) {
+
+ for (int i = minArtIndex; i <= maxArtIndex; i++) {
+ deck.get(DeckSection.Sideboard).add(landName, landSet, i, numArt > 1 ? landsCount : 30);
+ }
+ } else {
+ deck.get(DeckSection.Sideboard).add(landName, landSet, 30);
+ }
+ }
+
+ return deck;
+ } // getPlayersDeck()
+
+ /**
+ *
+ * saveDraft.
+ *
+ */
+ private void saveDraft() {
+ String s = FOptionPane.showInputDialog("Save this draft as:", "Save Draft", FOptionPane.QUESTION_ICON);
+
+ // Cancel button will be null; OK will return string.
+ // Must check for null value first, then string length.
+ // Recurse, if either null or empty string.
+ if (s == null || s.length() == 0) {
+ saveDraft();
+ return;
+ }
+
+ // Check for overwrite case
+ for (DeckGroup d : FModel.getDecks().getWinston()) {
+ if (s.equalsIgnoreCase(d.getName())) {
+ if (!FOptionPane.showConfirmDialog(
+ "There is already a deck named '" + s + "'. Overwrite?",
+ "Overwrite Deck?", false)) {
+ // If no overwrite, recurse.
+ saveDraft();
+ return;
+ }
+ break;
+ }
+ }
+
+ saved = true;
+
+ // TODO For pile drafts, only one other draft deck is made
+
+ // Construct computer's decks and save draft
+ final Deck[] computer = this.boosterDraft.getDecks();
+
+ final DeckGroup finishedDraft = new DeckGroup(s);
+ finishedDraft.setHumanDeck((Deck) this.getPlayersDeck().copyTo(s));
+ finishedDraft.addAiDecks(computer);
+
+ FModel.getDecks().getWinston().add(finishedDraft);
+ CSubmenuWinston.SINGLETON_INSTANCE.update();
+ FScreen.DRAFTING_PROCESS.close();
+
+ //open draft pool in Draft Deck Editor right away
+ Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_DRAFT);
+ CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(new CEditorLimited(FModel.getDecks().getWinston(), FScreen.DECK_EDITOR_DRAFT));
+ CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().getDeckController().load(null, s);
+ }
+
+ //========== Overridden from ACEditorBase
+
+ @Override
+ protected CardLimit getCardLimit() {
+ return CardLimit.None;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see forge.gui.deckeditor.ACEditorBase#getController()
+ */
+ @Override
+ public DeckController getDeckController() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see forge.gui.deckeditor.ACEditorBase#updateView()
+ */
+ @Override
+ public void resetTables() {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see forge.gui.deckeditor.ACEditorBase#show(forge.Command)
+ */
+ @Override
+ public void update() {
+ this.getCatalogManager().setup(ItemManagerConfig.DRAFT_PACK);
+ this.getDeckManager().setup(ItemManagerConfig.DRAFT_POOL);
+
+ ccAddLabel = this.getBtnAdd().getText();
+
+ if (this.getDeckManager().getPool() == null) { //avoid showing next choice or resetting pool if just switching back to Draft screen
+ this.getDeckManager().setPool((Iterable) null);
+ this.showChoices(this.boosterDraft.nextChoice());
+ }
+ else {
+ this.showChoices(this.getCatalogManager().getPool());
+ }
+
+ this.getBtnRemove().setVisible(false);
+ this.getBtnRemove4().setVisible(false);
+
+ this.getBtnAdd().setText(ccTakeLabel);
+ this.getBtnAdd4().setText(ccPassLabel);
+ // Link the buttons to the appropriate functions
+
+ this.ccAddCommand = this.getBtnAdd().getCommand();
+ this.ccAdd4Command = this.getBtnAdd4().getCommand();
+
+ this.getBtnAdd().setCommand(new UiCommand() {
+ @Override
+ public void run() {
+ CEditorWinstonProcess.this.takePile();
+ }
+ });
+ this.getBtnAdd4().setCommand(new UiCommand() {
+ @Override
+ public void run() {
+ CEditorWinstonProcess.this.passPile();
+ }
+ });
+
+ deckGenParent = removeTab(VDeckgen.SINGLETON_INSTANCE);
+ allDecksParent = removeTab(VAllDecks.SINGLETON_INSTANCE);
+
+ // set catalog table to single-selection only mode
+ //getCatalogManager().setAllowMultipleSelections(false);
+ }
+
+ /* (non-Javadoc)
+ * @see forge.gui.deckeditor.controllers.ACEditorBase#canSwitchAway()
+ */
+ @Override
+ public boolean canSwitchAway(boolean isClosing) {
+ if (isClosing && !saved) {
+ String userPrompt =
+ "This will end the current draft and you will not be able to resume.\n\n" +
+ "Leave anyway?";
+ return FOptionPane.showConfirmDialog(userPrompt, "Leave Draft?", "Leave", "Cancel", false);
+ }
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see forge.gui.deckeditor.controllers.ACEditorBase#resetUIChanges()
+ */
+ @Override
+ public void resetUIChanges() {
+ //Restore button names
+ this.getBtnAdd().setText(ccAddLabel);
+ this.getBtnAdd4().setText(ccAdd4Label);
+ this.getBtnAdd().setCommand(this.ccAddCommand);
+ this.getBtnAdd4().setCommand(this.ccAdd4Command);
+
+ //Re-add buttons
+ this.getBtnRemove().setVisible(true);
+ this.getBtnRemove4().setVisible(true);
+
+ VCurrentDeck.SINGLETON_INSTANCE.getPnlHeader().setVisible(true);
+
+ //Re-add tabs
+ if (deckGenParent != null) {
+ deckGenParent.addDoc(VDeckgen.SINGLETON_INSTANCE);
+ }
+ if (allDecksParent != null) {
+ allDecksParent.addDoc(VAllDecks.SINGLETON_INSTANCE);
+ }
+
+ // set catalog table back to free-selection mode
+ getCatalogManager().setAllowMultipleSelections(true);
+ }
+
+ private void takePile() {
+ CardPool pool = ((WinstonDraft)boosterDraft).takeActivePile(true);
+ // Add pool to deck
+ this.getDeckManager().getPool().addAll(pool);
+
+ // get next booster pack
+ if (this.boosterDraft.hasNextChoice()) {
+ CardPool newPool = this.boosterDraft.nextChoice();
+ if (newPool != null) {
+ this.showChoices(newPool);
+ return;
+ }
+ }
+ // If we get here, there's no choices left. Finish the draft and then save it
+ this.boosterDraft.finishedDrafting();
+ this.saveDraft();
+ }
+
+ private void passPile() {
+ CardPool pool = ((WinstonDraft)boosterDraft).passActivePile(true);
+
+ if (pool != null) {
+ // Passed the third pile, draw the top card of the deck
+ this.getDeckManager().getPool().addAll(pool);
+ }
+ CardPool newPool = this.boosterDraft.nextChoice();
+ if (newPool != null) {
+ this.showChoices(newPool);
+ }
+ }
+}
+
diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/EMenuItem.java b/forge-gui-desktop/src/main/java/forge/screens/home/EMenuItem.java
index b1f8144a485..6fd25e48d35 100644
--- a/forge-gui-desktop/src/main/java/forge/screens/home/EMenuItem.java
+++ b/forge-gui-desktop/src/main/java/forge/screens/home/EMenuItem.java
@@ -10,6 +10,7 @@ public enum EMenuItem { /** */
CONSTRUCTED, /** */
LIMITED_DRAFT, /** */
LIMITED_SEALED, /** */
+ LIMITED_WINSTON,
QUEST_CHALLENGES, /** */
QUEST_DUELS, /** */
diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java b/forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java
index 085176ca173..bff888cea50 100644
--- a/forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java
+++ b/forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java
@@ -31,6 +31,7 @@ import forge.screens.home.quest.*;
import forge.screens.home.sanctioned.VSubmenuConstructed;
import forge.screens.home.sanctioned.VSubmenuDraft;
import forge.screens.home.sanctioned.VSubmenuSealed;
+import forge.screens.home.sanctioned.VSubmenuWinston;
import forge.screens.home.settings.VSubmenuAvatars;
import forge.screens.home.settings.VSubmenuDownloaders;
import forge.screens.home.settings.VSubmenuPreferences;
@@ -115,6 +116,7 @@ public enum VHomeUI implements IVTopLevelUI {
allSubmenus.add(VSubmenuConstructed.SINGLETON_INSTANCE);
allSubmenus.add(VSubmenuDraft.SINGLETON_INSTANCE);
allSubmenus.add(VSubmenuSealed.SINGLETON_INSTANCE);
+ //allSubmenus.add(VSubmenuWinston.SINGLETON_INSTANCE);
allSubmenus.add(VSubmenuDuels.SINGLETON_INSTANCE);
allSubmenus.add(VSubmenuChallenges.SINGLETON_INSTANCE);
diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuDraft.java b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuDraft.java
index 794ffa2156b..9a3888251a9 100644
--- a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuDraft.java
+++ b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuDraft.java
@@ -75,7 +75,7 @@ public enum CSubmenuDraft implements ICDoc {
*/
@Override
public void update() {
- final VSubmenuDraft view = VSubmenuDraft.SINGLETON_INSTANCE;
+ final VSubmenuDraft view = VSubmenuDraft.SINGLETON_INSTANCE;
final JButton btnStart = view.getBtnStart();
view.getLstDecks().setPool(DeckProxy.getDraftDecks(FModel.getDecks().getDraft()));
diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuWinston.java b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuWinston.java
new file mode 100644
index 00000000000..7b4c5f97fa5
--- /dev/null
+++ b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuWinston.java
@@ -0,0 +1,162 @@
+package forge.screens.home.sanctioned;
+
+import forge.GuiBase;
+import forge.UiCommand;
+import forge.Singletons;
+import forge.deck.Deck;
+import forge.deck.DeckGroup;
+import forge.game.GameType;
+import forge.game.player.RegisteredPlayer;
+import forge.gui.GuiChoose;
+import forge.gui.SOverlayUtils;
+import forge.interfaces.IGuiBase;
+import forge.model.FModel;
+import forge.screens.deckeditor.CDeckEditorUI;
+import forge.deck.DeckProxy;
+import forge.screens.deckeditor.controllers.CEditorWinstonProcess;
+import forge.gui.framework.FScreen;
+import forge.gui.framework.ICDoc;
+import forge.toolbox.FOptionPane;
+import forge.itemmanager.ItemManagerConfig;
+import forge.limited.LimitedPoolType;
+import forge.limited.WinstonDraft;
+import forge.properties.ForgePreferences.FPref;
+
+import javax.swing.*;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Controls the draft submenu in the home UI.
+ *
+ *
(C at beginning of class name denotes a control class.)
+ *
+ */
+@SuppressWarnings("serial")
+public enum CSubmenuWinston implements ICDoc {
+ /** */
+ SINGLETON_INSTANCE;
+
+ private final UiCommand cmdDeckSelect = new UiCommand() {
+ @Override
+ public void run() {
+ VSubmenuWinston.SINGLETON_INSTANCE.getBtnStart().setEnabled(true);
+ }
+ };
+
+ /* (non-Javadoc)
+ * @see forge.control.home.IControlSubmenu#update()
+ */
+ @Override
+ public void initialize() {
+ final VSubmenuWinston view = VSubmenuWinston.SINGLETON_INSTANCE;
+
+ view.getLstDecks().setSelectCommand(cmdDeckSelect);
+
+ view.getBtnBuildDeck().setCommand(new UiCommand() {
+ @Override
+ public void run() {
+ setupDraft();
+ }
+ });
+
+ view.getBtnStart().addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ startGame(GameType.Winston);
+ }
+ });
+ }
+
+ /* (non-Javadoc)
+ * @see forge.control.home.IControlSubmenu#update()
+ */
+ @Override
+ public void update() {
+ final VSubmenuWinston view = VSubmenuWinston.SINGLETON_INSTANCE;
+ final JButton btnStart = view.getBtnStart();
+
+ view.getLstDecks().setPool(DeckProxy.getWinstonDecks(FModel.getDecks().getWinston()));
+ view.getLstDecks().setup(ItemManagerConfig.WINSTON_DECKS);
+
+ if (!view.getLstDecks().getPool().isEmpty()) {
+ btnStart.setEnabled(true);
+ }
+
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override public void run() {
+ if (btnStart.isEnabled()) {
+ view.getBtnStart().requestFocusInWindow();
+ } else {
+ view.getBtnBuildDeck().requestFocusInWindow();
+ }
+ }
+ });
+ }
+
+ private void startGame(final GameType gameType) {
+ final DeckProxy humanDeck = VSubmenuWinston.SINGLETON_INSTANCE.getLstDecks().getSelectedItem();
+ final int aiIndex = 0;
+
+ if (humanDeck == null) {
+ FOptionPane.showErrorDialog("No deck selected for human.\n(You may need to build a new deck)", "No Deck");
+ return;
+ }
+
+ if (FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY)) {
+ String errorMessage = gameType.getDecksFormat().getDeckConformanceProblem(humanDeck.getDeck());
+ if (null != errorMessage) {
+ FOptionPane.showErrorDialog("Your deck " + errorMessage + " Please edit or choose a different deck.", "Invalid Deck");
+ return;
+ }
+ }
+
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ SOverlayUtils.startGameOverlay();
+ SOverlayUtils.showOverlay();
+ }
+ });
+
+ DeckGroup opponentDecks = FModel.getDecks().getWinston().get(humanDeck.getName());
+ Deck aiDeck = opponentDecks.getAiDecks().get(aiIndex);
+ if (aiDeck == null) {
+ throw new IllegalStateException("Draft: Computer deck is null!");
+ }
+
+ IGuiBase fc = GuiBase.getInterface();
+ List starter = new ArrayList();
+ starter.add(new RegisteredPlayer(humanDeck.getDeck()).setPlayer(fc.getGuiPlayer()));
+ starter.add(new RegisteredPlayer(aiDeck).setPlayer(fc.createAiPlayer()));
+
+ Singletons.getControl().startMatch(GameType.Winston, starter);
+ }
+
+ /** */
+ private void setupDraft() {
+ // Determine what kind of booster draft to run
+ final LimitedPoolType poolType = GuiChoose.oneOrNone("Choose Draft Format", LimitedPoolType.values());
+ if (poolType == null) { return; }
+
+ WinstonDraft draft = WinstonDraft.createDraft(poolType);
+ if (draft == null) { return; }
+
+ final CEditorWinstonProcess draftController = new CEditorWinstonProcess();
+ draftController.showGui(draft);
+
+ Singletons.getControl().setCurrentScreen(FScreen.DRAFTING_PROCESS);
+ CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(draftController);
+ }
+
+ /* (non-Javadoc)
+ * @see forge.gui.framework.ICDoc#getCommandOnSelect()
+ */
+ @Override
+ public UiCommand getCommandOnSelect() {
+ return null;
+ }
+}
diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuWinston.java b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuWinston.java
new file mode 100644
index 00000000000..480fe3cf123
--- /dev/null
+++ b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuWinston.java
@@ -0,0 +1,177 @@
+package forge.screens.home.sanctioned;
+
+import forge.game.GameType;
+import forge.gui.framework.DragCell;
+import forge.gui.framework.DragTab;
+import forge.gui.framework.EDocID;
+import forge.itemmanager.DeckManager;
+import forge.itemmanager.ItemManagerContainer;
+import forge.screens.home.*;
+import forge.screens.home.VHomeUI.PnlDisplay;
+import forge.toolbox.*;
+import net.miginfocom.swing.MigLayout;
+
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * Assembles Swing components of draft submenu singleton.
+ *
+ *
(V at beginning of class name denotes a view class.)
+ */
+public enum VSubmenuWinston implements IVSubmenu {
+ /** */
+ SINGLETON_INSTANCE;
+
+ // Fields used with interface IVDoc
+ private DragCell parentCell;
+ private final DragTab tab = new DragTab("Winston Draft");
+
+ /** */
+ private final LblHeader lblTitle = new LblHeader("Sanctioned Format: Winston Draft");
+
+ private final JPanel pnlStart = new JPanel();
+ private final StartButton btnStart = new StartButton();
+
+ private final DeckManager lstDecks = new DeckManager(GameType.Winston);
+ private final JList lstAI = new FList();
+
+ private final JLabel lblInfo = new FLabel.Builder()
+ .fontAlign(SwingConstants.LEFT).fontSize(16).fontStyle(Font.BOLD)
+ .text("Build or select a deck").build();
+
+ private final FLabel lblDir1 = new FLabel.Builder()
+ .text("In Winston Draft mode, two players draft 6 packs of cards by piles.")
+ .fontSize(12).build();
+
+ private final FLabel lblDir2 = new FLabel.Builder()
+ .text("Build a deck from the cards you choose. The AI will do the same.")
+ .fontSize(12).build();
+
+ private final FLabel lblDir3 = new FLabel.Builder()
+ .text("Then, play against the AI opponent you drafted against.")
+ .fontSize(12).build();
+
+ private final FLabel btnBuildDeck = new FLabel.ButtonBuilder().text("New Winston Draft Game").fontSize(16).build();
+
+ /**
+ * Constructor.
+ */
+ private VSubmenuWinston() {
+ lstAI.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ btnStart.setEnabled(false);
+
+ lblTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
+ lstDecks.setCaption("Winston Draft Decks");
+
+ pnlStart.setLayout(new MigLayout("insets 0, gap 0, wrap 2"));
+ pnlStart.setOpaque(false);
+ pnlStart.add(btnStart);
+ }
+
+ /* (non-Javadoc)
+ * @see forge.view.home.IViewSubmenu#getGroup()
+ */
+ @Override
+ public EMenuGroup getGroupEnum() {
+ return EMenuGroup.SANCTIONED;
+ }
+
+ /* (non-Javadoc)
+ * @see forge.gui.home.IVSubmenu#getMenuTitle()
+ */
+ @Override
+ public String getMenuTitle() {
+ return "Winston Draft";
+ }
+
+ /* (non-Javadoc)
+ * @see forge.gui.home.IVSubmenu#getItemEnum()
+ */
+ @Override
+ public EDocID getItemEnum() {
+ return EDocID.HOME_WINSTON;
+ }
+
+ /** @return {@link forge.gui.toolbox.FLabel} */
+ public FLabel getBtnBuildDeck() {
+ return this.btnBuildDeck;
+ }
+
+ /** @return {@link javax.swing.JButton} */
+ public JButton getBtnStart() {
+ return this.btnStart;
+ }
+
+ /** @return {@link forge.gui.toolbox.itemmanager.DeckManager} */
+ public DeckManager getLstDecks() {
+ return lstDecks;
+ }
+
+ //========== Overridden from IVDoc
+
+ /* (non-Javadoc)
+ * @see forge.view.home.IViewSubmenu#populate()
+ */
+ @Override
+ public void populate() {
+ PnlDisplay pnlDisplay = VHomeUI.SINGLETON_INSTANCE.getPnlDisplay();
+ pnlDisplay.removeAll();
+ pnlDisplay.setLayout(new MigLayout("insets 0, gap 0, wrap, ax right"));
+ pnlDisplay.add(lblTitle, "w 80%!, h 40px!, gap 0 0 15px 15px, ax right");
+
+ pnlDisplay.add(lblInfo, "w 80%!, h 30px!, gap 0 10% 20px 5px");
+ pnlDisplay.add(lblDir1, "gap 0 0 0 5px");
+ pnlDisplay.add(lblDir2, "gap 0 0 0 5px");
+ pnlDisplay.add(lblDir3, "gap 0 0 0 20px");
+
+ pnlDisplay.add(btnBuildDeck, "w 250px!, h 30px!, ax center, gap 0 10% 0 20px");
+ pnlDisplay.add(new ItemManagerContainer(lstDecks), "w 80%!, gap 0 10% 0 0, pushy, growy");
+
+ pnlDisplay.add(pnlStart, "gap 0 10% 50px 50px, ax center");
+
+ pnlDisplay.repaint();
+ pnlDisplay.revalidate();
+ }
+
+ /* (non-Javadoc)
+ * @see forge.gui.framework.IVDoc#getDocumentID()
+ */
+ @Override
+ public EDocID getDocumentID() {
+ return EDocID.HOME_WINSTON;
+ }
+
+ /* (non-Javadoc)
+ * @see forge.gui.framework.IVDoc#getTabLabel()
+ */
+ @Override
+ public DragTab getTabLabel() {
+ return tab;
+ }
+
+ /* (non-Javadoc)
+ * @see forge.gui.framework.IVDoc#setParentCell(forge.gui.framework.DragCell)
+ */
+ @Override
+ public void setParentCell(final DragCell cell0) {
+ this.parentCell = cell0;
+ }
+
+ /* (non-Javadoc)
+ * @see forge.gui.framework.IVDoc#getParentCell()
+ */
+ @Override
+ public DragCell getParentCell() {
+ return parentCell;
+ }
+
+ /* (non-Javadoc)
+ * @see forge.gui.framework.IVDoc#getLayoutControl()
+ */
+ @Override
+ public CSubmenuWinston getLayoutControl() {
+ return CSubmenuWinston.SINGLETON_INSTANCE;
+ }
+}
diff --git a/forge-gui-desktop/src/test/java/forge/BoosterDraftTest.java b/forge-gui-desktop/src/test/java/forge/BoosterDraftTest.java
index 3928a752a73..3c3b5c43e48 100644
--- a/forge-gui-desktop/src/test/java/forge/BoosterDraftTest.java
+++ b/forge-gui-desktop/src/test/java/forge/BoosterDraftTest.java
@@ -105,4 +105,9 @@ public class BoosterDraftTest implements IBoosterDraft {
public void finishedDrafting() {
}
+
+ @Override
+ public boolean isPileDraft() {
+ return false;
+ }
}
diff --git a/forge-gui/src/main/java/forge/deck/DeckProxy.java b/forge-gui/src/main/java/forge/deck/DeckProxy.java
index d9b0d1a3607..43f1e4c1186 100644
--- a/forge-gui/src/main/java/forge/deck/DeckProxy.java
+++ b/forge-gui/src/main/java/forge/deck/DeckProxy.java
@@ -416,6 +416,15 @@ public class DeckProxy implements InventoryItem {
return decks;
}
+ @SuppressWarnings("unchecked")
+ public static Iterable getWinstonDecks(IStorage draft) {
+ ArrayList decks = new ArrayList();
+ for (DeckGroup d : draft) {
+ decks.add(new DeckProxy(d, "Winston", ((Function)(Object)DeckGroup.FN_HUMAN_DECK), GameType.Winston, draft));
+ }
+ return decks;
+ }
+
public static final Predicate IS_WHITE = new Predicate() {
@Override
public boolean apply(final DeckProxy deck) {
diff --git a/forge-gui/src/main/java/forge/itemmanager/ItemManagerConfig.java b/forge-gui/src/main/java/forge/itemmanager/ItemManagerConfig.java
index 8e575d39bae..15f28188b30 100644
--- a/forge-gui/src/main/java/forge/itemmanager/ItemManagerConfig.java
+++ b/forge-gui/src/main/java/forge/itemmanager/ItemManagerConfig.java
@@ -58,6 +58,8 @@ public enum ItemManagerConfig {
null, null, 3, 0),
SEALED_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
+ WINSTON_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
+ null, null, 3, 0),
QUEST_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
PRECON_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
diff --git a/forge-gui/src/main/java/forge/limited/BoosterDraft.java b/forge-gui/src/main/java/forge/limited/BoosterDraft.java
index cd829617229..fc725744d7e 100644
--- a/forge-gui/src/main/java/forge/limited/BoosterDraft.java
+++ b/forge-gui/src/main/java/forge/limited/BoosterDraft.java
@@ -50,31 +50,35 @@ import java.util.Map.Entry;
* Booster Draft Format.
*
*/
-public final class BoosterDraft implements IBoosterDraft {
+public class BoosterDraft implements IBoosterDraft {
private final BoosterDraftAI draftAI = new BoosterDraftAI();
private static final int N_PLAYERS = 8;
public static final String FILE_EXT = ".draft";
- private int nextBoosterGroup = 0;
+ protected int nextBoosterGroup = 0;
private int currentBoosterSize = 0;
private int currentBoosterPick = 0;
private List> pack; // size 8
/** The draft picks. */
private final Map draftPicks = new TreeMap();
- private final LimitedPoolType draftFormat;
+ protected LimitedPoolType draftFormat;
- private final List>> product = new ArrayList>>();
+ protected final List>> product = new ArrayList>>();
public static BoosterDraft createDraft(final LimitedPoolType draftType) {
BoosterDraft draft = new BoosterDraft(draftType);
+ if (!draft.generateProduct()) { return null; }
+ return draft;
+ }
- switch (draftType) {
+ protected boolean generateProduct() {
+ switch (this.draftFormat) {
case Full: // Draft from all cards in Forge
Supplier> s = new UnOpenedProduct(SealedProduct.Template.genericBooster);
for (int i = 0; i < 3; i++) {
- draft.product.add(s);
+ this.product.add(s);
}
IBoosterDraft.LAND_SET_CODE[0] = CardEdition.Predicates.getRandomSetWithAllBasicLands(FModel.getMagicDb().getEditions());
break;
@@ -82,7 +86,7 @@ public final class BoosterDraft implements IBoosterDraft {
case Block: // Draft from cards by block or set
case FantasyBlock:
List blocks = new ArrayList();
- IStorage storage = draftType == LimitedPoolType.Block
+ IStorage storage = this.draftFormat == LimitedPoolType.Block
? FModel.getBlocks() : FModel.getFantasyBlocks();
for (CardBlock b : storage) {
@@ -92,12 +96,12 @@ public final class BoosterDraft implements IBoosterDraft {
}
final CardBlock block = SGuiChoose.oneOrNone("Choose Block", blocks);
- if (block == null) { return null; }
+ if (block == null) { return false; }
final CardEdition[] cardSets = block.getSets();
if (cardSets.length == 0) {
SOptionPane.showErrorDialog(block.toString() + " does not contain any set combinations.");
- return null;
+ return false;
}
final Stack sets = new Stack();
@@ -115,18 +119,18 @@ public final class BoosterDraft implements IBoosterDraft {
if (sets.size() > 1) {
final Object p = SGuiChoose.oneOrNone("Choose Set Combination", getSetCombos(sets));
- if (p == null) { return null; }
+ if (p == null) { return false; }
final String[] pp = p.toString().split("/");
for (int i = 0; i < nPacks; i++) {
- draft.product.add(block.getBooster(pp[i]));
+ this.product.add(block.getBooster(pp[i]));
}
}
else {
IUnOpenedProduct product1 = block.getBooster(sets.get(0));
for (int i = 0; i < nPacks; i++) {
- draft.product.add(product1);
+ this.product.add(product1);
}
}
@@ -134,29 +138,28 @@ public final class BoosterDraft implements IBoosterDraft {
break;
case Custom:
- final List myDrafts = draft.loadCustomDrafts();
+ final List myDrafts = this.loadCustomDrafts();
if (myDrafts.isEmpty()) {
SOptionPane.showMessageDialog("No custom draft files found.");
}
else {
final CustomLimited customDraft = SGuiChoose.oneOrNone("Choose Custom Draft", myDrafts);
- if (customDraft == null) { return null; }
+ if (customDraft == null) { return false; }
- draft.setupCustomDraft(customDraft);
+ this.setupCustomDraft(customDraft);
}
break;
default:
- throw new NoSuchElementException("Draft for mode " + draftType + " has not been set up!");
+ throw new NoSuchElementException("Draft for mode " + this.draftFormat + " has not been set up!");
}
- draft.pack = draft.get8BoosterPack();
- return draft;
+ this.pack = this.get8BoosterPack();
+ return true;
}
-
- public static BoosterDraft createDraft(final LimitedPoolType draftType, final CardBlock block, final String[] boosters) {
-
+
+ public static BoosterDraft createDraft(final LimitedPoolType draftType, final CardBlock block, final String[] boosters) {
BoosterDraft draft = new BoosterDraft(draftType);
final int nPacks = boosters.length;
@@ -169,18 +172,20 @@ public final class BoosterDraft implements IBoosterDraft {
draft.pack = draft.get8BoosterPack();
return draft;
-
}
+ protected BoosterDraft() {
+ this.draftFormat = LimitedPoolType.Full;
+ }
/**
*
* Constructor for BoosterDraft_1.
*
- *
+ *
* @param draftType
* a {@link java.lang.String} object.
*/
- private BoosterDraft(final LimitedPoolType draftType) {
+ protected BoosterDraft(final LimitedPoolType draftType) {
this.draftAI.setBd(this);
this.draftFormat = draftType;
}
@@ -233,7 +238,7 @@ public final class BoosterDraft implements IBoosterDraft {
* nextChoice.
*
*
- * @return a {@link forge.CardList} object.
+ * @return a {@link forge.deck.CardPool} object.
*/
@Override
public CardPool nextChoice() {
@@ -252,7 +257,7 @@ public final class BoosterDraft implements IBoosterDraft {
* get8BoosterPack.
*
*
- * @return an array of {@link forge.CardList} objects.
+ * @return an array of {@link forge.deck.CardPool} objects.
*/
public List> get8BoosterPack() {
if (this.nextBoosterGroup >= this.product.size()) {
@@ -284,7 +289,7 @@ public final class BoosterDraft implements IBoosterDraft {
return this.draftAI.getDecks();
}
- private void computerChoose() {
+ protected void computerChoose() {
final int iHumansBooster = this.getCurrentBoosterIndex();
int iPlayer = 0;
for (int i = 1; i < this.pack.size(); i++) {
@@ -377,6 +382,11 @@ public final class BoosterDraft implements IBoosterDraft {
HttpUtil.upload(ForgeConstants.URL_DRAFT_UPLOAD + "?fmt=" + draftFormat, outDraftData);
}
+ @Override
+ public boolean isPileDraft() {
+ return false;
+ }
+
private static List getSetCombos(final List setz) {
String[] sets = setz.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
List setCombos = new ArrayList();
diff --git a/forge-gui/src/main/java/forge/limited/BoosterDraftAI.java b/forge-gui/src/main/java/forge/limited/BoosterDraftAI.java
index f2103f56dba..97a07e76de2 100644
--- a/forge-gui/src/main/java/forge/limited/BoosterDraftAI.java
+++ b/forge-gui/src/main/java/forge/limited/BoosterDraftAI.java
@@ -45,11 +45,11 @@ public class BoosterDraftAI {
/**
* Constant nDecks=7.
*/
- private static final int N_DECKS = 7;
+ protected static final int N_DECKS = 7;
// holds all the cards for each of the computer's decks
- private final List> deck = new ArrayList>();
- private final ArrayList playerColors = new ArrayList();
+ protected final List> deck = new ArrayList>();
+ protected final ArrayList playerColors = new ArrayList();
// roughly equivalent to 25 ranks in a core set, or 15 ranks in a small set
private static final double TAKE_BEST_THRESHOLD = 0.1;
@@ -63,7 +63,7 @@ public class BoosterDraftAI {
* List of CardPrinted
* @param player
* a int.
- * @return a {@link forge.CardList} object.
+ * @return a {@link forge.item.PaperCard} object.
*/
public PaperCard choose(final List chooseFrom, final int player) {
if (ForgePreferences.DEV_MODE) {
diff --git a/forge-gui/src/main/java/forge/limited/DeckColors.java b/forge-gui/src/main/java/forge/limited/DeckColors.java
index fda524518b2..b902879c317 100644
--- a/forge-gui/src/main/java/forge/limited/DeckColors.java
+++ b/forge-gui/src/main/java/forge/limited/DeckColors.java
@@ -22,6 +22,8 @@ import forge.card.MagicColor;
import forge.card.mana.ManaCost;
import forge.item.IPaperCard;
+import java.util.List;
+
/**
* Created by IntelliJ IDEA. User: dhudson Date: 6/24/11 Time: 8:42 PM To change
* this template use File | Settings | File Templates.
@@ -64,6 +66,14 @@ class DeckColors {
}
}
+ public void setColorsByList(List colors) {
+ colorMask = 0;
+ for (Byte col : colors) {
+ colorMask |= col;
+ }
+ chosen = null;
+ }
+
public boolean canChoseMoreColors() {
return getChosenColors().countColors() < MAX_COLORS;
diff --git a/forge-gui/src/main/java/forge/limited/IBoosterDraft.java b/forge-gui/src/main/java/forge/limited/IBoosterDraft.java
index e0af1085c94..268ffb68a17 100644
--- a/forge-gui/src/main/java/forge/limited/IBoosterDraft.java
+++ b/forge-gui/src/main/java/forge/limited/IBoosterDraft.java
@@ -76,4 +76,6 @@ public interface IBoosterDraft {
*/
void finishedDrafting();
+ boolean isPileDraft();
+
}
diff --git a/forge-gui/src/main/java/forge/limited/WinstonDraft.java b/forge-gui/src/main/java/forge/limited/WinstonDraft.java
new file mode 100644
index 00000000000..28fa75181ba
--- /dev/null
+++ b/forge-gui/src/main/java/forge/limited/WinstonDraft.java
@@ -0,0 +1,178 @@
+package forge.limited;
+
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+import forge.deck.CardPool;
+import forge.deck.Deck;
+import forge.item.IPaperCard;
+import forge.item.PaperCard;
+import forge.quest.data.GameFormatQuest;
+import forge.util.MyRandom;
+
+import java.util.*;
+
+public class WinstonDraft extends BoosterDraft {
+ private WinstonDraftAI draftAI = null;
+ private static int NUM_PILES = 3;
+ private static int NUM_PLAYERS = 2;
+
+ private Stack deck; // main deck where all cards
+ private List> piles; // 3 piles to draft from
+
+ public static WinstonDraft createDraft(final LimitedPoolType draftType) {
+ WinstonDraft draft = new WinstonDraft(draftType);
+ if (!draft.generateProduct()) {
+ return null;
+ }
+ draft.initializeWinstonDraft();
+ return draft;
+ }
+
+ private WinstonDraft(LimitedPoolType draftType) {
+ draftFormat = draftType;
+ draftAI = new WinstonDraftAI();
+
+ }
+
+ private void initializeWinstonDraft() {
+ this.deck = new Stack();
+ for (int i = 0; i < this.product.size(); i++) {
+ Supplier> supply = this.product.get(i);
+ for(int j = 0; j < NUM_PLAYERS; j++) {
+ // Remove Basic Lands from draft for simplicity
+ for (PaperCard paperCard : Iterables.filter(supply.get(), Predicates.not(PaperCard.Predicates.Presets.IS_BASIC_LAND))) {
+ this.deck.add(paperCard);
+ }
+ }
+ }
+ Collections.shuffle(this.deck, MyRandom.getRandom());
+
+ // Create three Winston piles, adding the top card from the Winston deck to start each pile
+ this.piles = new ArrayList<>();
+ for(int i = 0; i < NUM_PILES; i++) {
+ List pile = new ArrayList();
+ pile.add(this.deck.pop());
+ this.piles.add(pile);
+ }
+
+ this.nextBoosterGroup = 0;
+
+ draftAI.setDraft(this);
+
+ if (MyRandom.percentTrue(50)) {
+ // 50% chance of the AI picking the first card in a Winston Draft
+ //this.computerChoose();
+ }
+ }
+
+ @Override
+ public CardPool nextChoice() {
+ // This is called for two reasons: Skipping a pile, and getting the next one in line
+ // Or taking a pile and getting reset back to the first non-empty pile
+ int nextPile = -1;
+ for(int i = nextBoosterGroup; i < this.piles.size(); i++) {
+ if (this.piles.get(i).size() > 0) {
+ nextPile = i;
+ break;
+ }
+ }
+
+ if (nextPile < 0 || nextPile > this.piles.size())
+ return null;
+
+ nextBoosterGroup = nextPile;
+
+ return getPoolByPile(nextBoosterGroup);
+ }
+
+ public CardPool getActivePool() {
+ return getPoolByPile(this.nextBoosterGroup);
+ }
+
+ private CardPool getPoolByPile(int i) {
+ CardPool result = new CardPool();
+ result.addAllFlat(this.piles.get(i));
+ return result;
+ }
+
+ public void computerChoose() {
+ nextBoosterGroup = 0;
+ draftAI.choose();
+ }
+
+ public void refillPile(List pile) {
+ if (this.deck.size() > 0)
+ pile.add(this.deck.pop());
+ }
+
+ public int getNextChoice(int startPile) {
+ for(int i = startPile; i < NUM_PILES; i++) {
+ if (this.piles.get(i).size() > 0)
+ return i;
+ }
+ // All piles are empty, so draft is about to end.
+ return -1;
+ }
+
+ public boolean hasNextChoice() {
+ return getNextChoice(0) >= 0;
+ }
+
+ public boolean isLastPileAndEmptyDeck(int pile) {
+ return this.deck.size() == 0 && getNextChoice(pile+1) >= 0;
+ }
+
+ public int getCurrentBoosterIndex() {
+ return nextBoosterGroup;
+ }
+
+ public CardPool takeActivePile(boolean humanAction) {
+ CardPool pool = getPoolByPile(this.nextBoosterGroup);
+
+ this.piles.get(this.nextBoosterGroup).clear();
+ this.refillPile(this.piles.get(this.nextBoosterGroup));
+ this.nextBoosterGroup = 0;
+ if (humanAction)
+ computerChoose();
+ return pool;
+ }
+
+ public CardPool passActivePile(boolean humanAction) {
+ this.refillPile(this.piles.get(this.nextBoosterGroup));
+ this.nextBoosterGroup++;
+ if (this.nextBoosterGroup >= this.piles.size()) {
+ CardPool pool = new CardPool();
+ if (this.deck.size() > 0)
+ pool.add(this.deck.pop());
+ this.nextBoosterGroup = 0;
+ if (humanAction)
+ computerChoose();
+ return pool;
+ }
+ return null;
+ }
+
+ public int getNumPiles() {
+ return NUM_PILES;
+ }
+
+ @Override
+ public Deck[] getDecks() {
+ this.determineAIDeckColors();
+ return this.draftAI.getDecks();
+ }
+
+ public void determineAIDeckColors() {
+ this.draftAI.determineDeckColor();
+ }
+
+ @Override
+ public boolean isPileDraft() {
+ return true;
+ }
+
+ public int getDeckSize() { return this.deck.size(); }
+
+ public int getAIDraftSize() { return this.draftAI.getAIDraftSize(); }
+}
diff --git a/forge-gui/src/main/java/forge/limited/WinstonDraftAI.java b/forge-gui/src/main/java/forge/limited/WinstonDraftAI.java
new file mode 100644
index 00000000000..e71f7bc1dbc
--- /dev/null
+++ b/forge-gui/src/main/java/forge/limited/WinstonDraftAI.java
@@ -0,0 +1,114 @@
+package forge.limited;
+
+import forge.card.ColorSet;
+import forge.card.MagicColor;
+import forge.deck.CardPool;
+import forge.game.card.CardColor;
+import forge.item.PaperCard;
+import forge.util.MyRandom;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class WinstonDraftAI extends BoosterDraftAI{
+
+ private WinstonDraft draft = null;
+ private static final int N_DECKS = 1;
+ private ArrayList colorPreference = new ArrayList<>();
+
+ public WinstonDraft getDraft() {
+ return draft;
+ }
+
+ public void setDraft(WinstonDraft draft) {
+ this.draft = draft;
+ }
+
+ public WinstonDraftAI() {
+ this.deck.clear();
+ this.playerColors.clear();
+ for (int i = 0; i < N_DECKS; i++) {
+ this.deck.add(new ArrayList());
+ this.playerColors.add(new DeckColors());
+ }
+ }
+
+ public void determineDeckColor() {
+ // Turn colorPreference into playerColors
+ int count[] = tallyDeckColors();
+ // Just take the three best colors, but maybe sometimes only take best two
+ this.playerColors.get(0).setColorsByList(colorPreference.subList(0, 3));
+ }
+
+ public void choose() {
+ boolean takenPile = true;
+ CardPool acquire = null;
+ while(takenPile) {
+ CardPool pool = draft.getActivePool();
+ // Determine if the current pool is worth taking
+ // For now, each card in a pile is worth 10 points. Compare versus a d100 roll
+ String desc = "Pile " + (draft.getCurrentBoosterIndex()+1);
+ int value = pool.countAll() * 10;
+ // If this is the last pile, and the deck is empty, definitely take the pile!
+ boolean takePile = MyRandom.percentTrue(value) || draft.isLastPileAndEmptyDeck(draft.getCurrentBoosterIndex());
+
+ if (takePile) {
+ acquire = draft.takeActivePile(false);
+ } else {
+ acquire = draft.passActivePile(false);
+ desc = "Top of Deck";
+ }
+ if (acquire != null) {
+ System.out.println("AI taking " + desc + "(" + acquire.countAll() + " cards).");
+ takenPile = false;
+ }
+ }
+ if (acquire != null) {
+ this.deck.get(0).addAll(acquire.toFlatList());
+ //tallyDeckColors();
+ }
+ }
+
+ private int[] tallyDeckColors() {
+ int[] colorCount = new int[5];
+
+ for(PaperCard pc : this.deck.get(0)) {
+ ColorSet colors = pc.getRules().getColor();
+ if (colors.hasWhite())
+ colorCount[0]++;
+ if (colors.hasBlue())
+ colorCount[1]++;
+ if (colors.hasBlack())
+ colorCount[2]++;
+ if (colors.hasRed())
+ colorCount[3]++;
+ if (colors.hasGreen())
+ colorCount[4]++;
+ }
+
+ // Just keep order or should I keep order/value pairs?
+ colorPreference.clear();
+ for(int i = 0; i < colorCount.length; i++) {
+ // Sort colors in order.
+ Byte col = MagicColor.WUBRG[i];
+ int spot = 0;
+ for (int j = 0; j < i; j++) {
+ if (colorCount[i] > colorCount[j]) {
+ // If new color has more than the current slot, we need to add into that slot
+ // And push all remaining colors further down
+ break;
+ }
+ spot++;
+ }
+ colorPreference.add(spot, col);
+ }
+ // Is this the right order?
+ return colorCount;
+ }
+
+ public int getAIDraftSize() {
+ return this.deck.get(0).size();
+ }
+}
diff --git a/forge-gui/src/main/java/forge/model/CardCollections.java b/forge-gui/src/main/java/forge/model/CardCollections.java
index f1d7764a6fa..2ec1b02aace 100644
--- a/forge-gui/src/main/java/forge/model/CardCollections.java
+++ b/forge-gui/src/main/java/forge/model/CardCollections.java
@@ -37,6 +37,7 @@ public class CardCollections {
private final IStorage constructed;
private final IStorage draft;
private final IStorage sealed;
+ private final IStorage winston;
private final IStorage cube;
private final IStorage scheme;
private final IStorage plane;
@@ -53,11 +54,11 @@ public class CardCollections {
this.constructed = new StorageImmediatelySerialized("Constructed decks", new DeckStorage(new File(ForgeConstants.DECK_CONSTRUCTED_DIR), true), true);
this.draft = new StorageImmediatelySerialized("Draft deck sets", new DeckGroupSerializer(new File(ForgeConstants.DECK_DRAFT_DIR)));
this.sealed = new StorageImmediatelySerialized("Sealed deck sets", new DeckGroupSerializer(new File(ForgeConstants.DECK_SEALED_DIR)));
+ this.winston = new StorageImmediatelySerialized("Winston draft deck sets", new DeckGroupSerializer(new File(ForgeConstants.DECK_WINSTON_DIR)));
this.cube = new StorageImmediatelySerialized("Cubes", new DeckStorage(new File(ForgeConstants.DECK_CUBE_DIR)));
this.scheme = new StorageImmediatelySerialized("Archenemy decks", new DeckStorage(new File(ForgeConstants.DECK_SCHEME_DIR)));
this.plane = new StorageImmediatelySerialized("Planechase decks", new DeckStorage(new File(ForgeConstants.DECK_PLANE_DIR)));
this.commander = new StorageImmediatelySerialized("Commander decks", new DeckStorage(new File(ForgeConstants.DECK_COMMANDER_DIR)));
-
sw.stop();
System.out.printf("Read decks (%d ms): %d constructed, %d sealed, %d draft, %d cubes, %d scheme, %d planar, %d commander.%n", sw.getTime(), constructed.size(), sealed.size(), draft.size(), cube.size(), scheme.size(), plane.size(),commander.size());
// int sum = constructed.size() + sealed.size() + draft.size() + cube.size() + scheme.size() + plane.size();
@@ -85,6 +86,10 @@ public class CardCollections {
return this.draft;
}
+ public final IStorage getWinston() {
+ return this.winston;
+ }
+
/**
* Gets the cubes.
*
diff --git a/forge-gui/src/main/java/forge/properties/ForgeConstants.java b/forge-gui/src/main/java/forge/properties/ForgeConstants.java
index 101bceab668..a199c129788 100644
--- a/forge-gui/src/main/java/forge/properties/ForgeConstants.java
+++ b/forge-gui/src/main/java/forge/properties/ForgeConstants.java
@@ -102,6 +102,7 @@ public final class ForgeConstants {
public static final String DECK_BASE_DIR = USER_DIR + "decks/";
public static final String DECK_CONSTRUCTED_DIR = DECK_BASE_DIR + "constructed/";
public static final String DECK_DRAFT_DIR = DECK_BASE_DIR + "draft/";
+ public static final String DECK_WINSTON_DIR = DECK_BASE_DIR + "winston/";
public static final String DECK_SEALED_DIR = DECK_BASE_DIR + "sealed/";
public static final String DECK_SCHEME_DIR = DECK_BASE_DIR + "scheme/";
public static final String DECK_PLANE_DIR = DECK_BASE_DIR + "planar/";