Stockfish improvements

This commit is contained in:
Filip Znachor 2023-05-04 10:38:04 +02:00
parent 4699e26afc
commit 0025bf344f
5 changed files with 83 additions and 63 deletions

View file

@ -34,11 +34,8 @@ public class Chess {
window.setSize(800, 600);
window.setMinimumSize(new Dimension(800, 600));
chessboard = Chessboard.fromFEN(DEFAULT_FEN);
newGame(Chessboard.fromFEN(DEFAULT_FEN));
window.setJMenuBar(createMenuBar());
window.add(chessboard, BorderLayout.CENTER);
window.pack();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
@ -212,14 +209,22 @@ public class Chess {
public static void setCPU(Player player, String mode, Runnable update) {
if(mode != null && mode.equals("smart")) {
Stockfish stockfish = player.getStockfish();
if(stockfish != null) {
player.setStockfish(stockfish);
player.setCPU(mode);
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;
}
if(Stockfish.getInstance() == null) {
try {
Stockfish.create(binary);
} catch (IOException e) {
JOptionPane.showMessageDialog(chessboard, "Unable to start Stockfish engine!");
e.printStackTrace();
return;
}
}
} else {
player.setCPU(mode);
}
player.setCPU(mode);
update.run();
}
@ -232,8 +237,10 @@ public class Chess {
}
public static void newGame(Chessboard newChessboard) {
window.remove(chessboard);
if(chessboard != null) window.remove(chessboard);
chessboard = newChessboard;
Stockfish sf = Stockfish.getInstance();
if(sf != null) sf.stopEngine();
window.setJMenuBar(createMenuBar());
window.add(chessboard, BorderLayout.CENTER);
repaintWindow();

View file

@ -511,6 +511,14 @@ public class Chessboard extends JPanel {
public void changeActivePlayer() {
activePlayer = getOtherPlayer();
repaintRootPane();
if(player1.inCheck()) {
System.out.println("Player1 in check!");
if(player1.inMate()) System.out.println("Player1 in mate!");
}
if(player2.inCheck()) {
System.out.println("Player2 in check!");
if(player2.inMate()) System.out.println("Player2 in mate!");
}
activePlayer.play();
}

View file

@ -49,16 +49,14 @@ public class ChessboardMouseAdapter extends MouseAdapter {
PiecePosition pos = c.getPieceCoordinates(me.getX(), me.getY());
APiece piece = c.getPiece(pos.x, pos.y);
APiece selectedPiece = c.getSelectedPiece();
if (piece != null && piece.getPlayer() == c.getActivePlayer() && selectedPiece != piece) {
if (selectedPiece != piece && canMove(c, piece)) {
c.setSelectedPiece(piece);
c.showPossibleMoves(piece.getPossibleMoves());
c.repaintRootPane();
} else if(selectedPiece != null) {
if(selectedPiece.getPossibleMoves()[pos.y][pos.x]) {
selectedPiece.move(pos);
if(c.getActivePlayer().inCheck()) System.out.println("Inactive player in check!");
c.changeActivePlayer();
if(c.getActivePlayer().inCheck()) System.out.println("Active player in check!");
} else {
c.repaintRootPane();
}
@ -71,7 +69,7 @@ public class ChessboardMouseAdapter extends MouseAdapter {
Chessboard c = (Chessboard) me.getSource();
PiecePosition pos = c.getPieceCoordinates(me.getX(), me.getY());
APiece piece = c.getPiece(pos.x, pos.y);
if (piece != null && piece.getPlayer() == c.getActivePlayer()) {
if (canMove(c, piece)) {
c.setSelectedPiece(piece);
c.showPossibleMoves(piece.getPossibleMoves());
c.repaintRootPane();
@ -97,9 +95,7 @@ public class ChessboardMouseAdapter extends MouseAdapter {
if(piece != null) {
if(piece.getPossibleMoves()[pos.y][pos.x]) {
piece.move(pos, false);
if(c.getActivePlayer().inCheck()) System.out.println("Inactive player in check!");
c.changeActivePlayer();
if(c.getActivePlayer().inCheck()) System.out.println("Active player in check!");
} else {
c.repaintRootPane();
}
@ -108,4 +104,10 @@ public class ChessboardMouseAdapter extends MouseAdapter {
c.showPossibleMoves(null);
}
public boolean canMove(Chessboard chessboard, APiece piece) {
if(piece == null) return false;
Player player = piece.getPlayer();
return player == chessboard.getActivePlayer() && player.getCPU() == null;
}
}

View file

@ -1,5 +1,3 @@
import javax.swing.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Timer;
@ -15,10 +13,10 @@ public class Player {
private King king;
private Stockfish stockfish;
private String cpu;
private boolean isPlaying = false;
public Player(Chessboard chessboard, StartPosition startPosition, PieceColor color) {
this.chessboard = chessboard;
this.color = color;
@ -28,9 +26,22 @@ public class Player {
public boolean inCheck() {
return king.isEndangered();
}
public boolean inMate() {
for (APiece piece : getPieces()) {
boolean[][] possibleMoves = piece.getPossibleMoves();
for (int y = 0; y < possibleMoves.length; y++) {
for (int x = 0; x < possibleMoves[y].length; x++) {
if(possibleMoves[y][x]) return false;
}
}
}
return true;
}
public void play() {
if(cpu == null) return;
isPlaying = true;
Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
@ -39,9 +50,10 @@ public class Player {
if (cpu.equals("random")) randomMove();
if (cpu.equals("smart")) smartMove();
}
isPlaying = false;
t.cancel();
}
}, 1000, 1000);
}, 1000);
}
public boolean randomMove() {
@ -75,38 +87,20 @@ public class Player {
}
public boolean smartMove() {
stockfish = getStockfish();
Stockfish stockfish = Stockfish.getInstance();
if(stockfish == null) return false;
String fen = chessboard.toFEN();
String bestMove = stockfish.getBestMove(fen, 0, 500);
if(bestMove == null) return false;
PiecePosition fromPos = PiecePosition.fromString(bestMove.substring(0, 2));
PiecePosition toPos = PiecePosition.fromString(bestMove.substring(2, 4));
if(fromPos == null || toPos == null) return false;
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;
}
@ -141,15 +135,11 @@ public class Player {
public void setCPU(String cpu) {
this.cpu = cpu;
if(cpu != null && chessboard.getActivePlayer() == this) play();
if(chessboard.getActivePlayer() == this && !isPlaying) play();
}
public String getCPU() {
return cpu;
}
public void setStockfish(Stockfish stockfish) {
this.stockfish = stockfish;
}
}

View file

@ -8,6 +8,16 @@ public class Stockfish {
private BufferedReader reader;
private OutputStreamWriter writer;
public static Stockfish instance;
public static void create(String binary) throws IOException {
instance = new Stockfish(binary);
}
public static Stockfish getInstance() {
return instance;
}
public static String findBinary() {
ArrayList<String> paths = new ArrayList<>();
paths.add(".");
@ -38,20 +48,16 @@ public class Stockfish {
}
}
public String getOutput(int waitTime) {
public String getOutput(int waitTime) throws Exception {
StringBuffer buffer = new StringBuffer();
try {
Thread.sleep(waitTime);
sendCommand("isready");
while (true) {
String text = reader.readLine();
if (text.equals("readyok"))
break;
else
buffer.append(text + "\n");
}
} catch (Exception e) {
e.printStackTrace();
Thread.sleep(waitTime);
sendCommand("isready");
while (true) {
String text = reader.readLine();
if (text.equals("readyok"))
break;
else
buffer.append(text + "\n");
}
return buffer.toString();
}
@ -60,9 +66,15 @@ public class Stockfish {
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) {
parts = getOutput(150).split("bestmove ");
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];
}
@ -73,6 +85,7 @@ public class Stockfish {
reader.close();
writer.close();
} catch (IOException e) {}
instance = null;
}
}