Added javadoc
This commit is contained in:
parent
0b4c7d440c
commit
91608f1f7b
201
src/APiece.java
201
src/APiece.java
|
@ -39,14 +39,23 @@ public abstract class APiece {
|
|||
*/
|
||||
protected PieceColor color;
|
||||
|
||||
/**
|
||||
* Player owning the piece
|
||||
*/
|
||||
protected Player player;
|
||||
|
||||
/**
|
||||
* Piece's move count
|
||||
*/
|
||||
public int moveCount = 0;
|
||||
|
||||
/**
|
||||
* Piece's scale
|
||||
*/
|
||||
public double scale = 1;
|
||||
|
||||
/**
|
||||
* Create new piece
|
||||
* Create a new piece
|
||||
* @param player player
|
||||
* @param x piece's X location
|
||||
* @param y piece's Y location
|
||||
|
@ -147,31 +156,37 @@ public abstract class APiece {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set piece's new position
|
||||
* @param pos piece position
|
||||
* Set piece's new position with animation
|
||||
* @param newX new X position
|
||||
* @param newY new Y position
|
||||
*/
|
||||
public void setPosition(PiecePosition pos) {
|
||||
setPosition(pos, true);
|
||||
public void setPosition(int newX, int newY) {
|
||||
setPosition(newX, newY, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set piece's new position
|
||||
* @param pos piece position
|
||||
* @param newX new X position
|
||||
* @param newY new Y position
|
||||
* @param animate animate piece's move
|
||||
*/
|
||||
public void setPosition(PiecePosition pos, boolean animate) {
|
||||
if(animate) animateMove(x, y, pos.x, pos.y);
|
||||
public void setPosition(int newX, int newY, boolean animate) {
|
||||
if(animate) animateMove(x, y, newX, newY);
|
||||
moveCount++;
|
||||
chessboard.removePiece(x, y);
|
||||
APiece piece = chessboard.getPiece(pos.x, pos.y);
|
||||
APiece piece = chessboard.getPiece(newX, newY);
|
||||
if(piece != null) {
|
||||
piece.remove(animate);
|
||||
}
|
||||
x = pos.x;
|
||||
y = pos.y;
|
||||
x = newX;
|
||||
y = newY;
|
||||
chessboard.addPiece(this, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the piece is floating
|
||||
* @return is floating
|
||||
*/
|
||||
public boolean isFloating() {
|
||||
return overrideX != 0 && overrideY != 0;
|
||||
}
|
||||
|
@ -187,31 +202,31 @@ public abstract class APiece {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get piece's override X location
|
||||
* @return override X location
|
||||
* Get X position in px on the chessboard
|
||||
* @return real X position in px
|
||||
*/
|
||||
public double getOverrideX() {
|
||||
return (overrideX-chessboard.startX)/chessboard.boardScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get piece's override Y location
|
||||
* @return override Y location
|
||||
*/
|
||||
public double getOverrideY() {
|
||||
return (overrideY-chessboard.startY)/chessboard.boardScale;
|
||||
}
|
||||
|
||||
public double getRealX() {
|
||||
if(overrideX != 0) return getOverrideX();
|
||||
if(overrideX != 0) return (overrideX-chessboard.startX)/chessboard.boardScale;
|
||||
return chessboard.SQUARE_SIZE*x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Y position in px on the chessboard
|
||||
* @return real Y position in px
|
||||
*/
|
||||
public double getRealY() {
|
||||
if(overrideY != 0) return getOverrideY();
|
||||
if(overrideY != 0) return (overrideY-chessboard.startY)/chessboard.boardScale;;
|
||||
return chessboard.SQUARE_SIZE*y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get piece's scale
|
||||
* @return piece's scale
|
||||
*/
|
||||
public double getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get piece's X location
|
||||
* @return piece's X location
|
||||
|
@ -228,56 +243,116 @@ public abstract class APiece {
|
|||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get piece's color
|
||||
* @return piece's color
|
||||
*/
|
||||
public PieceColor getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setPossibleMove(boolean[][] moves, int x, int y) {
|
||||
/**
|
||||
* Get piece's player
|
||||
* @return piece's player
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get piece's move count
|
||||
* @return move count
|
||||
*/
|
||||
public int getMoveCount() {
|
||||
return moveCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set piece's move count
|
||||
* @param moveCount new move count
|
||||
*/
|
||||
public void setMoveCount(int moveCount) {
|
||||
this.moveCount = moveCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks, if passed move is possible
|
||||
* @param moves two-dimensional array of moves
|
||||
* @param x new X position
|
||||
* @param y new Y position
|
||||
*/
|
||||
public void setPossibleMove(boolean[][] moves, int x, int y) {
|
||||
if(x == this.x && y == this.y) return;
|
||||
if(x < 0 || x >= moves.length || y < 0 || y >= moves.length) return;
|
||||
APiece piece = chessboard.getPiece(x, y);
|
||||
if(piece != null && player == piece.getPlayer()) return;
|
||||
if(tryMove(piece, x, y)) return;
|
||||
moves[y][x] = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the player will be in check if the piece moves to a new position
|
||||
* @param piece selected piece
|
||||
* @param x new X position
|
||||
* @param y new Y position
|
||||
* @return true, if player will be in check
|
||||
*/
|
||||
public boolean tryMove(APiece piece, int x, int y) {
|
||||
chessboard.removePiece(this.x, this.y);
|
||||
chessboard.addPiece(this, x, y);
|
||||
int xBefore = this.x;
|
||||
int yBefore = this.y;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
int xBefore = this.x, yBefore = this.y;
|
||||
this.x = x; this.y = y;
|
||||
boolean inCheck = player.inCheck();
|
||||
this.x = xBefore;
|
||||
this.y = yBefore;
|
||||
this.x = xBefore; this.y = yBefore;
|
||||
chessboard.addPiece(piece, x, y);
|
||||
chessboard.addPiece(this, this.x, this.y);
|
||||
return inCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests, whether the piece is endangered by another piece
|
||||
* @return true, if endangered
|
||||
*/
|
||||
public boolean isEndangered() {
|
||||
return chessboard.isEndangered(x, y);
|
||||
}
|
||||
|
||||
public void move(PiecePosition pos) {
|
||||
move(pos, true);
|
||||
/**
|
||||
* Move the piece to the new position with animation
|
||||
* @param newX new X position
|
||||
* @param newY new Y position
|
||||
*/
|
||||
public void move(int newX, int newY) {
|
||||
move(newX, newY, true);
|
||||
}
|
||||
|
||||
public void move(PiecePosition pos, boolean animate) {
|
||||
/**
|
||||
* Move the piece to the new position with animation
|
||||
* @param newX new X position
|
||||
* @param newY new Y position
|
||||
* @param animate animate piece's move
|
||||
*/
|
||||
public void move(int newX, int newY, boolean animate) {
|
||||
boolean[][] lastMove = new boolean[chessboard.SQUARE_COUNT][chessboard.SQUARE_COUNT];
|
||||
lastMove[y][x] = true;
|
||||
lastMove[pos.y][pos.x] = true;
|
||||
setPosition(pos, animate);
|
||||
lastMove[newY][newX] = true;
|
||||
setPosition(newX, newY, animate);
|
||||
chessboard.showLastMove(lastMove);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repaint rectangle containing the piece
|
||||
* @return repaint rectangle
|
||||
*/
|
||||
public Rectangle getRepaintRectangle() {
|
||||
return getRepaintRectangle(Chess.menuBar.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repaint rectangle containing the piece with vertical offset
|
||||
* @param offsetY vertical offset
|
||||
* @return repaint rectangle
|
||||
*/
|
||||
public Rectangle getRepaintRectangle(int offsetY) {
|
||||
int rectSize = (int) (chessboard.SQUARE_SIZE*chessboard.boardScale);
|
||||
double x = getRealX()*chessboard.boardScale+chessboard.startX;
|
||||
|
@ -288,6 +363,12 @@ public abstract class APiece {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trace the piece's path in X, Y direction
|
||||
* @param moves two-dimensional array of moves
|
||||
* @param xDirection X direction
|
||||
* @param yDirection Y direction
|
||||
*/
|
||||
public void tracePath(boolean[][] moves, int xDirection, int yDirection) {
|
||||
int i = x + xDirection;
|
||||
int j = y + yDirection;
|
||||
|
@ -300,26 +381,34 @@ public abstract class APiece {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get piece's possible moves
|
||||
* @return two-dimensional array of moves
|
||||
*/
|
||||
public boolean[][] getPossibleMoves() {
|
||||
return getPossibleMoves(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get piece's possible moves
|
||||
* @param attack force the attack mode
|
||||
* @return two-dimensional array of moves
|
||||
*/
|
||||
abstract public boolean[][] getPossibleMoves(boolean attack);
|
||||
|
||||
/**
|
||||
* Paint the piece
|
||||
* @param g2 Graphics2D
|
||||
*/
|
||||
abstract public void paint(Graphics2D g2);
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public int getMoveCount() {
|
||||
return moveCount;
|
||||
}
|
||||
|
||||
public void setMoveCount(int moveCount) {
|
||||
this.moveCount = moveCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate piece's move
|
||||
* @param fromX original X position
|
||||
* @param fromY original Y position
|
||||
* @param toX new X position
|
||||
* @param toY new Y position
|
||||
*/
|
||||
public void animateMove(int fromX, int fromY, int toX, int toY) {
|
||||
double startX = chessboard.startX + (fromX*chessboard.SQUARE_SIZE)*chessboard.boardScale;
|
||||
double startY = chessboard.startY + (fromY*chessboard.SQUARE_SIZE)*chessboard.boardScale;
|
||||
|
@ -348,6 +437,10 @@ public abstract class APiece {
|
|||
}, 2, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the piece
|
||||
* @param animate animate piece's removal
|
||||
*/
|
||||
public void remove(boolean animate) {
|
||||
chessboard.removePiece(x, y);
|
||||
if(!animate) return;
|
||||
|
@ -367,8 +460,4 @@ public abstract class APiece {
|
|||
}, 10, 10);
|
||||
}
|
||||
|
||||
public double getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
}
|
|
@ -41,6 +41,11 @@ public class Bishop extends APiece {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Bishop's possible moves
|
||||
* @param attack force the attack mode
|
||||
* @return two-dimensional array of possible moves
|
||||
*/
|
||||
@Override
|
||||
public boolean[][] getPossibleMoves(boolean attack) {
|
||||
boolean[][] moves = new boolean[chessboard.SQUARE_COUNT][chessboard.SQUARE_COUNT];
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import org.jfree.chart.ChartFactory;
|
||||
import org.jfree.chart.ChartPanel;
|
||||
import org.jfree.chart.JFreeChart;
|
||||
import org.jfree.chart.axis.CategoryLabelPositions;
|
||||
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
|
||||
import org.jfree.chart.plot.CategoryPlot;
|
||||
import org.jfree.chart.renderer.category.BarRenderer;
|
||||
|
@ -18,7 +17,6 @@ import java.io.File;
|
|||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -35,7 +33,7 @@ public class Chess {
|
|||
static final String DEFAULT_FEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
||||
|
||||
/**
|
||||
* Create the main window and chessboard with pieces
|
||||
* Create the main window and the chessboard
|
||||
* @param args command-line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
@ -57,6 +55,9 @@ public class Chess {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to inherit design from the OS
|
||||
*/
|
||||
public static void setLookAndFeel() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
|
@ -65,6 +66,10 @@ public class Chess {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create window's menu bar
|
||||
* @return menu bar
|
||||
*/
|
||||
public static JMenuBar createMenuBar() {
|
||||
menuBar = new JMenuBar();
|
||||
|
||||
|
@ -76,6 +81,10 @@ public class Chess {
|
|||
return menuBar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Game menu
|
||||
* @return Game menu
|
||||
*/
|
||||
public static JMenu createMenuGame() {
|
||||
|
||||
JMenu menuGame = new JMenu("Game");
|
||||
|
@ -123,6 +132,10 @@ public class Chess {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Theme menu
|
||||
* @return Theme menu
|
||||
*/
|
||||
public static JMenu createMenuTheme() {
|
||||
|
||||
JMenu menuTheme = new JMenu("Theme");
|
||||
|
@ -154,6 +167,10 @@ public class Chess {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create CPU menu
|
||||
* @return CPU menu
|
||||
*/
|
||||
public static JMenu createMenuCPU() {
|
||||
|
||||
JMenu menuCPU = new JMenu("CPU");
|
||||
|
@ -181,34 +198,40 @@ public class Chess {
|
|||
};
|
||||
|
||||
whiteDisabled.addActionListener(l -> {
|
||||
setCPU(chessboard.getPlayer1(), null, updateWhite);
|
||||
setCPU(chessboard.getPlayer1(), null);
|
||||
updateWhite.run();
|
||||
});
|
||||
menuCPU.add(whiteDisabled);
|
||||
|
||||
whiteAutomaticRandom.addActionListener(l -> {
|
||||
setCPU(chessboard.getPlayer1(), "random", updateWhite);
|
||||
setCPU(chessboard.getPlayer1(), "random");
|
||||
updateWhite.run();
|
||||
});
|
||||
menuCPU.add(whiteAutomaticRandom);
|
||||
|
||||
whiteAutomaticSmart.addActionListener(l -> {
|
||||
setCPU(chessboard.getPlayer1(), "smart", updateWhite);
|
||||
setCPU(chessboard.getPlayer1(), "smart");
|
||||
updateWhite.run();
|
||||
});
|
||||
menuCPU.add(whiteAutomaticSmart);
|
||||
|
||||
menuCPU.add(new JPopupMenu.Separator());
|
||||
|
||||
blackDisabled.addActionListener(l -> {
|
||||
setCPU(chessboard.getPlayer2(), null, updateBlack);
|
||||
setCPU(chessboard.getPlayer2(), null);
|
||||
updateBlack.run();
|
||||
});
|
||||
menuCPU.add(blackDisabled);
|
||||
|
||||
blackAutomaticRandom.addActionListener(l -> {
|
||||
setCPU(chessboard.getPlayer2(), "random", updateBlack);
|
||||
setCPU(chessboard.getPlayer2(), "random");
|
||||
updateBlack.run();
|
||||
});
|
||||
menuCPU.add(blackAutomaticRandom);
|
||||
|
||||
blackAutomaticSmart.addActionListener(l -> {
|
||||
setCPU(chessboard.getPlayer2(), "smart", updateBlack);
|
||||
setCPU(chessboard.getPlayer2(), "smart");
|
||||
updateBlack.run();
|
||||
});
|
||||
menuCPU.add(blackAutomaticSmart);
|
||||
|
||||
|
@ -219,6 +242,10 @@ public class Chess {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Export menu
|
||||
* @return Export menu
|
||||
*/
|
||||
public static JMenu createMenuExport() {
|
||||
|
||||
JMenu menuExport = new JMenu("Export");
|
||||
|
@ -235,7 +262,12 @@ public class Chess {
|
|||
|
||||
}
|
||||
|
||||
public static void setCPU(Player player, String mode, Runnable update) {
|
||||
/**
|
||||
* Set player's CPU mode
|
||||
* @param player selected player
|
||||
* @param mode null, "random" or "smart"
|
||||
*/
|
||||
public static void setCPU(Player player, String mode) {
|
||||
if(mode != null && mode.equals("smart")) {
|
||||
String binary = Stockfish.findBinary();
|
||||
if(binary == null) {
|
||||
|
@ -253,9 +285,11 @@ public class Chess {
|
|||
}
|
||||
}
|
||||
player.setCPU(mode);
|
||||
update.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Repaint entire window
|
||||
*/
|
||||
public static void repaintWindow() {
|
||||
// Hack to force repaint of the chessboard (repaint is not working)
|
||||
int winWidth = window.getWidth();
|
||||
|
@ -264,6 +298,10 @@ public class Chess {
|
|||
window.setSize(winWidth, winHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new game with specified chessboard
|
||||
* @param newChessboard chessboard
|
||||
*/
|
||||
public static void newGame(Chessboard newChessboard) {
|
||||
if(chessboard != null) window.remove(chessboard);
|
||||
chessboard = newChessboard;
|
||||
|
@ -274,6 +312,9 @@ public class Chess {
|
|||
repaintWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Export current chessboard to SVG file
|
||||
*/
|
||||
public static void exportSVG() {
|
||||
SVGGraphics2D g2 = new SVGGraphics2D(1000, 1000);
|
||||
chessboard.paint(g2, 1000, 1000);
|
||||
|
@ -288,6 +329,10 @@ public class Chess {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export current chessboard to PNG file
|
||||
*/
|
||||
|
||||
public static void exportPNG() {
|
||||
BufferedImage image = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g = image.createGraphics();
|
||||
|
@ -301,6 +346,9 @@ public class Chess {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show window with statistics
|
||||
*/
|
||||
public static void showStatistics() {
|
||||
JFrame window = new JFrame();
|
||||
window.setTitle("Statistics");
|
||||
|
|
|
@ -49,22 +49,49 @@ public class Chessboard extends JPanel {
|
|||
*/
|
||||
public APiece[][] pieces = new APiece[SQUARE_COUNT][SQUARE_COUNT];
|
||||
|
||||
/**
|
||||
* Set of removed pieces
|
||||
*/
|
||||
public Set<APiece> removedPieces = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Two-dimensional boolean array of shown possible moves
|
||||
*/
|
||||
public boolean[][] possibleMoves = new boolean[SQUARE_COUNT][SQUARE_COUNT];
|
||||
|
||||
/**
|
||||
* Two-dimensional boolean array of shown last move
|
||||
*/
|
||||
public boolean[][] lastMove = new boolean[SQUARE_COUNT][SQUARE_COUNT];
|
||||
|
||||
/**
|
||||
* Currently active player
|
||||
*/
|
||||
private Player activePlayer;
|
||||
|
||||
/**
|
||||
* White player instance
|
||||
*/
|
||||
private Player player1;
|
||||
|
||||
/**
|
||||
* Black player instance
|
||||
*/
|
||||
private Player player2;
|
||||
|
||||
/**
|
||||
* Blind mode toggle
|
||||
*/
|
||||
public boolean blindMode = false;
|
||||
|
||||
/**
|
||||
* Current theme instance
|
||||
*/
|
||||
static private Theme theme = Theme.activeTheme;
|
||||
|
||||
/**
|
||||
* Last move time in ms
|
||||
*/
|
||||
private long lastMoveTime = System.currentTimeMillis();
|
||||
|
||||
/**
|
||||
|
@ -78,6 +105,11 @@ public class Chessboard extends JPanel {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Chessboard creation from FEN
|
||||
* @param input FEN
|
||||
* @return Chessbord instance or null, if FEN is invalid
|
||||
*/
|
||||
public static Chessboard fromFEN(String input) {
|
||||
|
||||
String[] parts = input.split(" ");
|
||||
|
@ -148,6 +180,10 @@ public class Chessboard extends JPanel {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current FEN of the chessboard
|
||||
* @return FEN
|
||||
*/
|
||||
public String toFEN() {
|
||||
|
||||
StringBuilder chessboardSB = new StringBuilder();
|
||||
|
@ -313,12 +349,23 @@ public class Chessboard extends JPanel {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint dark or light square
|
||||
* @param g Graphics context
|
||||
* @param isBlack whether square is dark or not
|
||||
*/
|
||||
private void paintSquare(Graphics g, boolean isBlack) {
|
||||
if(isBlack) g.setColor(theme.darkSquare);
|
||||
else g.setColor(theme.lightSquare);
|
||||
g.fillRect(0, 0, SQUARE_SIZE+1, SQUARE_SIZE+1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint last move and possible moves
|
||||
* @param g Graphics context
|
||||
* @param x X position
|
||||
* @param y Y position
|
||||
*/
|
||||
private void paintHighlights(Graphics g, int x, int y) {
|
||||
if(lastMove != null && lastMove[y][x]) {
|
||||
g.setColor(new Color(50, 50, 250, 30));
|
||||
|
@ -332,6 +379,11 @@ public class Chessboard extends JPanel {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint piece
|
||||
* @param g2 Graphics2D context
|
||||
* @param piece painted piece
|
||||
*/
|
||||
private void paintPiece(Graphics2D g2, APiece piece) {
|
||||
g2.translate(20+piece.getRealX(), 20+piece.getRealY());
|
||||
double pieceScale = piece.getScale();
|
||||
|
@ -343,10 +395,17 @@ public class Chessboard extends JPanel {
|
|||
piece.paint(g2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repaint entire root pane
|
||||
*/
|
||||
public void repaintRootPane() {
|
||||
repaintRootPane(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repaint rectangle on the root pane
|
||||
* @param r repaint rectangle
|
||||
*/
|
||||
public void repaintRootPane(Rectangle r) {
|
||||
JComponent pane = getRootPane();
|
||||
if(pane != null) {
|
||||
|
@ -355,6 +414,10 @@ public class Chessboard extends JPanel {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set active theme
|
||||
* @param newTheme new theme
|
||||
*/
|
||||
public static void setTheme(Theme newTheme) {
|
||||
theme = newTheme;
|
||||
}
|
||||
|
@ -420,6 +483,12 @@ public class Chessboard extends JPanel {
|
|||
return selected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if piece on specified XY position
|
||||
* @param x piece's X position
|
||||
* @param y piece's Y position
|
||||
* @return whether piece is endangered
|
||||
*/
|
||||
public boolean isEndangered(int x, int y) {
|
||||
|
||||
APiece piece = getPiece(x, y);
|
||||
|
@ -469,47 +538,92 @@ public class Chessboard extends JPanel {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set current possible moves
|
||||
* @param moves two-dimensional boolean array of possible moves
|
||||
*/
|
||||
public void showPossibleMoves(boolean[][] moves) {
|
||||
possibleMoves = moves;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set last move
|
||||
* @param move two-dimensional boolean array with from-to positions
|
||||
*/
|
||||
public void showLastMove(boolean[][] move) {
|
||||
lastMove = move;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if XY position is on the chessboard or not
|
||||
* @param x X position
|
||||
* @param y Y position
|
||||
* @return whether XY position is on the chessboard
|
||||
*/
|
||||
public boolean isOnBoard(int x, int y) {
|
||||
return !(y < 0 || y >= SQUARE_COUNT || x < 0 || x >= SQUARE_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set first player
|
||||
* @param player white player instance
|
||||
*/
|
||||
public void setPlayer1(Player player) {
|
||||
activePlayer = player;
|
||||
player1 = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set second player
|
||||
* @param player black player instance
|
||||
*/
|
||||
public void setPlayer2(Player player) {
|
||||
player2 = player;
|
||||
}
|
||||
|
||||
public Player getActivePlayer() {
|
||||
return activePlayer;
|
||||
}
|
||||
|
||||
public void setActivePlayer(Player player) {
|
||||
activePlayer = player;
|
||||
}
|
||||
|
||||
public Player getOtherPlayer() {
|
||||
return activePlayer == player1 ? player2 : player1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first player
|
||||
* @return white player instance
|
||||
*/
|
||||
public Player getPlayer1() {
|
||||
return player1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get second player
|
||||
* @return black player instance
|
||||
*/
|
||||
public Player getPlayer2() {
|
||||
return player2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active player
|
||||
* @return active player instance
|
||||
*/
|
||||
public Player getActivePlayer() {
|
||||
return activePlayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set active player
|
||||
* @param player player instance
|
||||
*/
|
||||
public void setActivePlayer(Player player) {
|
||||
activePlayer = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get non-active player
|
||||
* @return non-active player instance
|
||||
*/
|
||||
public Player getOtherPlayer() {
|
||||
return activePlayer == player1 ? player2 : player1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if some specified game state is or is not met
|
||||
*/
|
||||
public void checkGame() {
|
||||
Player[] players = new Player[]{player1, player2};
|
||||
String[] playerNames = new String[]{"White", "Black"};
|
||||
|
@ -528,6 +642,10 @@ public class Chessboard extends JPanel {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display message after 1 second
|
||||
* @param msg displayed message
|
||||
*/
|
||||
public void delayedMessage(String msg) {
|
||||
Timer t = new Timer();
|
||||
t.schedule(new TimerTask() {
|
||||
|
@ -538,6 +656,9 @@ public class Chessboard extends JPanel {
|
|||
}, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* End player's move, set other player as active and check game state
|
||||
*/
|
||||
public void changeActivePlayer() {
|
||||
long now = System.currentTimeMillis();
|
||||
activePlayer.addDelay((int) (now-lastMoveTime));
|
||||
|
|
|
@ -2,7 +2,7 @@ import java.awt.event.MouseAdapter;
|
|||
import java.awt.event.MouseEvent;
|
||||
|
||||
/**
|
||||
* Chessboard mouse adapter class
|
||||
* Chessboard mouse adapter class for detecting user input on the chessboard
|
||||
*/
|
||||
public class ChessboardMouseAdapter extends MouseAdapter {
|
||||
|
||||
|
@ -11,7 +11,7 @@ public class ChessboardMouseAdapter extends MouseAdapter {
|
|||
boolean dragging;
|
||||
|
||||
/**
|
||||
* Detect mouse press and select the piece
|
||||
* Detect mouse press
|
||||
* @param me mouse event
|
||||
*/
|
||||
public void mousePressed(MouseEvent me) {
|
||||
|
@ -21,7 +21,7 @@ public class ChessboardMouseAdapter extends MouseAdapter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Detect mouse dragging and show floating piece
|
||||
* Detect mouse dragging
|
||||
* @param me mouse event
|
||||
*/
|
||||
@Override
|
||||
|
@ -34,7 +34,7 @@ public class ChessboardMouseAdapter extends MouseAdapter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Detect mouse release and place piece on the chessboard
|
||||
* Detect mouse release
|
||||
* @param me mouse event
|
||||
*/
|
||||
@Override
|
||||
|
@ -43,7 +43,10 @@ public class ChessboardMouseAdapter extends MouseAdapter {
|
|||
else if(lastClicked > System.currentTimeMillis()) onClick(me);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Select, unselect or move the piece on the chessboard
|
||||
* @param me mouse event
|
||||
*/
|
||||
public void onClick(MouseEvent me) {
|
||||
Chessboard c = (Chessboard) me.getSource();
|
||||
PiecePosition pos = c.getPieceCoordinates(me.getX(), me.getY());
|
||||
|
@ -55,7 +58,7 @@ public class ChessboardMouseAdapter extends MouseAdapter {
|
|||
c.repaintRootPane();
|
||||
} else if(selectedPiece != null) {
|
||||
if(selectedPiece.getPossibleMoves()[pos.y][pos.x]) {
|
||||
selectedPiece.move(pos);
|
||||
selectedPiece.move(pos.x, pos.y);
|
||||
c.changeActivePlayer();
|
||||
} else {
|
||||
c.repaintRootPane();
|
||||
|
@ -65,6 +68,10 @@ public class ChessboardMouseAdapter extends MouseAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select piece on drag start
|
||||
* @param me mouse event
|
||||
*/
|
||||
public void onDragStart(MouseEvent me) {
|
||||
Chessboard c = (Chessboard) me.getSource();
|
||||
PiecePosition pos = c.getPieceCoordinates(me.getX(), me.getY());
|
||||
|
@ -76,6 +83,10 @@ public class ChessboardMouseAdapter extends MouseAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render and move selected piece on drag
|
||||
* @param me
|
||||
*/
|
||||
public void onDrag(MouseEvent me) {
|
||||
Chessboard c = (Chessboard) me.getSource();
|
||||
APiece piece = c.getSelectedPiece();
|
||||
|
@ -88,13 +99,17 @@ public class ChessboardMouseAdapter extends MouseAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move piece to the new position on drag end
|
||||
* @param me mouse event
|
||||
*/
|
||||
public void onDragEnd(MouseEvent me) {
|
||||
Chessboard c = (Chessboard) me.getSource();
|
||||
APiece piece = c.getSelectedPiece();
|
||||
PiecePosition pos = c.getPieceCoordinates(me.getX(), me.getY());
|
||||
if(piece != null) {
|
||||
if(piece.getPossibleMoves()[pos.y][pos.x]) {
|
||||
piece.move(pos, false);
|
||||
piece.move(pos.x, pos.y, false);
|
||||
c.changeActivePlayer();
|
||||
} else {
|
||||
c.repaintRootPane();
|
||||
|
@ -104,6 +119,12 @@ public class ChessboardMouseAdapter extends MouseAdapter {
|
|||
c.showPossibleMoves(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect if selected piece can be moved
|
||||
* @param chessboard chessboard instance
|
||||
* @param piece selected piece
|
||||
* @return true, if you can move the piece or false
|
||||
*/
|
||||
public boolean canMove(Chessboard chessboard, APiece piece) {
|
||||
if(piece == null) return false;
|
||||
Player player = piece.getPlayer();
|
||||
|
|
|
@ -33,6 +33,11 @@ public class King extends APiece {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get King's possible moves
|
||||
* @param attack force the attack mode
|
||||
* @return two-dimensional array of moves
|
||||
*/
|
||||
@Override
|
||||
public boolean[][] getPossibleMoves(boolean attack) {
|
||||
boolean[][] moves = new boolean[chessboard.SQUARE_COUNT][chessboard.SQUARE_COUNT];
|
||||
|
@ -46,6 +51,11 @@ public class King extends APiece {
|
|||
return moves;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if left (-1) or right (1) castling is possible
|
||||
* @param direction -1 for left, 1 for right
|
||||
* @return castling possibility
|
||||
*/
|
||||
private boolean checkCastling(int direction) {
|
||||
if(moveCount == 0 && !player.inCheck() && checkRook(direction)) {
|
||||
for (int pX = x + direction; (pX > 0 && pX < 7); pX += direction) {
|
||||
|
@ -56,22 +66,33 @@ public class King extends APiece {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if left or right Rook is able to do castling
|
||||
* @param direction -1 for left Rook, 1 for right Rook
|
||||
* @return rook castling ability
|
||||
*/
|
||||
private boolean checkRook(int direction) {
|
||||
int rookX = direction == -1 ? 0 : 7;
|
||||
APiece rook = chessboard.getPiece(rookX, y);
|
||||
return rook != null && rook instanceof Rook && rook.getMoveCount() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the piece to the new position
|
||||
* @param newX new X position
|
||||
* @param newY new Y position
|
||||
* @param animate animate piece's move
|
||||
*/
|
||||
@Override
|
||||
public void move(PiecePosition pos, boolean animate) {
|
||||
super.move(pos, animate);
|
||||
public void move(int newX, int newY, boolean animate) {
|
||||
super.move(newX, newY, animate);
|
||||
if(moveCount == 1 && x == 6) {
|
||||
APiece rook = chessboard.getPiece(7, y);
|
||||
if(rook != null) rook.setPosition(new PiecePosition(5, y));
|
||||
if(rook != null) rook.setPosition(5, y);
|
||||
}
|
||||
if(moveCount == 1 && x == 1) {
|
||||
APiece rook = chessboard.getPiece(0, y);
|
||||
if(rook != null) rook.setPosition(new PiecePosition(3, y));
|
||||
if(rook != null) rook.setPosition(3, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,11 @@ public class Knight extends APiece {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Knight's possible moves
|
||||
* @param attack force the attack mode
|
||||
* @return two-dimensional array of moves
|
||||
*/
|
||||
@Override
|
||||
public boolean[][] getPossibleMoves(boolean attack) {
|
||||
boolean[][] moves = new boolean[chessboard.SQUARE_COUNT][chessboard.SQUARE_COUNT];
|
||||
|
|
|
@ -28,6 +28,11 @@ public class Pawn extends APiece {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Pawn's possible moves
|
||||
* @param attack force the attack mode
|
||||
* @return two-dimensional array of moves
|
||||
*/
|
||||
@Override
|
||||
public boolean[][] getPossibleMoves(boolean attack) {
|
||||
|
||||
|
@ -51,6 +56,11 @@ public class Pawn extends APiece {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if en passant possible
|
||||
* @param directionX en passant X direction
|
||||
* @return true, if possible
|
||||
*/
|
||||
private boolean checkEnPassant(int directionX) {
|
||||
APiece piece = chessboard.getPiece(x+directionX, y);
|
||||
if(piece == null) return false;
|
||||
|
@ -58,17 +68,23 @@ public class Pawn extends APiece {
|
|||
return chessboard.lastMove[y][x+directionX] && piece instanceof Pawn && y == pieceY && piece.getMoveCount() == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the piece to the new position
|
||||
* @param newX new X position
|
||||
* @param newY new Y position
|
||||
* @param animate animate piece's move
|
||||
*/
|
||||
@Override
|
||||
public void move(PiecePosition pos, boolean animate) {
|
||||
public void move(int newX, int newY, boolean animate) {
|
||||
|
||||
for (int directionX : new int[]{-1, 1}) {
|
||||
if(checkEnPassant(directionX) && pos.x == x+directionX) {
|
||||
if(checkEnPassant(directionX) && newX == x+directionX) {
|
||||
APiece piece = chessboard.getPiece(x+directionX, y);
|
||||
if(piece != null) piece.remove(true);
|
||||
}
|
||||
}
|
||||
|
||||
super.move(pos, animate);
|
||||
super.move(newX, newY, animate);
|
||||
|
||||
int changeY = player.getStartPosition() == StartPosition.BOTTOM ? 0 : chessboard.SQUARE_COUNT-1;
|
||||
if(y == changeY) {
|
||||
|
|
|
@ -34,11 +34,20 @@ public enum PieceColor {
|
|||
setColors(fillColor, drawColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set piece's fill and draw colors
|
||||
* @param fillColor piece's fill color
|
||||
* @param drawColor piece's border color
|
||||
*/
|
||||
public void setColors(Color fillColor, Color drawColor) {
|
||||
fill = fillColor;
|
||||
draw = drawColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set theme to the piece color
|
||||
* @param theme new theme
|
||||
*/
|
||||
public static void setTheme(Theme theme) {
|
||||
PieceColor.WHITE.setColors(theme.whiteFill, theme.whiteBorder);
|
||||
PieceColor.BLACK.setColors(theme.blackFill, theme.blackBorder);
|
||||
|
|
|
@ -13,10 +13,19 @@ public class PiecePosition {
|
|||
*/
|
||||
public int y;
|
||||
|
||||
/**
|
||||
* Conversion to the string
|
||||
* @return string representation
|
||||
*/
|
||||
public String toString() {
|
||||
return String.valueOf((char) (x+97)) + (8-y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse PiecePosition from String
|
||||
* @param position parsed String
|
||||
* @return PiecePosition or null
|
||||
*/
|
||||
public static PiecePosition fromString(String position) {
|
||||
try {
|
||||
int x = position.charAt(0) - 97;
|
||||
|
|
|
@ -1,31 +1,69 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Player class
|
||||
*/
|
||||
public class Player {
|
||||
|
||||
/**
|
||||
* Player's chessboard
|
||||
*/
|
||||
private Chessboard chessboard;
|
||||
|
||||
/**
|
||||
* Player's piece color
|
||||
*/
|
||||
private PieceColor color;
|
||||
|
||||
/**
|
||||
* Player's start position
|
||||
*/
|
||||
private StartPosition startPosition;
|
||||
|
||||
/**
|
||||
* King piece
|
||||
*/
|
||||
private King king;
|
||||
|
||||
/**
|
||||
* Active CPU mode
|
||||
*/
|
||||
private String cpu;
|
||||
|
||||
/**
|
||||
* Waiting for CPU move
|
||||
*/
|
||||
private boolean isPlaying = false;
|
||||
|
||||
/**
|
||||
* Delays between player's moves
|
||||
*/
|
||||
private ArrayList<Integer> delays = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Player's constructor
|
||||
* @param chessboard player's chessboard
|
||||
* @param startPosition player's start position
|
||||
* @param color player's color
|
||||
*/
|
||||
public Player(Chessboard chessboard, StartPosition startPosition, PieceColor color) {
|
||||
this.chessboard = chessboard;
|
||||
this.color = color;
|
||||
this.startPosition = startPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects if player is in check
|
||||
* @return true, if in check
|
||||
*/
|
||||
public boolean inCheck() {
|
||||
return king.isEndangered();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects if player has no possible moves
|
||||
* @return true, if no possible moves
|
||||
*/
|
||||
public boolean hasNoPossibleMove() {
|
||||
for (APiece piece : getPieces()) {
|
||||
boolean[][] possibleMoves = piece.getPossibleMoves();
|
||||
|
@ -38,6 +76,9 @@ public class Player {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Play automatically as CPU
|
||||
*/
|
||||
public void play() {
|
||||
if(cpu == null) return;
|
||||
isPlaying = true;
|
||||
|
@ -55,6 +96,10 @@ public class Player {
|
|||
}, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select random piece and move it randomly
|
||||
* @return true, if piece was moved
|
||||
*/
|
||||
public boolean randomMove() {
|
||||
ArrayList<APiece> myPieces = getPieces();
|
||||
while(myPieces.size() != 0) {
|
||||
|
@ -78,13 +123,17 @@ public class Player {
|
|||
}
|
||||
|
||||
PiecePosition randomMove = possibleMoves.get(r.nextInt(moveCount));
|
||||
selectedPiece.move(randomMove, true);
|
||||
selectedPiece.move(randomMove.x, randomMove.y, true);
|
||||
chessboard.changeActivePlayer();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move piece according to the stockfish engine
|
||||
* @return true, if piece was moved
|
||||
*/
|
||||
public boolean smartMove() {
|
||||
Stockfish stockfish = Stockfish.getInstance();
|
||||
if(stockfish == null) return false;
|
||||
|
@ -95,31 +144,55 @@ public class Player {
|
|||
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);
|
||||
piece.move(toPos.x, toPos.y);
|
||||
chessboard.changeActivePlayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get player's chessboard
|
||||
* @return chessboard
|
||||
*/
|
||||
public Chessboard getChessboard() {
|
||||
return chessboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get player's piece color
|
||||
* @return piece color
|
||||
*/
|
||||
public PieceColor getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get player's start position
|
||||
* @return start position
|
||||
*/
|
||||
public StartPosition getStartPosition() {
|
||||
return startPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get player's King piece
|
||||
* @return King
|
||||
*/
|
||||
public King getKing() {
|
||||
return king;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set player's King piece
|
||||
* @param king new King
|
||||
*/
|
||||
public void setKing(King king) {
|
||||
this.king = king;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all player's pieces
|
||||
* @return player's pieces
|
||||
*/
|
||||
public ArrayList<APiece> getPieces() {
|
||||
ArrayList<APiece> myPieces = new ArrayList<>();
|
||||
for (APiece[] pieces : chessboard.pieces) {
|
||||
|
@ -132,19 +205,36 @@ public class Player {
|
|||
return myPieces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set player's CPU mode
|
||||
* @param cpu CPU mode
|
||||
*/
|
||||
public void setCPU(String cpu) {
|
||||
// TODO: use enums
|
||||
this.cpu = cpu;
|
||||
if(chessboard.getActivePlayer() == this && !isPlaying) play();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get player's CPU mode
|
||||
* @return CPU mode
|
||||
*/
|
||||
public String getCPU() {
|
||||
return cpu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new delay before last move
|
||||
* @param delay delay in ms
|
||||
*/
|
||||
public void addDelay(int delay) {
|
||||
delays.add(delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all delays between moves
|
||||
* @return delays list
|
||||
*/
|
||||
public List<Integer> getDelays() {
|
||||
return delays;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,11 @@ public class Queen extends APiece {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Queen's possible moves
|
||||
* @param attack force the attack mode
|
||||
* @return two-dimensional array of moves
|
||||
*/
|
||||
@Override
|
||||
public boolean[][] getPossibleMoves(boolean attack) {
|
||||
boolean[][] moves = new boolean[chessboard.SQUARE_COUNT][chessboard.SQUARE_COUNT];
|
||||
|
|
|
@ -29,6 +29,11 @@ public class Rook extends APiece {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Rook's possible moves
|
||||
* @param attack force the attack mode
|
||||
* @return two-dimensional array of moves
|
||||
*/
|
||||
@Override
|
||||
public boolean[][] getPossibleMoves(boolean attack) {
|
||||
boolean[][] moves = new boolean[chessboard.SQUARE_COUNT][chessboard.SQUARE_COUNT];
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/**
|
||||
* Starting position of the player
|
||||
*/
|
||||
public enum StartPosition {
|
||||
|
||||
TOP, BOTTOM;
|
||||
|
|
|
@ -2,22 +2,52 @@ 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(".");
|
||||
|
@ -33,12 +63,21 @@ public class Stockfish {
|
|||
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(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");
|
||||
|
@ -48,6 +87,12 @@ public class Stockfish {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
@ -62,6 +107,13 @@ public class Stockfish {
|
|||
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);
|
||||
|
@ -79,6 +131,9 @@ public class Stockfish {
|
|||
return parts[1].split(" ")[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the stockfish engine
|
||||
*/
|
||||
public void stopEngine() {
|
||||
try {
|
||||
sendCommand("quit");
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Color themes for the chessboard and pieces
|
||||
*/
|
||||
public enum Theme {
|
||||
|
||||
CLASSIC(
|
||||
|
@ -18,21 +21,60 @@ public enum Theme {
|
|||
Color.decode("#FF8A80"), Color.decode("#e2514c")
|
||||
);
|
||||
|
||||
/**
|
||||
* Current active theme
|
||||
*/
|
||||
public static Theme activeTheme = Theme.CLASSIC;
|
||||
|
||||
/**
|
||||
* Set new active theme
|
||||
* @param theme selected theme
|
||||
*/
|
||||
public static void setTheme(Theme theme) {
|
||||
activeTheme = theme;
|
||||
Chessboard.setTheme(theme);
|
||||
PieceColor.setTheme(theme);
|
||||
}
|
||||
|
||||
/**
|
||||
* White piece's fill color
|
||||
*/
|
||||
Color whiteFill;
|
||||
|
||||
/**
|
||||
* White piece's border color
|
||||
*/
|
||||
Color whiteBorder;
|
||||
|
||||
/**
|
||||
* Black piece's fill color
|
||||
*/
|
||||
Color blackFill;
|
||||
|
||||
/**
|
||||
* Black piece's border color
|
||||
*/
|
||||
Color blackBorder;
|
||||
|
||||
/**
|
||||
* Chessboard light square's color
|
||||
*/
|
||||
Color lightSquare;
|
||||
|
||||
/**
|
||||
* Chessboard dark square's color
|
||||
*/
|
||||
Color darkSquare;
|
||||
|
||||
/**
|
||||
* Constructor of the theme
|
||||
* @param whiteFill white piece's fill
|
||||
* @param whiteBorder white piece's border
|
||||
* @param blackFill black piece's fill
|
||||
* @param blackBorder black piece's border
|
||||
* @param lightSquare light square's color
|
||||
* @param darkSquare dark square's color
|
||||
*/
|
||||
Theme(Color whiteFill, Color whiteBorder, Color blackFill, Color blackBorder, Color lightSquare, Color darkSquare) {
|
||||
this.whiteFill = whiteFill;
|
||||
this.whiteBorder = whiteBorder;
|
||||
|
|
Loading…
Reference in a new issue