From 8bcd89d975251bbb6cf514f973c07c5b0500d88c Mon Sep 17 00:00:00 2001 From: CyB3RC0nN0R Date: Thu, 25 Jul 2019 07:21:07 +0200 Subject: [PATCH] Simplified game creation, added new configuration dialog --- src/dev/kske/chess/game/Game.java | 100 ++++++++---------- src/dev/kske/chess/ui/AIConfigDialog.java | 1 - .../chess/ui/GameConfigurationDialog.java | 82 ++++++++++++++ src/dev/kske/chess/ui/MainWindow.java | 6 +- src/dev/kske/chess/ui/MenuBar.java | 61 ++++------- 5 files changed, 151 insertions(+), 99 deletions(-) create mode 100644 src/dev/kske/chess/ui/GameConfigurationDialog.java diff --git a/src/dev/kske/chess/game/Game.java b/src/dev/kske/chess/game/Game.java index 5cf150c..8f33977 100644 --- a/src/dev/kske/chess/game/Game.java +++ b/src/dev/kske/chess/game/Game.java @@ -12,6 +12,8 @@ import dev.kske.chess.board.Piece.Color; import dev.kske.chess.game.ai.AIPlayer; import dev.kske.chess.ui.BoardComponent; import dev.kske.chess.ui.BoardPane; +import dev.kske.chess.ui.EngineUtil; +import dev.kske.chess.ui.EngineUtil.EngineInfo; import dev.kske.chess.ui.OverlayComponent; /** @@ -22,77 +24,61 @@ import dev.kske.chess.ui.OverlayComponent; */ public class Game { - private Map players; - private Board board; - private OverlayComponent overlayComponent; - private BoardComponent boardComponent; + private Map players; + private Board board; + private OverlayComponent overlayComponent; + private BoardComponent boardComponent; - public Game(Map players, BoardPane boardPane) { - this.players = players; - this.overlayComponent = boardPane.getOverlayComponent(); - this.boardComponent = boardPane.getBoardComponent(); - this.board = new Board(); + public Game(BoardPane boardPane, String whiteName, String blackName) { + players = new HashMap<>(); + board = new Board(); + overlayComponent = boardPane.getOverlayComponent(); + boardComponent = boardPane.getBoardComponent(); boardComponent.setBoard(board); + players.put(Color.WHITE, getPlayer(whiteName, Color.WHITE)); + players.put(Color.BLACK, getPlayer(blackName, Color.BLACK)); + // Initialize the game variable in each player players.values().forEach(player -> player.setGame(this)); } - public static Game createNatural(BoardPane boardPane) { - Map players = new HashMap<>(); - OverlayComponent overlay = boardPane.getOverlayComponent(); - - players.put(Color.WHITE, new NaturalPlayer(Color.WHITE, overlay)); - players.put(Color.BLACK, new NaturalPlayer(Color.BLACK, overlay)); - return new Game(players, boardPane); - } - - public static Game createNaturalVsAI(BoardPane boardPane, int maxDepth, int alphaBeta) { - Map players = new HashMap<>(); - OverlayComponent overlay = boardPane.getOverlayComponent(); - - players.put(Color.WHITE, new NaturalPlayer(Color.WHITE, overlay)); - players.put(Color.BLACK, new AIPlayer(Color.BLACK, maxDepth, alphaBeta)); - return new Game(players, boardPane); - } - - public static Game createAIVsAI(BoardPane boardPane, int maxDepthW, int maxDepthB, int alphaBetaW, int alphaBetaB) { - Map players = new HashMap<>(); - - players.put(Color.WHITE, new AIPlayer(Color.WHITE, maxDepthW, alphaBetaW)); - players.put(Color.BLACK, new AIPlayer(Color.BLACK, maxDepthB, alphaBetaB)); - return new Game(players, boardPane); - } - - public static Game createUCI(BoardPane boardPane, String enginePath) { - Map players = new HashMap<>(); - - players.put(Color.WHITE, new NaturalPlayer(Color.WHITE, boardPane.getOverlayComponent())); - players.put(Color.BLACK, new UCIPlayer(Color.BLACK, enginePath)); - return new Game(players, boardPane); + private Player getPlayer(String name, Color color) { + switch (name) { + case "Natural Player": + return new NaturalPlayer(color, overlayComponent); + case "AI Player": + return new AIPlayer(color, 4, -10); + default: + for (EngineInfo info : EngineUtil.getEngineInfos()) + if (info.name.equals(name)) return new UCIPlayer(color, info.path); + System.err.println("Invalid player name: " + name); + return null; + } } public void onMove(Player player, Move move) { if (board.getPos(move).getColor() == player.color && board.attemptMove(move)) { + // Redraw + boardComponent.repaint(); + overlayComponent.displayArrow(move); + System.out.printf("%s: %s%n", player.color, move); System.out.println("FEN: " + board.toFEN()); GameState eventType = board.getGameEventType(board.getDest(move).getColor().opposite()); switch (eventType) { - case CHECKMATE: - case STALEMATE: - String result = String.format("%s in %s!%n", player.color.opposite(), eventType); - System.out.print(result); - JOptionPane.showMessageDialog(boardComponent, result); - break; - case CHECK: - System.out.printf("%s in check!%n", player.color.opposite()); - default: - boardComponent.repaint(); - players.get(board.getActiveColor()).requestMove(); + case CHECKMATE: + case STALEMATE: + String result = String.format("%s in %s!%n", player.color.opposite(), eventType); + System.out.print(result); + JOptionPane.showMessageDialog(boardComponent, result); + break; + case CHECK: + System.out.printf("%s in check!%n", player.color.opposite()); + default: + players.get(board.getActiveColor()).requestMove(); } - overlayComponent.displayArrow(move); - } else - player.requestMove(); + } else player.requestMove(); } public void start() { @@ -116,8 +102,8 @@ public class Game { public void swapColors() { players.values().forEach(Player::cancelMove); - Player white = players.get(Color.WHITE); - Player black = players.get(Color.BLACK); + Player white = players.get(Color.WHITE); + Player black = players.get(Color.BLACK); white.setColor(Color.BLACK); black.setColor(Color.WHITE); players.put(Color.WHITE, black); diff --git a/src/dev/kske/chess/ui/AIConfigDialog.java b/src/dev/kske/chess/ui/AIConfigDialog.java index 6b7ee8d..5086f89 100644 --- a/src/dev/kske/chess/ui/AIConfigDialog.java +++ b/src/dev/kske/chess/ui/AIConfigDialog.java @@ -78,5 +78,4 @@ public class AIConfigDialog extends JDialog { public boolean isStartGame() { return startGame; } public void setStartGame(boolean startGame) { this.startGame = startGame; } - } diff --git a/src/dev/kske/chess/ui/GameConfigurationDialog.java b/src/dev/kske/chess/ui/GameConfigurationDialog.java new file mode 100644 index 0000000..8214fd6 --- /dev/null +++ b/src/dev/kske/chess/ui/GameConfigurationDialog.java @@ -0,0 +1,82 @@ +package dev.kske.chess.ui; + +import java.awt.Font; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JLabel; + +/** + * Project: Chess
+ * File: GameConfigurationDialog.java
+ * Created: 24.07.2019
+ * Author: Kai S. K. Engelbart + */ +public class GameConfigurationDialog extends JDialog { + + private static final long serialVersionUID = 9080577278529876972L; + + private String whiteName, blackName; + private boolean startGame; + + /** + * Create the dialog. + */ + public GameConfigurationDialog() { + setTitle("Game Configuration"); + setBounds(100, 100, 281, 142); + setModal(true); + setLocationRelativeTo(null); + getContentPane().setLayout(null); + + startGame = false; + List options = new ArrayList<>(Arrays.asList("Natural Player", "AI Player")); + EngineUtil.getEngineInfos().forEach(info -> options.add(info.name)); + + JLabel lblWhite = new JLabel("White:"); + lblWhite.setFont(new Font("Tahoma", Font.PLAIN, 14)); + lblWhite.setBounds(10, 11, 49, 14); + getContentPane().add(lblWhite); + + JComboBox cbWhite = new JComboBox<>(); + cbWhite.setModel(new DefaultComboBoxModel(options.toArray())); + cbWhite.setBounds(98, 9, 159, 22); + getContentPane().add(cbWhite); + + JLabel lblBlack = new JLabel("Black:"); + lblBlack.setFont(new Font("Tahoma", Font.PLAIN, 14)); + lblBlack.setBounds(10, 38, 49, 14); + getContentPane().add(lblBlack); + + JComboBox cbBlack = new JComboBox<>(); + cbBlack.setModel(new DefaultComboBoxModel(options.toArray())); + cbBlack.setBounds(98, 36, 159, 22); + getContentPane().add(cbBlack); + + JButton btnStart = new JButton("Start"); + btnStart.addActionListener((evt) -> { + startGame = true; + whiteName = options.get(cbWhite.getSelectedIndex()); + blackName = options.get(cbBlack.getSelectedIndex()); + dispose(); + }); + btnStart.setBounds(20, 73, 89, 23); + getContentPane().add(btnStart); + + JButton btnCancel = new JButton("Cancel"); + btnCancel.addActionListener((evt) -> dispose()); + btnCancel.setBounds(157, 73, 89, 23); + getContentPane().add(btnCancel); + } + + public String getWhiteName() { return whiteName; } + + public String getBlackName() { return blackName; } + + public boolean isStartGame() { return startGame; } +} diff --git a/src/dev/kske/chess/ui/MainWindow.java b/src/dev/kske/chess/ui/MainWindow.java index 29f32af..1d64376 100644 --- a/src/dev/kske/chess/ui/MainWindow.java +++ b/src/dev/kske/chess/ui/MainWindow.java @@ -54,7 +54,7 @@ public class MainWindow { * Initialize the contents of the frame. */ private void initialize() { - mframe = new JFrame(); + mframe = new JFrame("Chess by Kai S. K. Engelbart"); mframe.setResizable(true); mframe.setBounds(100, 100, 494, 565); mframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); @@ -103,7 +103,7 @@ public class MainWindow { if (this.game != null) this.game.disconnect(); this.game = game; - btnSwapColors.setEnabled(!(game.getPlayers().get(Color.WHITE) instanceof NaturalPlayer - && game.getPlayers().get(Color.BLACK) instanceof NaturalPlayer)); + btnSwapColors.setEnabled(game.getPlayers().get(Color.WHITE) instanceof NaturalPlayer + ^ game.getPlayers().get(Color.BLACK) instanceof NaturalPlayer); } } diff --git a/src/dev/kske/chess/ui/MenuBar.java b/src/dev/kske/chess/ui/MenuBar.java index aad87f7..16f7a6d 100644 --- a/src/dev/kske/chess/ui/MenuBar.java +++ b/src/dev/kske/chess/ui/MenuBar.java @@ -34,46 +34,26 @@ public class MenuBar extends JMenuBar { } private void initGameMenu() { - JMenu gameMenu = new JMenu("Game"); - - JMenuItem naturalMenuItem = new JMenuItem("Game against natural opponent"); - JMenuItem aiMenuItem = new JMenuItem("Game against artificial opponent"); - JMenuItem aiVsAiMenuItem = new JMenuItem("Watch AI vs. AI"); - JMenuItem uciMenuItem = new JMenuItem("UCI"); - - naturalMenuItem.addActionListener((evt) -> startGame(Game.createNatural(boardPane))); - - aiMenuItem.addActionListener((evt) -> { - AIConfigDialog dialog = new AIConfigDialog(); + JMenu gameMenu = new JMenu("Game"); + JMenuItem newGameMenuItem = new JMenuItem("New Game"); + newGameMenuItem.addActionListener((evt) -> { + GameConfigurationDialog dialog = new GameConfigurationDialog(); dialog.setVisible(true); - if (dialog.isStartGame()) - startGame(Game.createNaturalVsAI(boardPane, dialog.getMaxDepth(), dialog.getAlphaBetaThreshold())); + if (dialog.isStartGame()) startGame(new Game(boardPane, dialog.getWhiteName(), dialog.getBlackName())); }); - - aiVsAiMenuItem.addActionListener((evt) -> startGame(Game.createAIVsAI(boardPane, 4, 3, -10, -10))); - - uciMenuItem.addActionListener((evt) -> { - String enginePath = JOptionPane.showInputDialog(getParent(), - "Enter the path to a UCI-compatible chess engine:", - "Engine selection", - JOptionPane.QUESTION_MESSAGE); - if (enginePath != null) startGame(Game.createUCI(boardPane, enginePath)); - }); - - gameMenu.add(naturalMenuItem); - gameMenu.add(aiMenuItem); - gameMenu.add(aiVsAiMenuItem); - gameMenu.add(uciMenuItem); + gameMenu.add(newGameMenuItem); add(gameMenu); // Start a game - naturalMenuItem.doClick(); + startGame(new Game(boardPane, "Natural Player", "Natural Player")); } private void initEngineMenu() { JMenu engineMenu = new JMenu("Engine"); + // TODO: Adjust menu + JMenuItem addEngineMenuItem = new JMenuItem("Add engine"); addEngineMenuItem.addActionListener((evt) -> { String enginePath = JOptionPane.showInputDialog(getParent(), @@ -84,20 +64,25 @@ public class MenuBar extends JMenuBar { EngineUtil.addEngine(enginePath, () -> { EngineInfo info = EngineUtil.getEngineInfos() .get(EngineUtil.getEngineInfos().size() - 1); - JMenuItem engineMenuItem = new JMenuItem(info.name); - engineMenuItem.addActionListener((evt2) -> startGame(Game.createUCI(boardPane, info.path))); - engineMenu.add(engineMenuItem); + /* + * JMenuItem engineMenuItem = new JMenuItem(info.name); + * engineMenuItem.addActionListener((evt2) -> + * startGame(Game.createUCI(boardPane, info.path))); + * engineMenu.add(engineMenuItem); + */ }); } }); engineMenu.add(addEngineMenuItem); - for (EngineInfo info : EngineUtil.getEngineInfos()) { - JMenuItem engineMenuItem = new JMenuItem(info.name); - engineMenuItem.addActionListener((evt) -> startGame(Game.createUCI(boardPane, info.path))); - engineMenu.add(engineMenuItem); - } - + /* + * for (EngineInfo info : EngineUtil.getEngineInfos()) { + * JMenuItem engineMenuItem = new JMenuItem(info.name); + * engineMenuItem.addActionListener((evt) -> startGame(Game.createUCI(boardPane, + * info.path))); + * engineMenu.add(engineMenuItem); + * } + */ add(engineMenu); }