From 317260609a4fd326cb21e6f325c52326328111fe Mon Sep 17 00:00:00 2001 From: Yash Shah Date: Sat, 17 May 2025 13:12:33 +0200 Subject: [PATCH] Castling on both queen and king side --- src/backend/Board.java | 114 +++++++++++++++++++++++++++++++++++++++-- src/backend/Piece.java | 15 +++++- 2 files changed, 124 insertions(+), 5 deletions(-) diff --git a/src/backend/Board.java b/src/backend/Board.java index 2b95b27..cabeac8 100644 --- a/src/backend/Board.java +++ b/src/backend/Board.java @@ -35,8 +35,9 @@ public class Board { this.highlighted = new ArrayList<>(); for (int[] pos : other.highlighted) { this.highlighted.add(new int[]{pos[0], pos[1]}); + } - + this.moveHistory = new ArrayList<>(other.moveHistory); } @@ -215,8 +216,28 @@ public class Board { } } } - + private boolean simulateOnly = false; + + public void setSimulateOnly(boolean simulateOnly) { + this.simulateOnly = simulateOnly; + } + + public boolean isSimulateOnly() { + return simulateOnly; + } + private boolean isSquareUnderAttack(boolean byWhite, int x, int y) { + for (Piece p : pieces) { + if (p.isWhite() != byWhite) continue; + ArrayList enemyMoves = getLegalMoves(p, false); // No king safety check here + for (int[] move : enemyMoves) { + if (move[0] == x && move[1] == y) return true; + } + } + return false; + } + + public ArrayList getLegalMoves(Piece piece) { return getLegalMoves(piece, true); // default: check for king safety } @@ -278,11 +299,56 @@ public class Board { for (int dy = -1; dy <= 1; dy++) { if (dx == 0 && dy == 0) continue; int nx = x + dx, ny = y + dy; - if (isInBounds(nx, ny) && (getPieceAt(nx, ny) == null || getPieceAt(nx, ny).isWhite() != piece.isWhite())) { - moves.add(new int[]{nx, ny}); + if (isInBounds(nx, ny)) { + Piece target = getPieceAt(nx, ny); + if (target == null || target.isWhite() != piece.isWhite()) { + moves.add(new int[]{nx, ny}); + } } } } + + // Castling logic + // Castling logic + if (!piece.hasMoved() && (!validateCheck || !isInCheck(piece.isWhite()))) { + int row = piece.isWhite() ? 0 : 7; + + // Kingside castling + Piece kingsideRook = getPieceAt(7, row); + if (kingsideRook != null && + kingsideRook.getType() == PieceType.Rook && + !kingsideRook.hasMoved() && + getPieceAt(5, row) == null && + getPieceAt(6, row) == null) { + + if (!validateCheck || ( + !isSquareUnderAttack(!piece.isWhite(), 4, row) && + !isSquareUnderAttack(!piece.isWhite(), 5, row) && + !isSquareUnderAttack(!piece.isWhite(), 6, row))) { + + moves.add(new int[]{6, row}); + } + } + + // Queenside castling + Piece queensideRook = getPieceAt(0, row); + if (queensideRook != null && + queensideRook.getType() == PieceType.Rook && + !queensideRook.hasMoved() && + getPieceAt(1, row) == null && + getPieceAt(2, row) == null && + getPieceAt(3, row) == null) { + + if (!validateCheck || ( + !isSquareUnderAttack(!piece.isWhite(), 4, row) && + !isSquareUnderAttack(!piece.isWhite(), 3, row) && + !isSquareUnderAttack(!piece.isWhite(), 2, row))) { + + moves.add(new int[]{2, row}); + } + } + } + break; case Knight: @@ -383,9 +449,32 @@ public void undoLastMove() { Move lastMove = moveHistory.remove(moveHistory.size() - 1); Piece movedPiece = lastMove.getPieceMoved(); + + // Undo castling + if (movedPiece.getType() == PieceType.King && Math.abs(lastMove.getToX() - lastMove.getFromX()) == 2) { + int row = movedPiece.isWhite() ? 0 : 7; + + if (lastMove.getToX() == 6) { // Kingside + Piece rook = getPieceAt(5, row); + if (rook != null && rook.getType() == PieceType.Rook) { + rook.setPosition(7, row); + rook.setHasMoved(false); + } + } else if (lastMove.getToX() == 2) { // Queenside + Piece rook = getPieceAt(3, row); + if (rook != null && rook.getType() == PieceType.Rook) { + rook.setPosition(0, row); + rook.setHasMoved(false); + } + } + } + // Move the piece back to its original position movedPiece.setPosition(lastMove.getFromX(), lastMove.getFromY()); + + movedPiece.setHasMoved(false); + // Restore the captured piece if any if (lastMove.getPieceCaptured() != null) { @@ -403,6 +492,23 @@ public void undoLastMove() { public void playMove(Move move) { Piece piece = move.getPieceMoved(); + if (piece.getType() == PieceType.King && Math.abs(move.getToX() - move.getFromX()) == 2) { + int row = piece.isWhite() ? 0 : 7; + // Kingside castling + if (move.getToX() == 6) { + Piece rook = getPieceAt(7, row); + if (rook != null) { + rook.setPosition(5, row); // rook moves to f1/f8 + } + } + // Queenside castling + else if (move.getToX() == 2) { + Piece rook = getPieceAt(0, row); + if (rook != null) { + rook.setPosition(3, row); // rook moves to d1/d8 + } + } + } // If a piece is captured, remove it from the board if (move.getPieceCaptured() != null) { diff --git a/src/backend/Piece.java b/src/backend/Piece.java index c00a910..1490f6b 100644 --- a/src/backend/Piece.java +++ b/src/backend/Piece.java @@ -35,14 +35,27 @@ public class Piece { public void setPosition(int x , int y) { this.x=x; - this.y=y; + this.y=y; + this.hasMoved=true; } + public Piece(Piece other) { this.isWhite = other.isWhite; this.type = other.type; this.x = other.x; this.y = other.y; + this.hasMoved = other.hasMoved; } + private boolean hasMoved = false; + + public boolean hasMoved() { + return hasMoved; + } + + public void setHasMoved(boolean moved) { + this.hasMoved = moved; + } + }