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; }
+}