package dev.kske.chess.uci; import java.io.*; import java.util.ArrayList; import java.util.List; import dev.kske.chess.board.Move; /** * Project: Chess
* File: UCIReceiver.java
* Created: 19.07.2019
* * @since Chess v0.3-alpha * @author Kai S. K. Engelbart */ public class UCIReceiver implements Runnable { private final BufferedReader in; private List listeners; /** * Creates an instance of {@link UCIReceiver}. * * @param in the input stream to parse for commands generated by the engine */ public UCIReceiver(InputStream in) { this.in = new BufferedReader(new InputStreamReader(in)); listeners = new ArrayList<>(); } /** * Starts listening for UCI commands passed through the input stream. */ @Override public void run() { String line; while (!Thread.currentThread().isInterrupted()) try { if ((line = in.readLine()) != null && !line.isEmpty()) 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": listeners.forEach(UCIListener::onUCIOk); break; case "readyok": listeners.forEach(UCIListener::onReadyOk); break; case "bestmove": parseBestMove(line.substring(command.length() + 1)); break; 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": listeners.forEach(l -> l.onIdName(arg)); break; case "author": listeners.forEach(l -> l.onIdAuthor(arg)); break; default: System.err.printf( "Unknown parameter '%s' for command 'id' found!%n", param ); } } private void parseBestMove(String line) { String[] tokens = line.split(" "); String move = tokens[0]; // Ponder move if (tokens.length == 3) listeners.forEach(l -> l.onBestMove(move, Move.fromLAN(tokens[2]))); else listeners.forEach(l -> l.onBestMove(move)); } private void parseCopyProtection(String line) { switch (line) { case "checking": listeners.forEach(UCIListener::onCopyProtectionChecking); break; case "ok": listeners.forEach(UCIListener::onCopyProtectionOk); break; case "error": listeners.forEach(UCIListener::onCopyProtectionError); break; default: System.err.printf( "Unknown parameter '%s' for command 'copyprotection' found!%n", line ); } } private void parseRegistration(String line) { switch (line) { case "checking": listeners.forEach(UCIListener::onRegistrationChecking); break; case "ok": listeners.forEach(UCIListener::onRegistrationOk); break; case "error": listeners.forEach(UCIListener::onRegistrationError); break; default: System.err.printf( "Unknown parameter '%s' for command 'registration' found!%n", line ); } } private void parseInfo(String line) { listeners.forEach(l -> l.onInfo(new UCIInfo(line))); } private void parseOption(String line) { listeners.forEach(l -> l.onOption(new UCIOption(line))); } /** * Registers a UCI listener * * @param listener the UCI listener to register */ public void registerListener(UCIListener listener) { listeners.add(listener); } }