Chess/src/Stockfish.java
2023-05-07 21:07:15 +02:00

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;
}
}