Compare commits

...

2 commits

Author SHA1 Message Date
Filip Znachor be4d94a5bb Better stockfish integration 2023-05-02 22:44:34 +02:00
Filip Znachor 76ac71fbf1 Improved scripts 2023-05-02 22:43:51 +02:00
5 changed files with 84 additions and 45 deletions

View file

@ -1,3 +1,3 @@
#!/bin/bash
mkdir ./bin
javac -cp ./src -encoding UTF-8 -d ./bin src/*.java
mkdir -p ./bin
javac -cp ./lib/org.jfree.svg-5.0.5.jar:./src -encoding UTF-8 -d ./bin src/*.java

2
run.sh
View file

@ -1,2 +1,2 @@
#!/bin/bash
java -cp ./bin Chess $@
java -cp ./lib/org.jfree.svg-5.0.5.jar:./bin Chess $@

View file

@ -85,13 +85,20 @@ public class Chess {
JMenuItem toggleAutomaticRandomOpponent = new JMenuItem("Toggle automatic random opponent");
toggleAutomaticRandomOpponent.addActionListener(l -> {
chessboard.getOtherPlayer().toggleAutomaticRandom();
Player opponent = chessboard.getOtherPlayer();
opponent.toggleAutomaticRandom(!opponent.isAutomaticRandom());
});
menuCPU.add(toggleAutomaticRandomOpponent);
JMenuItem toggleAutomaticSmartOpponent = new JMenuItem("Toggle automatic smart opponent");
toggleAutomaticSmartOpponent.addActionListener(l -> {
chessboard.getOtherPlayer().toggleAutomaticSmart();
Player opponent = chessboard.getOtherPlayer();
if(!opponent.isAutomaticSmart()) {
Stockfish stockfish = opponent.getStockfish();
opponent.toggleAutomaticSmart(stockfish);
} else {
opponent.toggleAutomaticSmart(null);
}
});
menuCPU.add(toggleAutomaticSmartOpponent);

View file

@ -1,3 +1,5 @@
import javax.swing.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Timer;
@ -72,10 +74,8 @@ public class Player {
}
public boolean smartMove() {
if(stockfish == null) {
stockfish = new Stockfish();
stockfish.startEngine();
}
stockfish = getStockfish();
if(stockfish == null) return false;
String fen = chessboard.toFEN();
String bestMove = stockfish.getBestMove(fen, 0, 500);
PiecePosition fromPos = PiecePosition.fromString(bestMove.substring(0, 2));
@ -84,9 +84,28 @@ public class Player {
APiece piece = chessboard.getPiece(fromPos.x, fromPos.y);
piece.move(toPos);
chessboard.changeActivePlayer();
stockfish.stopEngine();
stockfish = null;
return true;
}
public Stockfish getStockfish() {
if(stockfish == null) {
String binary = Stockfish.findBinary();
if(binary == null) {
JOptionPane.showMessageDialog(chessboard, "Stockfish engine not found! (stockfishchess.org)\nDownload 'stockfish' or 'stockfish.exe' to the program's folder or the system's path.");
return null;
}
try {
stockfish = new Stockfish(binary);
} catch (IOException e) {
JOptionPane.showMessageDialog(chessboard, "Unable to start Stockfish engine!");
e.printStackTrace();
}
}
return stockfish;
}
public Chessboard getChessboard() {
return chessboard;
}
@ -119,12 +138,26 @@ public class Player {
return myPieces;
}
public void toggleAutomaticRandom() {
automaticRandom = !automaticRandom;
public void toggleAutomaticRandom(boolean state) {
if(state) automaticSmart = false;
automaticRandom = state;
}
public void toggleAutomaticSmart() {
automaticSmart = !automaticSmart;
public boolean isAutomaticRandom() {
return automaticRandom;
}
public void toggleAutomaticSmart(Stockfish stockfish) {
boolean state = stockfish != null;
if(state) {
this.stockfish = stockfish;
automaticRandom = false;
}
automaticSmart = state;
}
public boolean isAutomaticSmart() {
return automaticSmart;
}
}

View file

@ -1,38 +1,38 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.*;
import java.nio.file.Paths;
import java.util.ArrayList;
public class Stockfish {
private Process engineProcess;
private BufferedReader processReader;
private OutputStreamWriter processWriter;
private Process process;
private BufferedReader reader;
private OutputStreamWriter writer;
private static final String PATH = "./stockfish";
/**
* Starts Stockfish engine as a process and initializes it
*
* @return True on success. False otherwise
*/
public boolean startEngine() {
try {
engineProcess = Runtime.getRuntime().exec(PATH);
processReader = new BufferedReader(new InputStreamReader(
engineProcess.getInputStream()));
processWriter = new OutputStreamWriter(
engineProcess.getOutputStream());
} catch (Exception e) {
return false;
public static String findBinary() {
ArrayList<String> paths = new ArrayList<>();
paths.add(".");
for (String path : System.getenv("PATH").split(":")) {
paths.add(path);
}
return true;
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;
}
public Stockfish(String binary) throws IOException {
process = Runtime.getRuntime().exec(binary);
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
writer = new OutputStreamWriter(process.getOutputStream());
}
public void sendCommand(String command) {
try {
processWriter.write(command + "\n");
processWriter.flush();
writer.write(command + "\n");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
@ -44,7 +44,7 @@ public class Stockfish {
Thread.sleep(waitTime);
sendCommand("isready");
while (true) {
String text = processReader.readLine();
String text = reader.readLine();
if (text.equals("readyok"))
break;
else
@ -57,8 +57,8 @@ public class Stockfish {
}
public String getBestMove(String fen, int skill, int waitTime) {
sendCommand("position fen " + fen);
sendCommand("setoption name Skill Level value " + skill);
sendCommand("position fen " + fen);
sendCommand("go movetime " + waitTime);
String[] parts = getOutput(waitTime+150).split("bestmove ");
while(parts.length != 2) {
@ -70,10 +70,9 @@ public class Stockfish {
public void stopEngine() {
try {
sendCommand("quit");
processReader.close();
processWriter.close();
} catch (IOException e) {
}
reader.close();
writer.close();
} catch (IOException e) {}
}
}