This commit is contained in:
@@ -54,6 +54,10 @@ public class ChessBoard {
|
||||
this.kingPos = new Coordinate[Color.values().length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a move on the board.
|
||||
* @param move move to apply
|
||||
*/
|
||||
public void applyMove(Move move) {
|
||||
assert move.isValid() : "Invalid move !";
|
||||
Piece deadPiece = pieceAt(move.getDeadPieceCoords());
|
||||
@@ -70,12 +74,20 @@ public class ChessBoard {
|
||||
this.lastVirtualMove = move;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo the last move
|
||||
*/
|
||||
public void undoLastMove() {
|
||||
assert this.lastVirtualMove != null : "Can't undo at the beginning!";
|
||||
|
||||
undoMove(this.lastVirtualMove, this.lastEjectedPiece);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo the specified move
|
||||
* @param move
|
||||
* @param deadPiece
|
||||
*/
|
||||
public void undoMove(Move move, Piece deadPiece) {
|
||||
Piece movingPiece = pieceAt(move.getFinish());
|
||||
pieceComes(movingPiece, move.getStart());
|
||||
@@ -85,16 +97,29 @@ public class ChessBoard {
|
||||
movingPiece.unMove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the cell is empty
|
||||
* @param coordinate
|
||||
* @return true if the cell is empty
|
||||
*/
|
||||
public boolean isCellEmpty(Coordinate coordinate) {
|
||||
return pieceAt(coordinate) == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the piece at the given coordinates
|
||||
* @param coordinate
|
||||
* @return piece at the given coordinates, or null if the coordinates are invalid or the cell is empty
|
||||
*/
|
||||
public Piece pieceAt(Coordinate coordinate) {
|
||||
if (!coordinate.isValid())
|
||||
return null;
|
||||
return cellAt(coordinate).getPiece();
|
||||
}
|
||||
|
||||
/**
|
||||
* Nuke all pieces of the board
|
||||
*/
|
||||
public void clearBoard() {
|
||||
for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
|
||||
for (int j = 0; j < Coordinate.VALUE_MAX; j++) {
|
||||
@@ -103,24 +128,48 @@ public class ChessBoard {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cell at the given coordinates
|
||||
* @param coordinate
|
||||
* @return
|
||||
*/
|
||||
private Cell cellAt(Coordinate coordinate) {
|
||||
return this.cells[coordinate.getX()][coordinate.getY()];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the piece at the given coordinate
|
||||
*/
|
||||
public void pieceComes(Piece piece, Coordinate coordinate) {
|
||||
cellAt(coordinate).setPiece(piece);
|
||||
if (piece instanceof King)
|
||||
this.kingPos[piece.getColor().ordinal()] = coordinate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the piece at the given coordiinates
|
||||
* @param coordinate
|
||||
*/
|
||||
public void pieceLeaves(Coordinate coordinate) {
|
||||
cellAt(coordinate).setPiece(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the king of the given color on the board
|
||||
* @param color
|
||||
* @return the coordinates of the king
|
||||
*/
|
||||
public Coordinate findKing(Color color) {
|
||||
return kingPos[color.ordinal()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the allowed starting positions for a piece to attack the given Coordinate. Useful for PGN trasnlation.
|
||||
* @param finish
|
||||
* @param color
|
||||
* @return coordinates of the pieces that could attack
|
||||
*/
|
||||
public List<Coordinate> getAllowedStarts(Coordinate finish, Color color) {
|
||||
List<Coordinate> starts = new ArrayList<>();
|
||||
for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
|
||||
@@ -145,6 +194,11 @@ public class ChessBoard {
|
||||
return starts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the king of the given color is in check
|
||||
* @param color
|
||||
* @return true if the king is in check
|
||||
*/
|
||||
public boolean isKingInCheck(Color color) {
|
||||
Coordinate kingPos = findKing(color);
|
||||
assert kingPos.isValid() : "King position is invalid!";
|
||||
@@ -164,10 +218,20 @@ public class ChessBoard {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given player has allowed moves
|
||||
* @param player
|
||||
* @return true if the player can move
|
||||
*/
|
||||
public boolean hasAllowedMoves(Color player) {
|
||||
return !getAllowedMoves(player).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the allowed moves for the given player
|
||||
* @param player
|
||||
* @return
|
||||
*/
|
||||
public List<Move> getAllowedMoves(Color player) {
|
||||
if (this.cachedAllowedMoves != null) {
|
||||
return this.cachedAllowedMoves;
|
||||
@@ -211,7 +275,10 @@ public class ChessBoard {
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Coordinate> getAllowedMoves(Coordinate pieceCoords) {
|
||||
/**
|
||||
* Get all the end positions possible of a piece
|
||||
*/
|
||||
public List<Coordinate> getPieceAllowedMoves(Coordinate pieceCoords) {
|
||||
Piece piece = pieceAt(pieceCoords);
|
||||
if (piece == null)
|
||||
return null;
|
||||
@@ -239,6 +306,13 @@ public class ChessBoard {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given player can castle with the given rook
|
||||
* @param color
|
||||
* @param rookX
|
||||
* @param kingDirection
|
||||
* @return true if the player can Castle
|
||||
*/
|
||||
private boolean canCastle(Color color, int rookX, Direction kingDirection) {
|
||||
if (isKingInCheck(color))
|
||||
return false;
|
||||
@@ -273,20 +347,32 @@ public class ChessBoard {
|
||||
return obstacle == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return wether the player can perform a kingside castling.
|
||||
*/
|
||||
public boolean canSmallCastle(Color color) {
|
||||
return canCastle(color, 7, Direction.Right);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given player is allowed to execute a queenside castling.
|
||||
* @param color
|
||||
* @return
|
||||
*/
|
||||
public boolean canBigCastle(Color color) {
|
||||
return canCastle(color, 0, Direction.Left);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is a pawn to be promoted by the given player.
|
||||
* @return
|
||||
*/
|
||||
public boolean pawnShouldBePromoted() {
|
||||
return pawnPromotePosition() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Check if there's a pawn in the adversary line on the board
|
||||
* @return Null if there is no pawn to promote
|
||||
*/
|
||||
public Coordinate pawnPromotePosition() {
|
||||
@@ -297,7 +383,7 @@ public class ChessBoard {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Check if there's a pawn of the given player in the adversary line on the board
|
||||
* @return Null if there is no pawn to promote
|
||||
*/
|
||||
private Coordinate pawnPromotePosition(Color color) {
|
||||
@@ -315,6 +401,10 @@ public class ChessBoard {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash according to the pieces position on the board
|
||||
* @return hash code
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 0;
|
||||
@@ -329,10 +419,16 @@ public class ChessBoard {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the last played move
|
||||
*/
|
||||
public Move getLastMove() {
|
||||
return this.lastMove;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the last move of the board and invalidate the allowedMoves cache.
|
||||
*/
|
||||
public void setLastMove(Move lastMove) {
|
||||
this.lastMove = lastMove;
|
||||
this.cachedAllowedMoves = null;
|
||||
|
||||
@@ -38,19 +38,24 @@ public class Game {
|
||||
return playerTurn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the game
|
||||
*/
|
||||
public void reset() {
|
||||
resetPlayerTurn();
|
||||
this.traitsPos.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the player turn.
|
||||
* Aka: white for the win
|
||||
*/
|
||||
public void resetPlayerTurn() {
|
||||
this.playerTurn = Color.White;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param color the current player turn
|
||||
* @return true if a draw should be declared
|
||||
* Save the current board configuration
|
||||
*/
|
||||
public void saveTraitPiecesPos() {
|
||||
int piecesHash = this.board.hashCode();
|
||||
@@ -67,14 +72,16 @@ public class Game {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if a draw should occur
|
||||
* Switch player turn
|
||||
*/
|
||||
public void switchPlayerTurn() {
|
||||
playerTurn = Color.getEnemy(playerTurn);
|
||||
}
|
||||
|
||||
// this is the bottleneck of algorithms using this chess engine
|
||||
/**
|
||||
* Check the status of the game ofr the specified player
|
||||
* @return a GameStatus enum
|
||||
*/
|
||||
public GameStatus checkGameStatus(Color color) {
|
||||
if (checkDraw())
|
||||
return GameStatus.Draw;
|
||||
@@ -91,20 +98,32 @@ public class Game {
|
||||
return GameStatus.OnGoing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the status of the gamere
|
||||
*/
|
||||
public GameStatus checkGameStatus() {
|
||||
return checkGameStatus(Color.getEnemy(getPlayerTurn()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a player move (basic move, castling, ...) to the game history.
|
||||
*/
|
||||
public void addAction(PlayerCommand command) {
|
||||
this.movesHistory.add(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the last player action
|
||||
*/
|
||||
public PlayerCommand getLastAction() {
|
||||
if (this.movesHistory.isEmpty())
|
||||
return null;
|
||||
return this.movesHistory.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the last board move ater an undo.
|
||||
*/
|
||||
public void updateLastMove() {
|
||||
if (this.movesHistory.isEmpty())
|
||||
return;
|
||||
@@ -115,6 +134,9 @@ public class Game {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the board configuration occurence from the game history
|
||||
*/
|
||||
public void undoTraitPiecesPos() {
|
||||
int piecesHash = this.board.hashCode();
|
||||
Integer count = this.traitsPos.get(piecesHash);
|
||||
@@ -126,6 +148,9 @@ public class Game {
|
||||
return this.movesHistory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return wether a pawn should be promoted
|
||||
*/
|
||||
public boolean pawnShouldBePromoted() {
|
||||
return this.board.pawnShouldBePromoted();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@ public class Move {
|
||||
this.deadPieceCoords = finish;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if the move is valid, false otherwise
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return this.start.isValid() && this.finish.isValid() && !this.start.equals(this.finish);
|
||||
}
|
||||
@@ -27,6 +31,10 @@ public class Move {
|
||||
return finish;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of cells traversed by the move.
|
||||
* @return int
|
||||
*/
|
||||
public int traversedCells() {
|
||||
assert isValid() : "Move is invalid!";
|
||||
|
||||
@@ -45,6 +53,9 @@ public class Move {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the coordinates of the cell in the middle of the move
|
||||
*/
|
||||
public Coordinate getMiddle() {
|
||||
return Coordinate.fromIndex((getStart().toIndex() + getFinish().toIndex()) / 2);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user