From 5aa48edb93931611218d3dcb8354a3eae43d04c2 Mon Sep 17 00:00:00 2001 From: kske Date: Tue, 23 Jul 2019 16:28:53 +0200 Subject: [PATCH] Added engine info serialization and integration into MenuBar --- .gitignore | 1 + src/dev/kske/chess/board/Board.java | 9 ++- src/dev/kske/chess/ui/EngineUtil.java | 87 +++++++++++++++++++-------- src/dev/kske/chess/ui/LogFrame.java | 13 +--- src/dev/kske/chess/ui/MenuBar.java | 44 ++++++++------ 5 files changed, 96 insertions(+), 58 deletions(-) diff --git a/.gitignore b/.gitignore index 91e622d..1948207 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ local.properties # Annotation Processing .apt_generated/ +/engine_infos.ser diff --git a/src/dev/kske/chess/board/Board.java b/src/dev/kske/chess/board/Board.java index 88cb298..a507405 100644 --- a/src/dev/kske/chess/board/Board.java +++ b/src/dev/kske/chess/board/Board.java @@ -144,11 +144,7 @@ public class Board implements Cloneable { // Update the king's position if the moved piece is the king and castling // availability - if (piece.getType() == Type.KING) { - kingPos.put(piece.getColor(), move.dest); - castlingRights.get(piece.getColor()).put(Type.KING, false); - castlingRights.get(piece.getColor()).put(Type.QUEEN, false); - } + if (piece.getType() == Type.KING) kingPos.put(piece.getColor(), move.dest); // Update log log.add(move, capturePiece); @@ -162,6 +158,9 @@ public class Board implements Cloneable { // Increment halfmove clock ++halfmoveClock; + // Reset halfmove clock + if (piece.getType() == Type.PAWN || capturePiece != null) halfmoveClock = 0; + updateCastlingRights(); } diff --git a/src/dev/kske/chess/ui/EngineUtil.java b/src/dev/kske/chess/ui/EngineUtil.java index 41b8ef8..b56c416 100644 --- a/src/dev/kske/chess/ui/EngineUtil.java +++ b/src/dev/kske/chess/ui/EngineUtil.java @@ -1,6 +1,11 @@ package dev.kske.chess.ui; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -17,45 +22,77 @@ public class EngineUtil { private static volatile List engineInfos; + private static final String engineInfoFile = "engine_infos.ser"; + static { - engineInfos = new ArrayList<>(); + loadEngineInfos(); } private EngineUtil() {} public static void addEngine(String enginePath) { - try { - EngineInfo info = new EngineInfo(enginePath); - UCIHandle handle = new UCIHandle(enginePath); - handle.setListener(new UCIListener() { + try { + EngineInfo info = new EngineInfo(enginePath); + UCIHandle handle = new UCIHandle(enginePath); + handle.setListener(new UCIListener() { - @Override - public void onIdName(String name) { - info.name = name; - } + @Override + public void onIdName(String name) { + info.name = name; + } - @Override - public void onIdAuthor(String author) { - info.author = author; - } - - @Override - public void onUCIOk() { - engineInfos.add(info); - System.out.println("Engine: " + info.name); - } - }); - handle.start(); - } catch (IOException ex) { - ex.printStackTrace(); - } + @Override + public void onIdAuthor(String author) { + info.author = author; + } + + @Override + public void onUCIOk() { + engineInfos.add(info); + handle.quit(); + saveEngineInfos(); + } + }); + handle.start(); + } catch (IOException ex) { + ex.printStackTrace(); + } } - public static class EngineInfo { + @SuppressWarnings("unchecked") + private static void loadEngineInfos() { + try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(engineInfoFile))) { + Object obj = in.readObject(); + if (obj instanceof ArrayList) engineInfos = (ArrayList) obj; + else throw new IOException("Serialized object has the wrong class."); + } catch (ClassNotFoundException | IOException ex) { + engineInfos = new ArrayList<>(); + } + } + + private static void saveEngineInfos() { + try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(engineInfoFile))) { + out.writeObject(engineInfos); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + public static class EngineInfo implements Serializable { + + private static final long serialVersionUID = -474177108900833005L; + public String path, name, author; public EngineInfo(String path) { this.path = path; } + + @Override + public String toString() { + return name + " by " + author + " at " + path; + } } + + public static List getEngineInfos() { return engineInfos; } } diff --git a/src/dev/kske/chess/ui/LogFrame.java b/src/dev/kske/chess/ui/LogFrame.java index cabcabc..79b885e 100644 --- a/src/dev/kske/chess/ui/LogFrame.java +++ b/src/dev/kske/chess/ui/LogFrame.java @@ -8,7 +8,7 @@ import javax.swing.JTable; import javax.swing.border.EmptyBorder; import javax.swing.table.DefaultTableModel; -import dev.kske.chess.board.Log; +import dev.kske.chess.board.Move; /** * Project: Chess
@@ -23,8 +23,6 @@ public class LogFrame extends JFrame { private JPanel mcontentPane; private JTable mtable; - private Log log; - /** * Create the frame. */ @@ -38,17 +36,12 @@ public class LogFrame extends JFrame { setContentPane(mcontentPane); mtable = new JTable(); - mtable.setModel(new DefaultTableModel(new Object[][] {}, new String[] { "Black", "New column" })); + mtable.setModel(new DefaultTableModel(new Object[][] {}, new String[] { "White", "Black" })); mtable.setEnabled(false); mcontentPane.add(mtable, BorderLayout.CENTER); } - public void update() { + public void add(Move move) { } - - public Log getLog() { return log; } - - public void setLog(Log log) { this.log = log; } - } diff --git a/src/dev/kske/chess/ui/MenuBar.java b/src/dev/kske/chess/ui/MenuBar.java index 4be983d..b1fd6b3 100644 --- a/src/dev/kske/chess/ui/MenuBar.java +++ b/src/dev/kske/chess/ui/MenuBar.java @@ -6,6 +6,7 @@ import javax.swing.JMenuItem; import javax.swing.JOptionPane; import dev.kske.chess.game.Game; +import dev.kske.chess.ui.EngineUtil.EngineInfo; /** * Project: Chess
@@ -17,12 +18,12 @@ public class MenuBar extends JMenuBar { private static final long serialVersionUID = -7221583703531248228L; - private final MainWindow mainWindow; - private final BoardPane boardPane; + private final MainWindow mainWindow; + private final BoardPane boardPane; public MenuBar(MainWindow mainWindow) { - this.mainWindow = mainWindow; - boardPane = mainWindow.getBoardPane(); + this.mainWindow = mainWindow; + boardPane = mainWindow.getBoardPane(); initGameMenu(); initEngineMenu(); @@ -31,10 +32,10 @@ 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"); + 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))); @@ -49,10 +50,10 @@ public class MenuBar extends JMenuBar { uciMenuItem.addActionListener((evt) -> { String enginePath = JOptionPane.showInputDialog(getParent(), - "Enter the path to a UCI-compatible chess engine:", "Engine selection", + "Enter the path to a UCI-compatible chess engine:", + "Engine selection", JOptionPane.QUESTION_MESSAGE); - if (enginePath != null) - startGame(Game.createUCI(boardPane, enginePath)); + if (enginePath != null) startGame(Game.createUCI(boardPane, enginePath)); }); gameMenu.add(naturalMenuItem); @@ -68,22 +69,29 @@ public class MenuBar extends JMenuBar { private void initEngineMenu() { JMenu engineMenu = new JMenu("Engine"); - + JMenuItem addEngineMenuItem = new JMenuItem("Add engine"); - addEngineMenuItem.addActionListener((evt) -> { String enginePath = JOptionPane.showInputDialog(getParent(), - "Enter the path to a UCI-compatible chess engine:", "Engine selection", + "Enter the path to a UCI-compatible chess engine:", + "Engine selection", JOptionPane.QUESTION_MESSAGE); - if(enginePath != null) + if (enginePath != null) { EngineUtil.addEngine(enginePath); + // TODO: Rebuilt the engine menu + } }); - 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); + } + add(engineMenu); } - + private void startGame(Game game) { mainWindow.setGame(game);