2019-07-19 22:16:02 +02:00
|
|
|
package dev.kske.chess.uci;
|
|
|
|
|
2020-01-19 22:12:33 +01:00
|
|
|
import java.io.*;
|
2019-07-31 17:47:49 +02:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
2019-07-20 06:36:56 +02:00
|
|
|
|
2019-07-31 17:47:49 +02:00
|
|
|
import dev.kske.chess.board.Move;
|
2019-07-19 22:16:02 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Project: <strong>Chess</strong><br>
|
|
|
|
* File: <strong>UCIReceiver.java</strong><br>
|
|
|
|
* Created: <strong>19.07.2019</strong><br>
|
2020-01-19 22:12:33 +01:00
|
|
|
*
|
2019-10-26 07:55:21 +02:00
|
|
|
* @since Chess v0.3-alpha
|
|
|
|
* @author Kai S. K. Engelbart
|
2019-07-19 22:16:02 +02:00
|
|
|
*/
|
|
|
|
public class UCIReceiver implements Runnable {
|
|
|
|
|
|
|
|
private final BufferedReader in;
|
|
|
|
|
2019-07-31 17:47:49 +02:00
|
|
|
private List<UCIListener> listeners;
|
2019-07-19 22:16:02 +02:00
|
|
|
|
2020-01-19 22:12:33 +01:00
|
|
|
/**
|
|
|
|
* Creates an instance of {@link UCIReceiver}.
|
|
|
|
*
|
|
|
|
* @param in the input stream to parse for commands generated by the engine
|
|
|
|
*/
|
2019-07-19 22:16:02 +02:00
|
|
|
public UCIReceiver(InputStream in) {
|
2020-05-19 16:50:12 +02:00
|
|
|
this.in = new BufferedReader(new InputStreamReader(in));
|
|
|
|
listeners = new ArrayList<>();
|
2019-07-19 22:16:02 +02:00
|
|
|
}
|
|
|
|
|
2020-01-19 22:12:33 +01:00
|
|
|
/**
|
|
|
|
* Starts listening for UCI commands passed through the input stream.
|
|
|
|
*/
|
2019-07-19 22:16:02 +02:00
|
|
|
@Override
|
|
|
|
public void run() {
|
2019-07-22 07:29:58 +02:00
|
|
|
String line;
|
|
|
|
while (!Thread.currentThread().isInterrupted())
|
|
|
|
try {
|
2020-05-19 16:50:12 +02:00
|
|
|
if ((line = in.readLine()) != null && !line.isEmpty())
|
|
|
|
parse(line);
|
2019-07-22 07:29:58 +02:00
|
|
|
} catch (IndexOutOfBoundsException ex) {
|
|
|
|
System.err.println("Too few arguments were provided!");
|
|
|
|
ex.printStackTrace();
|
|
|
|
} catch (IOException ex) {
|
|
|
|
ex.printStackTrace();
|
|
|
|
}
|
2019-07-19 22:16:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void parse(String line) {
|
2020-05-19 16:50:12 +02:00
|
|
|
int spaceIndex = line.indexOf(' ');
|
|
|
|
String command
|
|
|
|
= spaceIndex == -1 ? line : line.substring(0, spaceIndex);
|
2019-07-19 22:16:02 +02:00
|
|
|
switch (command) {
|
|
|
|
case "id":
|
|
|
|
parseId(line.substring(command.length() + 1));
|
|
|
|
break;
|
|
|
|
case "uciok":
|
2019-07-31 17:47:49 +02:00
|
|
|
listeners.forEach(UCIListener::onUCIOk);
|
2019-07-19 22:16:02 +02:00
|
|
|
break;
|
|
|
|
case "readyok":
|
2019-07-31 17:47:49 +02:00
|
|
|
listeners.forEach(UCIListener::onReadyOk);
|
2019-07-19 22:16:02 +02:00
|
|
|
break;
|
2019-07-22 14:51:24 +02:00
|
|
|
case "bestmove":
|
|
|
|
parseBestMove(line.substring(command.length() + 1));
|
|
|
|
break;
|
2019-07-19 22:16:02 +02:00
|
|
|
case "copyprotection":
|
|
|
|
parseCopyProtection(line.substring(command.length() + 1));
|
|
|
|
break;
|
|
|
|
case "registration":
|
|
|
|
parseRegistration(line.substring(command.length() + 1));
|
|
|
|
break;
|
2019-07-20 06:36:56 +02:00
|
|
|
case "info":
|
|
|
|
parseInfo(line.substring(command.length() + 1));
|
|
|
|
break;
|
|
|
|
case "option":
|
|
|
|
parseOption(line.substring(command.length() + 1));
|
|
|
|
break;
|
2019-07-19 22:16:02 +02:00
|
|
|
default:
|
|
|
|
System.err.printf("Unknown command '%s' found!%n", command);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void parseId(String line) {
|
2020-05-19 16:50:12 +02:00
|
|
|
String param = line.substring(0, line.indexOf(' '));
|
|
|
|
String arg = line.substring(param.length() + 1);
|
2019-07-21 14:35:14 +02:00
|
|
|
switch (param) {
|
2019-07-19 22:16:02 +02:00
|
|
|
case "name":
|
2019-07-31 17:47:49 +02:00
|
|
|
listeners.forEach(l -> l.onIdName(arg));
|
2019-07-19 22:16:02 +02:00
|
|
|
break;
|
|
|
|
case "author":
|
2019-07-31 17:47:49 +02:00
|
|
|
listeners.forEach(l -> l.onIdAuthor(arg));
|
2019-07-19 22:16:02 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-05-19 16:50:12 +02:00
|
|
|
System.err.printf(
|
|
|
|
"Unknown parameter '%s' for command 'id' found!%n",
|
|
|
|
param
|
|
|
|
);
|
2019-07-19 22:16:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-22 14:51:24 +02:00
|
|
|
private void parseBestMove(String line) {
|
2020-05-19 16:50:12 +02:00
|
|
|
String[] tokens = line.split(" ");
|
|
|
|
String move = tokens[0];
|
2019-07-22 14:51:24 +02:00
|
|
|
|
|
|
|
// Ponder move
|
2020-05-19 16:50:12 +02:00
|
|
|
if (tokens.length == 3)
|
|
|
|
listeners.forEach(l -> l.onBestMove(move, Move.fromLAN(tokens[2])));
|
|
|
|
else
|
|
|
|
listeners.forEach(l -> l.onBestMove(move));
|
2019-07-22 14:51:24 +02:00
|
|
|
}
|
|
|
|
|
2019-07-19 22:16:02 +02:00
|
|
|
private void parseCopyProtection(String line) {
|
|
|
|
switch (line) {
|
|
|
|
case "checking":
|
2019-07-31 17:47:49 +02:00
|
|
|
listeners.forEach(UCIListener::onCopyProtectionChecking);
|
2019-07-19 22:16:02 +02:00
|
|
|
break;
|
|
|
|
case "ok":
|
2019-07-31 17:47:49 +02:00
|
|
|
listeners.forEach(UCIListener::onCopyProtectionOk);
|
2019-07-19 22:16:02 +02:00
|
|
|
break;
|
|
|
|
case "error":
|
2019-07-31 17:47:49 +02:00
|
|
|
listeners.forEach(UCIListener::onCopyProtectionError);
|
2019-07-19 22:16:02 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-05-19 16:50:12 +02:00
|
|
|
System.err.printf(
|
|
|
|
"Unknown parameter '%s' for command 'copyprotection' found!%n",
|
|
|
|
line
|
|
|
|
);
|
2019-07-19 22:16:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void parseRegistration(String line) {
|
|
|
|
switch (line) {
|
|
|
|
case "checking":
|
2019-07-31 17:47:49 +02:00
|
|
|
listeners.forEach(UCIListener::onRegistrationChecking);
|
2019-07-19 22:16:02 +02:00
|
|
|
break;
|
|
|
|
case "ok":
|
2019-07-31 17:47:49 +02:00
|
|
|
listeners.forEach(UCIListener::onRegistrationOk);
|
2019-07-19 22:16:02 +02:00
|
|
|
break;
|
|
|
|
case "error":
|
2019-07-31 17:47:49 +02:00
|
|
|
listeners.forEach(UCIListener::onRegistrationError);
|
2019-07-19 22:16:02 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-05-19 16:50:12 +02:00
|
|
|
System.err.printf(
|
|
|
|
"Unknown parameter '%s' for command 'registration' found!%n",
|
|
|
|
line
|
|
|
|
);
|
2019-07-19 22:16:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-19 16:50:12 +02:00
|
|
|
private void parseInfo(String line) {
|
|
|
|
listeners.forEach(l -> l.onInfo(new UCIInfo(line)));
|
|
|
|
}
|
2019-07-20 06:36:56 +02:00
|
|
|
|
2020-05-19 16:50:12 +02:00
|
|
|
private void parseOption(String line) {
|
|
|
|
listeners.forEach(l -> l.onOption(new UCIOption(line)));
|
|
|
|
}
|
2019-07-20 06:36:56 +02:00
|
|
|
|
2020-01-19 22:12:33 +01:00
|
|
|
/**
|
|
|
|
* Registers a UCI listener
|
|
|
|
*
|
|
|
|
* @param listener the UCI listener to register
|
|
|
|
*/
|
2020-05-19 16:50:12 +02:00
|
|
|
public void registerListener(UCIListener listener) {
|
|
|
|
listeners.add(listener);
|
|
|
|
}
|
2019-07-19 22:16:02 +02:00
|
|
|
}
|