diff --git a/.gitattributes b/.gitattributes index dde0acc3469..6694d9b1077 100644 --- a/.gitattributes +++ b/.gitattributes @@ -11343,6 +11343,8 @@ src/main/java/forge/gui/home/constructed/VSubmenuColors.java -text src/main/java/forge/gui/home/constructed/VSubmenuCustom.java -text src/main/java/forge/gui/home/constructed/VSubmenuQuestEvents.java -text src/main/java/forge/gui/home/constructed/VSubmenuThemes.java -text +src/main/java/forge/gui/home/draft/CSubmenuDraft.java -text +src/main/java/forge/gui/home/draft/VSubmenuDraft.java -text src/main/java/forge/gui/home/quest/CSubmenuDuels.java -text src/main/java/forge/gui/home/quest/VSubmenuDuels.java -text src/main/java/forge/gui/package-info.java svneol=native#text/plain diff --git a/src/main/java/forge/gui/home/draft/CSubmenuDraft.java b/src/main/java/forge/gui/home/draft/CSubmenuDraft.java new file mode 100644 index 00000000000..0923892e60e --- /dev/null +++ b/src/main/java/forge/gui/home/draft/CSubmenuDraft.java @@ -0,0 +1,222 @@ +package forge.gui.home.draft; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +import forge.Command; +import forge.Constant; +import forge.Singletons; +import forge.deck.Deck; +import forge.deck.DeckGroup; +import forge.game.GameNew; +import forge.game.GameType; +import forge.game.limited.BoosterDraft; +import forge.game.limited.CardPoolLimitation; +import forge.gui.GuiUtils; +import forge.gui.deckeditor.DraftingProcess; +import forge.gui.home.ICSubmenu; +import forge.view.toolbox.FSkin; + +/** + * TODO: Write javadoc for this type. + * + */ +public enum CSubmenuDraft implements ICSubmenu { + /** */ + SINGLETON_INSTANCE; + + private final String[] opponentNames = new String[] { + "Abigail", "Ada", "Adeline", "Adriana", "Agatha", "Agnes", "Aileen", "Alba", "Alcyon", + "Alethea", "Alice", "Alicia", "Alison", "Amanda", "Amelia", "Amy", "Andrea", "Angelina", + "Anita", "Ann", "Annabel", "Anne", "Audrey", "Barbara", "Belinda", "Bernice", "Bertha", + "Bonnie", "Brenda", "Bridget", "Bunny", "Carmen", "Carol", "Catherine", "Cheryl", + "Christine", "Cinderalla", "Claire", "Clarice", "Claudia", "Constance", "Cora", + "Corinne", "Cnythia", "Daisy", "Daphne", "Dawn", "Deborah", "Diana", "Dolly", "Dora", + "Doreen", "Doris", "Dorothy", "Eileen", "Elaine", "Elizabeth", "Emily", "Emma", "Ethel", + "Evelyn", "Fiona", "Florence", "Frances", "Geraldine", "Gertrude", "Gladys", "Gloria", + "Grace", "Greta", "Harriet", "Hazel", "Helen", "Hilda", "Ida", "Ingrid", "Irene", + "Isabel", "Jacinta", "Jackie", "Jane", "Janet", "Janice", "Jennifer", "Jessie", "Joan", + "Jocelyn", "Josephine", "Joyce", "Judith", "Julia", "Juliana", "Karina", "Kathleen", + "Laura", "Lilian", "Lily", "Linda", "Lisa", "Lilita", "Lora", "Lorna", "Lucy", "Lydia", + "Mabel", "Madeline", "Maggie", "Maria", "Mariam", "Marilyn", "Mary", "Matilda", "Mavis", + "Melanie", "Melinda", "Melody", "Michelle", "Mildred", "Molly", "Mona", "Monica", + "Nancy", "Nora", "Norma", "Olga", "Pamela", "Patricia", "Paula", "Pauline", "Pearl", + "Peggy", "Penny", "Phoebe", "Phyllis", "Polly", "Priscilla", "Rachel", "Rebecca", + "Rita", "Rosa", "Rosalind", "Rose", "Rosemary", "Rowena", "Ruby", "Sally", "Samantha", + "Sarah", "Selina", "Sharon", "Sheila", "Shirley", "Sonya", "Stella", "Sue", "Susan", + "Sylvia", "Tina", "Tracy", "Ursula", "Valentine", "Valerie", "Vanessa", "Veronica", + "Victoria", "Violet", "Vivian", "Wendy", "Winnie", "Yvonne", "Aaron", "Abraham", "Adam", + "Adrain", "Alain", "Alan", "Alban", "Albert", "Alec", "Alexander", "Alfonso", "Alfred", + "Allan", "Allen", "Alonso", "Aloysius", "Alphonso", "Alvin", "Andrew", "Andy", "Amadeus", + "Amselm", "Anthony", "Arnold", "Augusta", "Austin", "Barnaby", "Benedict", "Benjamin", + "Bertie", "Bertram", "Bill", "Bob", "Boris", "Brady", "Brian", "Bruce", "Burt", "Byron", + "Calvin", "Carl", "Carter", "Casey", "Cecil", "Charles", "Christian", "Christopher", + "Clarence", "Clement", "Colin", "Conan", "Dalton", "Damian", "Daniel", "David", "Denis", + "Derek", "Desmond", "Dick", "Dominic", "Donald", "Douglas", "Duncan", "Edmund", + "Edward", "Ellen", "Elton", "Elvis", "Eric", "Eugene", "Felix", "Francis", "Frank", + "Frederick", "Gary", "Geoffrey", "George", "Gerald", "Gerry", "Gordon", "Hamish", + "Hardy", "Harold", "Harry", "Henry", "Herbert", "Ignatius", "Jack", "James", "Jeffrey", + "Jim", "Joe", "John", "Joseph", "Karl", "Keith", "Kenneth", "Kevin", "Larry", "Lawrence", + "Leonard", "Lionel", "Louis", "Lucas", "Malcolm", "Mark", "Martin", "Mathew", "Maurice", + "Max", "Melvin", "Michael", "Milton", "Morgan", "Morris", "Murphy", "Neville", + "Nicholas", "Noel", "Norman", "Oliver", "Oscar", "Patrick", "Paul", "Perkin", "Peter", + "Philip", "Ralph", "Randy", "Raymond", "Richard", "Ricky", "Robert", "Robin", "Rodney", + "Roger", "Roland", "Ronald", "Roy", "Sam", "Sebastian", "Simon", "Stanley", "Stephen", + "Stuart", "Terence", "Thomas", "Tim", "Tom", "Tony", "Victor", "Vincent", "Wallace", + "Walter", "Wilfred", "William", "Winston" + }; + + /* (non-Javadoc) + * @see forge.control.home.IControlSubmenu#update() + */ + @Override + public void initialize() { + final VSubmenuDraft view = VSubmenuDraft.SINGLETON_INSTANCE; + + view.populate(); + CSubmenuDraft.SINGLETON_INSTANCE.update(); + + VSubmenuDraft.SINGLETON_INSTANCE.getBtnBuildDeck().addMouseListener( + new MouseAdapter() { @Override + public void mousePressed(MouseEvent e) { setupDraft(); } }); + + VSubmenuDraft.SINGLETON_INSTANCE.getBtnStart().addMouseListener( + new MouseAdapter() { + @Override + public void mouseReleased(final MouseEvent e) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + startGame(); + } + }); + } + }); + + VSubmenuDraft.SINGLETON_INSTANCE.getBtnDirections().addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + view.showDirections(); + } + @Override + public void mouseEntered(MouseEvent e) { + view.getBtnDirections().setForeground(FSkin.getColor(FSkin.Colors.CLR_HOVER)); + } + @Override + public void mouseExited(MouseEvent e) { + view.getBtnDirections().setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); + } + }); + } + + /* (non-Javadoc) + * @see forge.control.home.IControlSubmenu#getCommand() + */ + @Override + public Command getMenuCommand() { + return null; + } + + /* (non-Javadoc) + * @see forge.control.home.IControlSubmenu#update() + */ + @Override + public void update() { + VSubmenuDraft.SINGLETON_INSTANCE.getLstAIDecks().setListData(generateNames()); + VSubmenuDraft.SINGLETON_INSTANCE.getLstAIDecks().setSelectedIndex( + (int) Math.floor(Math.random() * VSubmenuDraft.SINGLETON_INSTANCE.getLstAIDecks().getModel().getSize())); + + List human = new ArrayList(); + for (DeckGroup d : Singletons.getModel().getDecks().getDraft()) { + human.add(d.getHumanDeck()); + } + VSubmenuDraft.SINGLETON_INSTANCE.getLstHumanDecks().setDecks(human); + + if (human.size() > 1) { + VSubmenuDraft.SINGLETON_INSTANCE.getBtnStart().setEnabled(true); + } + } + + private void startGame() { + final Deck human = VSubmenuDraft.SINGLETON_INSTANCE.getLstHumanDecks().getSelectedDeck(); + final int aiIndex = VSubmenuDraft.SINGLETON_INSTANCE.getLstAIDecks().getSelectedIndex(); + + if (human == null) { + JOptionPane.showMessageDialog(null, + "No deck selected for human!\r\n(You may need to build a new deck.)", + "No deck", JOptionPane.ERROR_MESSAGE); + return; + } + else if (human.getMain().countAll() < 40) { + JOptionPane.showMessageDialog(null, + "The selected deck doesn't have enough cards to play (minimum 40)." + + "\r\nUse the deck editor to choose the cards you want before starting.", + "No deck", JOptionPane.ERROR_MESSAGE); + return; + } + + GuiUtils.startGameOverlay().showOverlay(); + + DeckGroup opponentDecks = Singletons.getModel().getDecks().getDraft().get(human.getName()); + + Constant.Runtime.HUMAN_DECK[0] = human; + Constant.Runtime.COMPUTER_DECK[0] = opponentDecks.getAiDecks().get(aiIndex); //zero is human deck, so it must be +1 + + if (Constant.Runtime.COMPUTER_DECK[0] == null) { + throw new IllegalStateException("Draft: Computer deck is null!"); + } + + Constant.Runtime.setGameType(GameType.Draft); + GameNew.newGame(Constant.Runtime.HUMAN_DECK[0], Constant.Runtime.COMPUTER_DECK[0]); + } + + /** */ + private void setupDraft() { + final DraftingProcess draft = new DraftingProcess(); + + // Determine what kind of booster draft to run + final ArrayList draftTypes = new ArrayList(); + draftTypes.add("Full Cardpool"); + draftTypes.add("Block / Set"); + draftTypes.add("Custom"); + + final String prompt = "Choose Draft Format:"; + final Object o = GuiUtils.getChoice(prompt, draftTypes.toArray()); + + if (o.toString().equals(draftTypes.get(0))) { + draft.showGui(new BoosterDraft(CardPoolLimitation.Full)); + } + + else if (o.toString().equals(draftTypes.get(1))) { + draft.showGui(new BoosterDraft(CardPoolLimitation.Block)); + } + + else if (o.toString().equals(draftTypes.get(2))) { + draft.showGui(new BoosterDraft(CardPoolLimitation.Custom)); + } + + } + + private String[] generateNames() { + // Generate random selection of names for display + Random generator = new Random(); + int i = opponentNames.length; + String[] ai = { + opponentNames[generator.nextInt(i)], + opponentNames[generator.nextInt(i)], + opponentNames[generator.nextInt(i)], + opponentNames[generator.nextInt(i)], + opponentNames[generator.nextInt(i)], + opponentNames[generator.nextInt(i)], + opponentNames[generator.nextInt(i)] + }; + + return ai; + } +} diff --git a/src/main/java/forge/gui/home/draft/VSubmenuDraft.java b/src/main/java/forge/gui/home/draft/VSubmenuDraft.java new file mode 100644 index 00000000000..6f4885a2f93 --- /dev/null +++ b/src/main/java/forge/gui/home/draft/VSubmenuDraft.java @@ -0,0 +1,189 @@ +package forge.gui.home.draft; + +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JTextPane; +import javax.swing.ListSelectionModel; +import javax.swing.SwingConstants; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; + +import net.miginfocom.swing.MigLayout; +import forge.Command; +import forge.game.GameType; +import forge.gui.GuiUtils; +import forge.gui.home.EMenuGroup; +import forge.gui.home.IVSubmenu; +import forge.view.home.StartButton; +import forge.view.toolbox.DeckLister; +import forge.view.toolbox.FButton; +import forge.view.toolbox.FLabel; +import forge.view.toolbox.FList; +import forge.view.toolbox.FOverlay; +import forge.view.toolbox.FPanel; +import forge.view.toolbox.FScrollPane; +import forge.view.toolbox.FSkin; + +/** + * Singleton instance of "Draft" submenu in "Constructed" group. + */ +public enum VSubmenuDraft implements IVSubmenu { + /** */ + SINGLETON_INSTANCE; + + @SuppressWarnings("serial") + private final Command cmdExit = new Command() { @Override + public void execute() { CSubmenuDraft.SINGLETON_INSTANCE.update(); } }; + + /** */ + private final JPanel pnl = new JPanel(); + private final StartButton btnStart = new StartButton(); + private final DeckLister lstHumanDecks = new DeckLister(GameType.Draft, cmdExit); + private final JList lstAI = new FList(); + private final JLabel btnBuildDeck = new FLabel.Builder() + .fontScaleAuto(false).fontSize(16) + .opaque(true).hoverable(true).text("Start A New Draft").build(); + private final JLabel btnDirections = new FLabel.Builder() + .fontScaleAuto(false).fontSize(16) + .text("Click For Directions").fontAlign(SwingConstants.CENTER).build(); + + /* (non-Javadoc) + * @see forge.view.home.IViewSubmenu#populate() + */ + @Override + public void populate() { + pnl.removeAll(); + pnl.setOpaque(false); + pnl.setLayout(new MigLayout("insets 0, gap 0, hidemode 2")); + + lstAI.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + btnStart.setEnabled(false); + + // Layout + final JLabel lblHuman = new JLabel("Select your deck: "); + lblHuman.setFont(FSkin.getBoldFont(16)); + lblHuman.setHorizontalAlignment(SwingConstants.CENTER); + lblHuman.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); + pnl.add(lblHuman, "w 60%!, gap 5% 5% 2% 2%"); + + final JLabel lblAI = new JLabel("Who will you play?"); + lblAI.setFont(FSkin.getBoldFont(16)); + lblAI.setHorizontalAlignment(SwingConstants.CENTER); + lblAI.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); + pnl.add(lblAI, "w 25%!, gap 0 0 2% 2%, wrap"); + + pnl.add(new FScrollPane(lstHumanDecks), "w 60%!, h 30%!, gap 5% 5% 2% 2%"); + + pnl.add(new FScrollPane(lstAI), "w 25%!, h 37%!, gap 0 0 2% 0, span 1 2, wrap"); + + pnl.add(btnBuildDeck, "w 60%!, h 5%!, gap 5% 5% 0 0, wrap"); + + pnl.add(btnDirections, "alignx center, span 2 1, gap 5% 5% 5% 2%, wrap"); + + pnl.add(btnStart, "gap 5% 5% 0 0, ax center, span 2 1, wrap"); + } + + /* (non-Javadoc) + * @see forge.view.home.IViewSubmenu#getGroup() + */ + @Override + public EMenuGroup getGroup() { + return null; + } + + /* (non-Javadoc) + * @see forge.view.home.IViewSubmenu#getPanel() + */ + @Override + public JPanel getPanel() { + return pnl; + } + + /** @return {@link javax.swing.JLabel} */ + public JLabel getBtnDirections() { + return this.btnDirections; + } + + /** @return {@link javax.swing.JLabel} */ + public JLabel getBtnBuildDeck() { + return this.btnBuildDeck; + } + + /** @return {@link javax.swing.JButton} */ + public JButton getBtnStart() { + return this.btnStart; + } + + /** @return {@link javax.swing.JList} */ + public JList getLstAIDecks() { + return lstAI; + } + + /** @return {@link forge.view.toolbox.DeckLister} */ + public DeckLister getLstHumanDecks() { + return lstHumanDecks; + } + + /** */ + public void showDirections() { + final FOverlay overlay = GuiUtils.genericOverlay(); + final int w = overlay.getWidth(); + + final String instructions = "BOOSTER DRAFT MODE INSTRUCTIONS" + + "\r\n\r\n" + + "In a booster draft, several players (usually eight) are seated " + + "around a table and each player is given three booster packs." + + "\r\n\r\n" + + "Each player opens a pack, selects a card from it and passes the remaining " + + "cards to his or her left. Each player then selects one of the 14 remaining " + + "cards from the pack that was just passed to him or her, and passes the " + + "remaining cards to the left again. This continues until all of the cards " + + "are depleted. The process is repeated with the second and third packs, " + + "except that the cards are passed to the right in the second pack." + + "\r\n\r\n" + + "Players then build decks out of any of the cards that they selected " + + "during the drafting and add as many basic lands as they want." + + "\r\n\r\n" + + "Credit: Wikipedia"; + + // Init directions text pane + final JTextPane tpnDirections = new JTextPane(); + tpnDirections.setOpaque(false); + tpnDirections.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); + tpnDirections.setFont(FSkin.getFont(15)); + tpnDirections.setAlignmentX(SwingConstants.CENTER); + tpnDirections.setFocusable(false); + tpnDirections.setEditable(false); + tpnDirections.setBorder(null); + tpnDirections.setText(instructions); + + final StyledDocument doc = tpnDirections.getStyledDocument(); + SimpleAttributeSet center = new SimpleAttributeSet(); + StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER); + doc.setParagraphAttributes(0, doc.getLength(), center, false); + + final JButton btnCloseBig = new FButton("OK"); + btnCloseBig.setBounds(new Rectangle((w / 2 - 100), 510, 200, 30)); + btnCloseBig.addActionListener(new ActionListener() { @Override + public void actionPerformed(ActionEvent arg0) { overlay.hideOverlay(); } }); + + final FPanel pnl = new FPanel(); + pnl.setCornerDiameter(0); + pnl.setBackgroundTexture(FSkin.getIcon(FSkin.Backgrounds.BG_TEXTURE)); + pnl.setLayout(new MigLayout("insets 0, gap 0")); + pnl.add(tpnDirections, "w 90%!, h 90%!, gap 5% 0 5% 0"); + pnl.setBounds(new Rectangle((w / 2 - 250), 80, 500, 400)); + + overlay.setLayout(null); + overlay.add(btnCloseBig); + overlay.add(pnl); + overlay.showOverlay(); + } +}