146 lines
3.7 KiB
Java
146 lines
3.7 KiB
Java
import java.io.*;
|
|
import java.nio.file.Paths;
|
|
import java.util.ArrayList;
|
|
|
|
/**
|
|
* Stockfish class
|
|
*/
|
|
public class Stockfish {
|
|
|
|
/**
|
|
* Stockfish process
|
|
*/
|
|
private Process process;
|
|
|
|
/**
|
|
* Process reader
|
|
*/
|
|
private BufferedReader reader;
|
|
|
|
/**
|
|
* Process writer
|
|
*/
|
|
private OutputStreamWriter writer;
|
|
|
|
/**
|
|
* Singleton Stockfish instance
|
|
*/
|
|
public static Stockfish instance;
|
|
|
|
/**
|
|
* Create instance
|
|
* @param binary stockfish binary path
|
|
* @throws IOException
|
|
*/
|
|
public static void create(String binary) throws IOException {
|
|
instance = new Stockfish(binary);
|
|
}
|
|
|
|
/**
|
|
* Get singleton Stockfish instance
|
|
* @return instance
|
|
*/
|
|
public static Stockfish getInstance() {
|
|
return instance;
|
|
}
|
|
|
|
/**
|
|
* Get stockfish binary path
|
|
* @return stockfish binary
|
|
*/
|
|
public static String findBinary() {
|
|
ArrayList<String> paths = new ArrayList<>();
|
|
paths.add(".");
|
|
for (String path : System.getenv("PATH").split(":")) {
|
|
paths.add(path);
|
|
}
|
|
for (String path : paths) {
|
|
for (String binary : new String[]{"stockfish", "stockfish.exe"}) {
|
|
String file = Paths.get(path, binary).toString();
|
|
if(new File(file).exists()) return file;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Constructor which starts the stockfish engine
|
|
* @param binary stockfish binary path
|
|
* @throws IOException
|
|
*/
|
|
public Stockfish(String binary) throws IOException {
|
|
process = Runtime.getRuntime().exec(new String[]{binary});
|
|
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
writer = new OutputStreamWriter(process.getOutputStream());
|
|
}
|
|
|
|
/**
|
|
* Send command to the process
|
|
* @param command stockfish command
|
|
*/
|
|
public void sendCommand(String command) {
|
|
try {
|
|
writer.write(command + "\n");
|
|
writer.flush();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get stockfish output
|
|
* @param waitTime wait time in ms
|
|
* @return stockfish output
|
|
* @throws Exception
|
|
*/
|
|
public String getOutput(int waitTime) throws Exception {
|
|
StringBuffer buffer = new StringBuffer();
|
|
Thread.sleep(waitTime);
|
|
sendCommand("isready");
|
|
while (true) {
|
|
String text = reader.readLine();
|
|
if (text.equals("readyok"))
|
|
break;
|
|
else
|
|
buffer.append(text + "\n");
|
|
}
|
|
return buffer.toString();
|
|
}
|
|
|
|
/**
|
|
* Get the best possible move
|
|
* @param fen FEN of the chessboard
|
|
* @param skill stockfish skill level
|
|
* @param waitTime wait time in ms
|
|
* @return the best possible move
|
|
*/
|
|
public String getBestMove(String fen, int skill, int waitTime) {
|
|
sendCommand("setoption name Skill Level value " + skill);
|
|
sendCommand("position fen " + fen);
|
|
sendCommand("go movetime " + waitTime);
|
|
String[] parts = new String[0];
|
|
try {
|
|
parts = getOutput(waitTime+150).split("bestmove ");
|
|
while(parts.length != 2) {
|
|
parts = getOutput(150).split("bestmove ");
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
return null;
|
|
}
|
|
return parts[1].split(" ")[0];
|
|
}
|
|
|
|
/**
|
|
* Stop the stockfish engine
|
|
*/
|
|
public void stopEngine() {
|
|
try {
|
|
sendCommand("quit");
|
|
reader.close();
|
|
writer.close();
|
|
} catch (IOException e) {}
|
|
instance = null;
|
|
}
|
|
|
|
} |