From 9014731426ed6e4a32e88e13a58e02f79e46f4df Mon Sep 17 00:00:00 2001 From: CyB3RC0nN0R Date: Fri, 19 Jul 2019 22:16:02 +0200 Subject: [PATCH] Added UCIReceiver and UCIListner, implemented a part of the UCI protocol --- src/dev/kske/chess/game/UCIPlayer.java | 2 +- src/dev/kske/chess/uci/UCIHandle.java | 101 ++++++++++++--------- src/dev/kske/chess/uci/UCIListener.java | 104 ++++++++++++++++++++++ src/dev/kske/chess/uci/UCIReceiver.java | 111 ++++++++++++++++++++++++ 4 files changed, 277 insertions(+), 41 deletions(-) create mode 100644 src/dev/kske/chess/uci/UCIListener.java create mode 100644 src/dev/kske/chess/uci/UCIReceiver.java diff --git a/src/dev/kske/chess/game/UCIPlayer.java b/src/dev/kske/chess/game/UCIPlayer.java index bb1bde3..1cdbb70 100644 --- a/src/dev/kske/chess/game/UCIPlayer.java +++ b/src/dev/kske/chess/game/UCIPlayer.java @@ -35,6 +35,6 @@ public class UCIPlayer extends Player { } public void disconnect() { - + handle.quit(); } } diff --git a/src/dev/kske/chess/uci/UCIHandle.java b/src/dev/kske/chess/uci/UCIHandle.java index 84d13f4..5b4b547 100644 --- a/src/dev/kske/chess/uci/UCIHandle.java +++ b/src/dev/kske/chess/uci/UCIHandle.java @@ -1,8 +1,6 @@ package dev.kske.chess.uci; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; import java.io.PrintWriter; /** @@ -14,60 +12,83 @@ import java.io.PrintWriter; public class UCIHandle { private final Process process; - private final BufferedReader in; private final PrintWriter out; + private final UCIReceiver receiver; private String name, author; public UCIHandle(String enginePath) throws IOException { process = new ProcessBuilder(enginePath).start(); - in = new BufferedReader(new InputStreamReader(process.getInputStream())); out = new PrintWriter(process.getOutputStream()); + receiver = new UCIReceiver(process.getInputStream()); } - public void processInput() { - try { - while (in.ready()) - parse(in.readLine()); - } catch (IndexOutOfBoundsException ex) { - System.err.println("Too few arguments were provided!"); - ex.printStackTrace(); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - - private void parse(String line) { - String command = line.substring(0, line.indexOf(' ')); - switch (command) { - case "id": - parseId(line.substring(command.length() + 1)); - break; - default: - System.err.printf("Unknown command '%s' found!%n", command); - } - } - - private void parseId(String line) { - String param = line.substring(line.indexOf(' ')); - String arg = line.substring(param.length() + 1); - switch (line) { - case "name": - name = arg; - break; - case "author": - author = arg; - break; - default: - System.err.printf("Unknown parameter '%s' for command 'id' found!%n", param); - } + public void start() { + uci(); + new Thread(receiver).start(); } + /** + * Tells the engine to use UCI. + */ public void uci() { out.println("uci"); } + /** + * Switches the debug mode of the engine on or off. + * + * @param debug Enables debugging if set to {@code true}, disables it otherwise + */ + public void debug(boolean debug) { + out.println("debug " + (debug ? "on" : "off")); + } + + /** + * Synchronized the engine with the GUI + */ + public void isready() { + out.println("isready"); + } + + /** + * Registers the engine + * + * @param name The name the engine should be registered with + * @param code The code the engine should be registered with + */ + public void register(String name, String code) { + out.printf("register %s %s%n", name, code); + } + + /** + * Tells the engine to postpone the registration. + */ + public void registerLater() { + out.println("register later"); + } + + /** + * Stops calculation as soon as possible. + */ + public void stop() { + out.println("stop"); + } + + /** + * Quits the engine process as soon as possible. + */ + public void quit() { + out.println("quit"); + } + + /** + * @return The name of the engine + */ public String getName() { return name; } + /** + * @return The author of the engine + */ public String getAuthor() { return author; } } diff --git a/src/dev/kske/chess/uci/UCIListener.java b/src/dev/kske/chess/uci/UCIListener.java new file mode 100644 index 0000000..c7cd17d --- /dev/null +++ b/src/dev/kske/chess/uci/UCIListener.java @@ -0,0 +1,104 @@ +package dev.kske.chess.uci; + +import java.util.Map; + +/** + * Project: Chess
+ * File: UCIListener.java
+ * Created: 19.07.2019
+ * Author: Kai S. K. Engelbart + */ +public interface UCIListener { + + /** + * Identifies the name of the engine. + * + * @param name The name of the engine + */ + void onIdName(String name); + + /** + * Identifies the author of the engine. + * + * @param author The name of the engine's author + */ + void onIdAuthor(String author); + + /** + * The engine is ready in UCI mode. + */ + void onUCIOk(); + + /** + * The engine has processed all inputs and is ready for new commands. + */ + void onReadyOk(); + + /** + * The engine has stopped searching and has found the best move. + * + * @param move The best moves the engine has found + */ + void onBestMove(String move); + + /** + * The engine has stopped searching and has found the best move. + * + * @param move The best move the engine has found + * @param ponderMove The move the engine likes to ponder on + */ + void onBestMove(String move, String ponderMove); + + /** + * The engine will check the copy protection now. + */ + void onCopyProtectionChecking(); + + /** + * The engine has successfully checked the copy protection. + */ + void onCopyProtectionOk(); + + /** + * The engine has encountered an error during copy protection checking. + */ + void onCopyProtectionError(); + + /** + * The engine will check the registration now. + */ + void onRegistrationChecking(); + + /** + * The engine has successfully checked the registration. + */ + void onRegistrationOk(); + + /** + * The engine has encountered an error during registration checking. + */ + void onRegistrationError(); + + /** + * The engine sends information to the GUI. + * + * @param additionalInfo Contains all pieces of information to be sent + */ + void onInfo(Map additionalInfo); + + /** + * Tells the GUI which parameters can be changed in the engine. + * + * @param name The name of the option + * @param type The GUI component through which the option should be set + * @param defaultVal The default value of this parameter + * @param minVal The minimum value of this parameter + * @param maxVal The maximum value of this parameter + * @param var A predefined value of this parameter + */ + void onOption(String name, GUIType type, String defaultVal, String minVal, String maxVal, String var); + + public static enum GUIType { + CHECK, SPIN, COMBO, BUTTON, STRING + } +} diff --git a/src/dev/kske/chess/uci/UCIReceiver.java b/src/dev/kske/chess/uci/UCIReceiver.java new file mode 100644 index 0000000..8610e69 --- /dev/null +++ b/src/dev/kske/chess/uci/UCIReceiver.java @@ -0,0 +1,111 @@ +package dev.kske.chess.uci; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** + * Project: Chess
+ * File: UCIReceiver.java
+ * Created: 19.07.2019
+ * Author: Kai S. K. Engelbart + */ +public class UCIReceiver implements Runnable { + + private final BufferedReader in; + + private UCIListener listener; + + public UCIReceiver(InputStream in) { + this.in = new BufferedReader(new InputStreamReader(in)); + } + + @Override + public void run() { + try { + while (in.ready()) + parse(in.readLine()); + } catch (IndexOutOfBoundsException ex) { + System.err.println("Too few arguments were provided!"); + ex.printStackTrace(); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + private void parse(String line) { + String command = line.substring(0, line.indexOf(' ')); + switch (command) { + case "id": + parseId(line.substring(command.length() + 1)); + break; + case "uciok": + listener.onUCIOk(); + break; + case "readyok": + listener.onReadyOk(); + break; + // TODO: bestmove + case "copyprotection": + parseCopyProtection(line.substring(command.length() + 1)); + break; + case "registration": + parseRegistration(line.substring(command.length() + 1)); + break; + // TODO: info + // TODO: option + default: + System.err.printf("Unknown command '%s' found!%n", command); + } + } + + private void parseId(String line) { + String param = line.substring(line.indexOf(' ')); + String arg = line.substring(param.length() + 1); + switch (line) { + case "name": + listener.onIdName(arg); + break; + case "author": + listener.onIdAuthor(arg); + break; + default: + System.err.printf("Unknown parameter '%s' for command 'id' found!%n", param); + } + } + + private void parseCopyProtection(String line) { + switch (line) { + case "checking": + listener.onCopyProtectionChecking(); + break; + case "ok": + listener.onCopyProtectionOk(); + break; + case "error": + listener.onCopyProtectionError(); + break; + default: + System.err.printf("Unknown parameter '%s' for command 'copyprotection' found!%n", line); + } + } + + private void parseRegistration(String line) { + switch (line) { + case "checking": + listener.onRegistrationChecking(); + break; + case "ok": + listener.onRegistrationOk(); + break; + case "error": + listener.onRegistrationError(); + break; + default: + System.err.printf("Unknown parameter '%s' for command 'registration' found!%n", line); + } + } + + public void setListener(UCIListener listener) { this.listener = listener; } +}