196 lines
5.1 KiB
Java
196 lines
5.1 KiB
Java
package dev.kske.chess.uci;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.StringJoiner;
|
|
|
|
import dev.kske.chess.uci.UCIListener.GUIType;
|
|
|
|
/**
|
|
* Project: <strong>Chess</strong><br>
|
|
* File: <strong>UCIReceiver.java</strong><br>
|
|
* Created: <strong>19.07.2019</strong><br>
|
|
* Author: <strong>Kai S. K. Engelbart</strong>
|
|
*/
|
|
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() {
|
|
String line;
|
|
while (!Thread.currentThread().isInterrupted())
|
|
try {
|
|
if ((line = in.readLine()) != null && !line.isBlank()) parse(line);
|
|
} catch (IndexOutOfBoundsException ex) {
|
|
System.err.println("Too few arguments were provided!");
|
|
ex.printStackTrace();
|
|
} catch (IOException ex) {
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
|
|
private void parse(String line) {
|
|
int spaceIndex = line.indexOf(' ');
|
|
String command = spaceIndex == -1 ? line : line.substring(0, spaceIndex);
|
|
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;
|
|
case "info":
|
|
parseInfo(line.substring(command.length() + 1));
|
|
break;
|
|
case "option":
|
|
parseOption(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(0, line.indexOf(' '));
|
|
String arg = line.substring(param.length() + 1);
|
|
switch (param) {
|
|
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);
|
|
}
|
|
}
|
|
|
|
private void parseInfo(String line) {
|
|
String[] tokens = line.split(" ");
|
|
Map<String, String> additionalInfo = new HashMap<>();
|
|
|
|
for (int i = 0; i < tokens.length; i++)
|
|
switch (tokens[i]) {
|
|
// Single parameter info
|
|
case "depth":
|
|
case "seldepth":
|
|
case "time":
|
|
case "nodes":
|
|
case "multipv":
|
|
case "currmove":
|
|
case "currmovenumber":
|
|
case "hashfull":
|
|
case "nps":
|
|
case "tbhits":
|
|
case "sbhits":
|
|
case "cpuload":
|
|
case "string":
|
|
additionalInfo.put(tokens[i], tokens[++i]);
|
|
break;
|
|
// TODO: pv
|
|
// TODO: score
|
|
// TODO: refutation
|
|
// TODO: currline
|
|
default:
|
|
System.err.printf("Unknown parameter '%s' for command 'info' found!%n", tokens[i]);
|
|
}
|
|
listener.onInfo(additionalInfo);
|
|
}
|
|
|
|
private void parseOption(String line) {
|
|
String[] tokens = line.split(" ");
|
|
|
|
StringJoiner name = new StringJoiner(" ");
|
|
GUIType type = null;
|
|
String defaultVal = null;
|
|
String minVal = null;
|
|
String maxVal = null;
|
|
List<String> var = new ArrayList<>();
|
|
|
|
for (int i = 0; i < tokens.length; i++)
|
|
switch (tokens[i]) {
|
|
case "name":
|
|
while (!Arrays.asList("type", "default", "min", "max", "var").contains(tokens[i + 1]))
|
|
name.add(tokens[++i]);
|
|
break;
|
|
case "type":
|
|
type = GUIType.valueOf(tokens[++i].toUpperCase());
|
|
break;
|
|
case "default":
|
|
// Default string may be empty
|
|
defaultVal = i == tokens.length - 1 ? "" : tokens[++i];
|
|
break;
|
|
case "min":
|
|
minVal = tokens[++i];
|
|
break;
|
|
case "max":
|
|
maxVal = tokens[++i];
|
|
break;
|
|
case "var":
|
|
var.add(tokens[++i]);
|
|
break;
|
|
default:
|
|
System.err.printf("Unknown parameter '%s' for command 'option' found!%n", tokens[i]);
|
|
}
|
|
listener.onOption(name.toString(), type, defaultVal, minVal, maxVal, var);
|
|
}
|
|
|
|
public void setListener(UCIListener listener) { this.listener = listener; }
|
|
}
|