Skip to content

Commit 3c87d81

Browse files
committed
2 parents cb9d41f + 6ece400 commit 3c87d81

File tree

12 files changed

+249
-2
lines changed

12 files changed

+249
-2
lines changed

JavaStockfish/.classpath

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<classpath>
3+
<classpathentry kind="src" path="src"/>
4+
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
5+
<classpathentry kind="output" path="bin"/>
6+
</classpath>

JavaStockfish/.project

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>Stockfish</name>
4+
<comment></comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
<buildCommand>
9+
<name>org.eclipse.jdt.core.javabuilder</name>
10+
<arguments>
11+
</arguments>
12+
</buildCommand>
13+
</buildSpec>
14+
<natures>
15+
<nature>org.eclipse.jdt.core.javanature</nature>
16+
</natures>
17+
</projectDescription>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
eclipse.preferences.version=1
2+
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3+
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
4+
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5+
org.eclipse.jdt.core.compiler.compliance=1.7
6+
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7+
org.eclipse.jdt.core.compiler.debug.localVariable=generate
8+
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9+
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10+
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11+
org.eclipse.jdt.core.compiler.source=1.7
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
eclipse.preferences.version=1
2+
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
3.94 KB
Binary file not shown.
1.65 KB
Binary file not shown.
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package com.rahul.stockfish;
2+
3+
import java.io.BufferedReader;
4+
import java.io.IOException;
5+
import java.io.InputStreamReader;
6+
import java.io.OutputStreamWriter;
7+
8+
/**
9+
* A simple and efficient client to run Stockfish from Java
10+
*
11+
* @author Rahul A R
12+
*
13+
*/
14+
public class Stockfish {
15+
16+
private Process engineProcess;
17+
private BufferedReader processReader;
18+
private OutputStreamWriter processWriter;
19+
20+
private static final String PATH = "../engine/stockfish";
21+
22+
/**
23+
* Starts Stockfish engine as a process and initializes it
24+
*
25+
* @param None
26+
* @return True on success. False otherwise
27+
*/
28+
public boolean startEngine() {
29+
try {
30+
engineProcess = Runtime.getRuntime().exec(PATH);
31+
processReader = new BufferedReader(new InputStreamReader(
32+
engineProcess.getInputStream()));
33+
processWriter = new OutputStreamWriter(
34+
engineProcess.getOutputStream());
35+
} catch (Exception e) {
36+
return false;
37+
}
38+
return true;
39+
}
40+
41+
/**
42+
* Takes in any valid UCI command and executes it
43+
*
44+
* @param command
45+
*/
46+
public void sendCommand(String command) {
47+
try {
48+
processWriter.write(command + "\n");
49+
processWriter.flush();
50+
} catch (IOException e) {
51+
e.printStackTrace();
52+
}
53+
}
54+
55+
/**
56+
* This is generally called right after 'sendCommand' for getting the raw
57+
* output from Stockfish
58+
*
59+
* @param waitTime
60+
* Time in milliseconds for which the function waits before
61+
* reading the output. Useful when a long running command is
62+
* executed
63+
* @return Raw output from Stockfish
64+
*/
65+
public String getOutput(int waitTime) {
66+
StringBuffer buffer = new StringBuffer();
67+
try {
68+
Thread.sleep(waitTime);
69+
sendCommand("isready");
70+
while (true) {
71+
String text = processReader.readLine();
72+
if (text.equals("readyok"))
73+
break;
74+
else
75+
buffer.append(text + "\n");
76+
}
77+
} catch (Exception e) {
78+
e.printStackTrace();
79+
}
80+
return buffer.toString();
81+
}
82+
83+
/**
84+
* This function returns the best move for a given position after
85+
* calculating for 'waitTime' ms
86+
*
87+
* @param fen
88+
* Position string
89+
* @param waitTime
90+
* in milliseconds
91+
* @return Best Move in PGN format
92+
*/
93+
public String getBestMove(String fen, int waitTime) {
94+
sendCommand("position fen " + fen);
95+
sendCommand("go movetime " + waitTime);
96+
return getOutput(waitTime + 20).split("bestmove ")[1].split(" ")[0];
97+
}
98+
99+
/**
100+
* Stops Stockfish and cleans up before closing it
101+
*/
102+
public void stopEngine() {
103+
try {
104+
sendCommand("quit");
105+
processReader.close();
106+
processWriter.close();
107+
} catch (IOException e) {
108+
}
109+
}
110+
111+
/**
112+
* Get a list of all legal moves from the given position
113+
*
114+
* @param fen
115+
* Position string
116+
* @return String of moves
117+
*/
118+
public String getLegalMoves(String fen) {
119+
sendCommand("position fen " + fen);
120+
sendCommand("d");
121+
return getOutput(0).split("Legal moves: ")[1];
122+
}
123+
124+
/**
125+
* Draws the current state of the chess board
126+
*
127+
* @param fen
128+
* Position string
129+
*/
130+
public void drawBoard(String fen) {
131+
sendCommand("position fen " + fen);
132+
sendCommand("d");
133+
134+
String[] rows = getOutput(0).split("\n");
135+
136+
for (int i = 1; i < 18; i++) {
137+
System.out.println(rows[i]);
138+
}
139+
}
140+
141+
/**
142+
* Get the evaluation score of a given board position
143+
* @param fen Position string
144+
* @param waitTime in milliseconds
145+
* @return evalScore
146+
*/
147+
public float getEvalScore(String fen, int waitTime) {
148+
sendCommand("position fen " + fen);
149+
sendCommand("go movetime " + waitTime);
150+
151+
float evalScore = 0.0f;
152+
String[] dump = getOutput(waitTime + 20).split("\n");
153+
for (int i = dump.length - 1; i >= 0; i--) {
154+
if (dump[i].startsWith("info depth ")) {
155+
evalScore = Float.parseFloat(dump[i].split("score cp ")[1]
156+
.split(" nodes")[0]);
157+
}
158+
}
159+
return evalScore/100;
160+
}
161+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.rahul.stockfish;
2+
3+
public class StockfishTest {
4+
public static void main(String[] args) {
5+
Stockfish client = new Stockfish();
6+
String FEN = "8/6pk/8/1R5p/3K3P/8/6r1/8 b - - 0 42";
7+
8+
// initialize and connect to engine
9+
if (client.startEngine()) {
10+
System.out.println("Engine has started..");
11+
} else {
12+
System.out.println("Oops! Something went wrong..");
13+
}
14+
15+
// send commands manually
16+
client.sendCommand("uci");
17+
18+
// receive output dump
19+
System.out.println(client.getOutput(0));
20+
21+
// get the best move for a position with a given think time
22+
System.out.println("Best move : " + client.getBestMove(FEN, 100));
23+
24+
// get all the legal moves from a given position
25+
System.out.println("Legal moves : " + client.getLegalMoves(FEN));
26+
27+
// draw board from a given position
28+
System.out.println("Board state :");
29+
client.drawBoard(FEN);
30+
31+
// get the evaluation score of current position
32+
System.out.println("Evaluation score : " + client.getEvalScore(FEN, 2000));
33+
34+
// stop the engine
35+
System.out.println("Stopping engine..");
36+
client.stopEngine();
37+
}
38+
}

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,15 @@ This will take data from `game_moves.log`
2525
make_dataset.py
2626
---------------
2727
This file takes in a puzzle file in PGN format which contains Mate in 4+ puzzles, parses out the FEN strings, finds the optimal move sequence for mate and prints it to `stdout` and a file named `dataset`
28+
29+
JavaStockfish
30+
=============
31+
A thin client for Stockfish. Comes in handy when we need to use Stockfish along with the object oriented goodness of Java. See `Javadoc` for detailed explanation. The functions currently implemented are :
32+
* Start the engine
33+
* Stop the engine
34+
* Get list of valid moves
35+
* Get best move
36+
* Send UCI commands to engine
37+
* Get raw dump from engine
38+
* Pretty print the board state
39+
* Get evaluation score

chess-position-eval/position_eval.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import subprocess, time
33

44
engine = subprocess.Popen(
5-
'./stockfish',
5+
'../engine/stockfish',
66
universal_newlines=True,
77
stdin=subprocess.PIPE,
88
stdout=subprocess.PIPE,

0 commit comments

Comments
 (0)