Skip to content

Commit

Permalink
Continues UCI client implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
fathzer committed Feb 3, 2024
1 parent 313d4f5 commit b28395c
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 18 deletions.
6 changes: 5 additions & 1 deletion src/main/java/com/fathzer/jchess/bot/Engine.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
public interface Engine {
String getName();
List<Option<?>> getOptions();
void newGame();
/** Starts a new game.
* @param variant The game variant
* @return false if the variant is not supported
*/
boolean newGame(Variant variant);
void setPosition(String startpos, List<Move> moves);
Move play(PlayParameters params);
}
4 changes: 3 additions & 1 deletion src/main/java/com/fathzer/jchess/bot/PlayParameters.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.fathzer.jchess.bot;

public interface PlayParameters {

long getRemainingMs();
long getIncrementMs();
long getMovesToGo();
}
5 changes: 5 additions & 0 deletions src/main/java/com/fathzer/jchess/bot/Variant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.fathzer.jchess.bot;

public enum Variant {
STANDARD, CHESS_960
}
10 changes: 6 additions & 4 deletions src/main/java/com/fathzer/jchess/bot/uci/StdErrReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,31 @@
import java.io.Closeable;
import java.io.EOFException;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;

class StdErrReader implements Closeable, Runnable {
private final BufferedReader errorReader;
private final Thread spyThread;
private boolean stopped;
private final AtomicBoolean stopped;

StdErrReader(Process process) {
this.errorReader = process.errorReader();
this.stopped = new AtomicBoolean();
this.spyThread = new Thread(this);
this.spyThread.setDaemon(true);
this.spyThread.start();
}

@Override
public void run() {
while (!stopped) {
while (!stopped.get()) {
try {
final String line = errorReader.readLine();
if (line!=null) {
System.err.println (line); //TODO
}
} catch (EOFException e) {
if (!stopped) {
if (!stopped.get()) {
log(e);
}
} catch (IOException e) {
Expand All @@ -44,7 +46,7 @@ private void log(IOException e) {

@Override
public void close() throws IOException {
this.stopped = true;
this.stopped.set(true);
this.errorReader.close();
}
}
58 changes: 46 additions & 12 deletions src/main/java/com/fathzer/jchess/bot/uci/UCIEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,31 @@
import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;

import com.fathzer.jchess.bot.Engine;
import com.fathzer.jchess.bot.Move;
import com.fathzer.jchess.bot.Option;
import com.fathzer.jchess.bot.PlayParameters;
import com.fathzer.jchess.bot.Variant;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class UCIEngine implements Closeable, Engine {
private static final String CHESS960_OPTION = "UCI_Chess960";
private final Process process;
private final String name;
private final BufferedReader reader;
private final BufferedWriter writer;
private final StdErrReader errorReader;
private final List<Option<?>> options;
private boolean is960Supported;

public UCIEngine(String path) throws IOException {
log.info ("Launching process {}",path);
Expand Down Expand Up @@ -68,16 +73,24 @@ private Option<?> parseOption(String[] tokens) throws IOException {
return null;
}

private void write(String line) throws IOException {
this.writer.write(line);
this.writer.newLine();
this.writer.flush();
log.info("> " + line);
private void write(String line) {
try {
this.writer.write(line);
this.writer.newLine();
this.writer.flush();
log.info("> " + line);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private String read() throws IOException {
final String line = reader.readLine();
log.info("< " + line);
return line;
private String read() {
try {
final String line = reader.readLine();
log.info("< " + line);
return line;
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

@Override
Expand All @@ -91,9 +104,30 @@ public List<Option<?>> getOptions() {
}

@Override
public void newGame() {
// TODO Auto-generated method stub

public boolean newGame(Variant variant) {
if (variant==Variant.CHESS_960 && !is960Supported) {
return false;
}
write("ucinewgame");
if (is960Supported) {
write("setoption name "+CHESS960_OPTION + " value "+(variant==Variant.CHESS_960?true:false));
}
write("isready");
return waitAnswer("readyok"::equals)!=null;
}

/** Reads the engine standard output until a valid answer is returned.
* @param answerValidator a predicate that checks the lines returned by engine.
* @return The line that is considered valid, null if no valid line is returned
* and the engine closed its output.
*/
private String waitAnswer(Predicate<String> answerValidator) {
for (String line = read(); line!=null; line=read()) {
if (answerValidator.test(line)) {
return line;
}
}
return null;
}

@Override
Expand Down

0 comments on commit b28395c

Please sign in to comment.