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/";