mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +00:00
- 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.
This commit is contained in:
5
.gitattributes
vendored
5
.gitattributes
vendored
@@ -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
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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), /** */
|
||||
|
||||
@@ -237,6 +237,10 @@ public final class DeckManager extends ItemManager<DeckProxy> {
|
||||
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;
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* <br><br><i>(C at beginning of class name denotes a control class.)</i>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: CEditorDraftingProcess.java 24872 2014-02-17 07:35:47Z drdev $
|
||||
*/
|
||||
public class CEditorWinstonProcess extends ACEditorBase<PaperCard, DeckGroup> {
|
||||
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<Entry<PaperCard, Integer>> 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<Entry<PaperCard, Integer>> items, boolean toAlternate) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildAddContextMenu(EditorContextMenuBuilder cmb) {
|
||||
cmb.addMoveItems("Draft", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildRemoveContextMenu(EditorContextMenuBuilder cmb) {
|
||||
// no valid remove options
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* showChoices.
|
||||
* </p>
|
||||
*
|
||||
* @param list
|
||||
* a {@link ItemPool<PaperCard>} object.
|
||||
*/
|
||||
private void showChoices(final ItemPool<PaperCard> 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()
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getPlayersDeck.
|
||||
* </p>
|
||||
*
|
||||
* @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()
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* saveDraft.
|
||||
* </p>
|
||||
*/
|
||||
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<DeckGroup> 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<PaperCard>) 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ public enum EMenuItem { /** */
|
||||
CONSTRUCTED, /** */
|
||||
LIMITED_DRAFT, /** */
|
||||
LIMITED_SEALED, /** */
|
||||
LIMITED_WINSTON,
|
||||
|
||||
QUEST_CHALLENGES, /** */
|
||||
QUEST_DUELS, /** */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* <br><br><i>(C at beginning of class name denotes a control class.)</i>
|
||||
*
|
||||
*/
|
||||
@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<RegisteredPlayer> starter = new ArrayList<RegisteredPlayer>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*
|
||||
* <br><br><i>(V at beginning of class name denotes a view class.)</i>
|
||||
*/
|
||||
public enum VSubmenuWinston implements IVSubmenu<CSubmenuWinston> {
|
||||
/** */
|
||||
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<String> lstAI = new FList<String>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -105,4 +105,9 @@ public class BoosterDraftTest implements IBoosterDraft {
|
||||
public void finishedDrafting() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPileDraft() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,6 +416,15 @@ public class DeckProxy implements InventoryItem {
|
||||
return decks;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Iterable<DeckProxy> getWinstonDecks(IStorage<DeckGroup> draft) {
|
||||
ArrayList<DeckProxy> decks = new ArrayList<DeckProxy>();
|
||||
for (DeckGroup d : draft) {
|
||||
decks.add(new DeckProxy(d, "Winston", ((Function<IHasName, Deck>)(Object)DeckGroup.FN_HUMAN_DECK), GameType.Winston, draft));
|
||||
}
|
||||
return decks;
|
||||
}
|
||||
|
||||
public static final Predicate<DeckProxy> IS_WHITE = new Predicate<DeckProxy>() {
|
||||
@Override
|
||||
public boolean apply(final DeckProxy deck) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<List<PaperCard>> pack; // size 8
|
||||
|
||||
/** The draft picks. */
|
||||
private final Map<String, Float> draftPicks = new TreeMap<String, Float>();
|
||||
private final LimitedPoolType draftFormat;
|
||||
protected LimitedPoolType draftFormat;
|
||||
|
||||
private final List<Supplier<List<PaperCard>>> product = new ArrayList<Supplier<List<PaperCard>>>();
|
||||
protected final List<Supplier<List<PaperCard>>> product = new ArrayList<Supplier<List<PaperCard>>>();
|
||||
|
||||
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<List<PaperCard>> 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<CardBlock> blocks = new ArrayList<CardBlock>();
|
||||
IStorage<CardBlock> storage = draftType == LimitedPoolType.Block
|
||||
IStorage<CardBlock> 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<String> sets = new Stack<String>();
|
||||
@@ -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<CustomLimited> myDrafts = draft.loadCustomDrafts();
|
||||
final List<CustomLimited> 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;
|
||||
}
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for BoosterDraft_1.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @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.
|
||||
* </p>
|
||||
*
|
||||
* @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.
|
||||
* </p>
|
||||
*
|
||||
* @return an array of {@link forge.CardList} objects.
|
||||
* @return an array of {@link forge.deck.CardPool} objects.
|
||||
*/
|
||||
public List<List<PaperCard>> 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<String> getSetCombos(final List<String> setz) {
|
||||
String[] sets = setz.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
|
||||
List<String> setCombos = new ArrayList<String>();
|
||||
|
||||
@@ -45,11 +45,11 @@ public class BoosterDraftAI {
|
||||
/**
|
||||
* Constant <code>nDecks=7.</code>
|
||||
*/
|
||||
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<List<PaperCard>> deck = new ArrayList<List<PaperCard>>();
|
||||
private final ArrayList<DeckColors> playerColors = new ArrayList<DeckColors>();
|
||||
protected final List<List<PaperCard>> deck = new ArrayList<List<PaperCard>>();
|
||||
protected final ArrayList<DeckColors> playerColors = new ArrayList<DeckColors>();
|
||||
|
||||
// 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<PaperCard> chooseFrom, final int player) {
|
||||
if (ForgePreferences.DEV_MODE) {
|
||||
|
||||
@@ -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<Byte> colors) {
|
||||
colorMask = 0;
|
||||
for (Byte col : colors) {
|
||||
colorMask |= col;
|
||||
}
|
||||
chosen = null;
|
||||
}
|
||||
|
||||
|
||||
public boolean canChoseMoreColors() {
|
||||
return getChosenColors().countColors() < MAX_COLORS;
|
||||
|
||||
@@ -76,4 +76,6 @@ public interface IBoosterDraft {
|
||||
*/
|
||||
void finishedDrafting();
|
||||
|
||||
boolean isPileDraft();
|
||||
|
||||
}
|
||||
|
||||
178
forge-gui/src/main/java/forge/limited/WinstonDraft.java
Normal file
178
forge-gui/src/main/java/forge/limited/WinstonDraft.java
Normal file
@@ -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<PaperCard> deck; // main deck where all cards
|
||||
private List<List<PaperCard>> 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<PaperCard>();
|
||||
for (int i = 0; i < this.product.size(); i++) {
|
||||
Supplier<List<PaperCard>> 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<PaperCard> pile = new ArrayList<PaperCard>();
|
||||
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<PaperCard> 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(); }
|
||||
}
|
||||
114
forge-gui/src/main/java/forge/limited/WinstonDraftAI.java
Normal file
114
forge-gui/src/main/java/forge/limited/WinstonDraftAI.java
Normal file
@@ -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<Byte> 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<PaperCard>());
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ public class CardCollections {
|
||||
private final IStorage<Deck> constructed;
|
||||
private final IStorage<DeckGroup> draft;
|
||||
private final IStorage<DeckGroup> sealed;
|
||||
private final IStorage<DeckGroup> winston;
|
||||
private final IStorage<Deck> cube;
|
||||
private final IStorage<Deck> scheme;
|
||||
private final IStorage<Deck> plane;
|
||||
@@ -53,11 +54,11 @@ public class CardCollections {
|
||||
this.constructed = new StorageImmediatelySerialized<Deck>("Constructed decks", new DeckStorage(new File(ForgeConstants.DECK_CONSTRUCTED_DIR), true), true);
|
||||
this.draft = new StorageImmediatelySerialized<DeckGroup>("Draft deck sets", new DeckGroupSerializer(new File(ForgeConstants.DECK_DRAFT_DIR)));
|
||||
this.sealed = new StorageImmediatelySerialized<DeckGroup>("Sealed deck sets", new DeckGroupSerializer(new File(ForgeConstants.DECK_SEALED_DIR)));
|
||||
this.winston = new StorageImmediatelySerialized<DeckGroup>("Winston draft deck sets", new DeckGroupSerializer(new File(ForgeConstants.DECK_WINSTON_DIR)));
|
||||
this.cube = new StorageImmediatelySerialized<Deck>("Cubes", new DeckStorage(new File(ForgeConstants.DECK_CUBE_DIR)));
|
||||
this.scheme = new StorageImmediatelySerialized<Deck>("Archenemy decks", new DeckStorage(new File(ForgeConstants.DECK_SCHEME_DIR)));
|
||||
this.plane = new StorageImmediatelySerialized<Deck>("Planechase decks", new DeckStorage(new File(ForgeConstants.DECK_PLANE_DIR)));
|
||||
this.commander = new StorageImmediatelySerialized<Deck>("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<DeckGroup> getWinston() {
|
||||
return this.winston;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cubes.
|
||||
*
|
||||
|
||||
@@ -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/";
|
||||
|
||||
Reference in New Issue
Block a user