This commit is contained in:
cleme 2025-05-23 17:05:18 +02:00
parent b08bd6477f
commit 9ee1df68d8
1 changed files with 359 additions and 0 deletions

View File

@ -0,0 +1,359 @@
package backend;
import java.util.ArrayList;
import java.util.List;
public class CastlingHandler {
private Board board;
public CastlingHandler(Board board) {
this.board = board;
}
public class CastlingMove {
public final int kingFromX, kingFromY, kingToX, kingToY;
public final int rookFromX, rookFromY, rookToX, rookToY;
public final boolean isKingside;
public CastlingMove(int kingFromX, int kingFromY, int kingToX, int kingToY,
int rookFromX, int rookFromY, int rookToX, int rookToY,
boolean isKingside) {
this.kingFromX = kingFromX;
this.kingFromY = kingFromY;
this.kingToX = kingToX;
this.kingToY = kingToY;
this.rookFromX = rookFromX;
this.rookFromY = rookFromY;
this.rookToX = rookToX;
this.rookToY = rookToY;
this.isKingside = isKingside;
}
}
public class Position {
public int x;
public int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Position position = (Position) obj;
return x == position.x && y == position.y;
}
}
/**
* Checks if castling is possible and returns the castling move details
*/
public CastlingMove getCastlingMove(int fromX, int fromY, int toX, int toY) {
Piece piece = board.getPieceAt(fromX, fromY);
// Must be a king
if (piece == null || piece.getType() != PieceType.King) {
return null;
}
boolean isWhite = piece.isWhite();
int kingRow = isWhite ? 7 : 0;
// King must be on its starting position
if (fromY != kingRow || fromX != 4) {
return null;
}
// Check if this is a castling move (king moves 2 squares horizontally)
if (fromY != toY || Math.abs(toX - fromX) != 2) {
return null;
}
boolean isKingside = toX > fromX;
int rookStartX = isKingside ? 7 : 0;
int rookEndX = isKingside ? 5 : 3;
return new CastlingMove(fromX, fromY, toX, toY,
rookStartX, kingRow, rookEndX, kingRow,
isKingside);
}
/**
* Validates if castling is legal
*/
public boolean isCastlingValid(CastlingMove castling) {
if (castling == null) return false;
Piece king = board.getPieceAt(castling.kingFromX, castling.kingFromY);
Piece rook = board.getPieceAt(castling.rookFromX, castling.rookFromY);
// Verify pieces exist and are correct type/color
if (king == null || king.getType() != PieceType.King) return false;
if (rook == null || rook.getType() != PieceType.Rook) return false;
if (king.isWhite() != rook.isWhite()) return false;
// Check if king or rook have moved (simplified - assumes starting positions)
boolean isWhite = king.isWhite();
int expectedKingRow = isWhite ? 7 : 0;
if (castling.kingFromY != expectedKingRow || castling.kingFromX != 4) return false;
if (castling.rookFromY != expectedKingRow) return false;
if (castling.isKingside && castling.rookFromX != 7) return false;
if (!castling.isKingside && castling.rookFromX != 0) return false;
// Check path is clear between king and rook
int startX = Math.min(castling.kingFromX, castling.rookFromX) + 1;
int endX = Math.max(castling.kingFromX, castling.rookFromX) - 1;
for (int x = startX; x <= endX; x++) {
if (board.getPieceAt(x, castling.kingFromY) != null) {
return false;
}
}
// Check that king is not in check
if (isKingInCheck(isWhite)) {
return false;
}
// Check that king doesn't pass through check
for (int x = castling.kingFromX; x != castling.kingToX + (castling.isKingside ? 1 : -1);
x += castling.isKingside ? 1 : -1) {
// Create temporary board with king at this position
Board tempBoard = new Board(board);
tempBoard.removePiece(castling.kingFromX, castling.kingFromY);
tempBoard.setPiece(isWhite, PieceType.King, x, castling.kingFromY);
CastlingHandler tempHandler = new CastlingHandler(tempBoard);
if (tempHandler.isKingInCheck(isWhite)) {
return false;
}
}
return true;
}
/**
* Executes the castling move on the board
*/
public void executeCastling(CastlingMove castling) {
Piece king = board.getPieceAt(castling.kingFromX, castling.kingFromY);
Piece rook = board.getPieceAt(castling.rookFromX, castling.rookFromY);
// Move the king
board.removePiece(castling.kingFromX, castling.kingFromY);
board.setPiece(king.isWhite(), king.getType(), castling.kingToX, castling.kingToY);
// Move the rook
board.removePiece(castling.rookFromX, castling.rookFromY);
board.setPiece(rook.isWhite(), rook.getType(), castling.rookToX, castling.rookToY);
}
/**
* Gets all possible castling moves for a king
*/
public List<Position> getCastlingPositions(Piece king) {
List<Position> castlingMoves = new ArrayList<>();
if (king.getType() != PieceType.King) {
return castlingMoves;
}
boolean isWhite = king.isWhite();
int kingRow = isWhite ? 7 : 0;
// King must be on starting position
if (king.getX() != 4 || king.getY() != kingRow) {
return castlingMoves;
}
// Check kingside castling
CastlingMove kingsideCastling = getCastlingMove(4, kingRow, 6, kingRow);
if (isCastlingValid(kingsideCastling)) {
castlingMoves.add(new Position(6, kingRow));
}
// Check queenside castling
CastlingMove queensideCastling = getCastlingMove(4, kingRow, 2, kingRow);
if (isCastlingValid(queensideCastling)) {
castlingMoves.add(new Position(2, kingRow));
}
return castlingMoves;
}
public boolean isKingInCheck(boolean isWhiteKing) {
// Find the king's position
Piece king = null;
for (Piece p : board.getPieces()) {
if (p.getType() == PieceType.King && p.isWhite() == isWhiteKing) {
king = p;
break;
}
}
if (king == null) return false;
return checkIfKingUnderAttack(isWhiteKing, king);
}
private boolean checkIfKingUnderAttack(boolean isWhiteKing, Piece king) {
// Check if any opponent piece can attack the king
for (Piece p : board.getPieces()) {
if (p.isWhite() == isWhiteKing) continue; // Skip pieces of same color
// Get raw moves without check validation
List<Position> attackMoves = getValidDestinations(p);
// If any piece can move to king's position, king is in check
for (Position pos : attackMoves) {
if (pos.x == king.getX() && pos.y == king.getY()) {
return true;
}
}
}
return false;
}
private List<Position> getValidDestinations(Piece piece) {
List<Position> moves = new ArrayList<>();
switch (piece.getType()) {
case Pawn:
addPawnMoves(moves, piece);
break;
case Rook:
addRookMoves(moves, piece);
break;
case Knight:
addKnightMoves(moves, piece);
break;
case Bishop:
addBishopMoves(moves, piece);
break;
case Queen:
addRookMoves(moves, piece);
addBishopMoves(moves, piece);
break;
case King:
addKingMoves(moves, piece);
break;
}
return moves;
}
private void addPawnMoves(List<Position> validMoves, Piece piece) {
int x = piece.getX();
int y = piece.getY();
boolean isWhite = piece.isWhite();
int direction = isWhite ? -1 : 1;
// Diagonal captures only (for attack patterns)
int newY = y + direction;
if (newY >= 0 && newY < board.getHeight()) {
for (int dx = -1; dx <= 1; dx += 2) {
int newX = x + dx;
if (newX >= 0 && newX < board.getWidth()) {
validMoves.add(new Position(newX, newY));
}
}
}
}
private void addRookMoves(List<Position> validMoves, Piece piece) {
int x = piece.getX();
int y = piece.getY();
boolean isWhite = piece.isWhite();
int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
for (int[] dir : directions) {
int dx = dir[0];
int dy = dir[1];
int newX = x + dx;
int newY = y + dy;
while (newX >= 0 && newX < board.getWidth() && newY >= 0 && newY < board.getHeight()) {
validMoves.add(new Position(newX, newY));
Piece targetPiece = board.getPieceAt(newX, newY);
if (targetPiece != null) {
break; // Cannot move beyond a piece
}
newX += dx;
newY += dy;
}
}
}
private void addKnightMoves(List<Position> validMoves, Piece piece) {
int x = piece.getX();
int y = piece.getY();
int[][] knightMoves = {
{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2},
{1, -2}, {1, 2}, {2, -1}, {2, 1}
};
for (int[] move : knightMoves) {
int newX = x + move[0];
int newY = y + move[1];
if (newX >= 0 && newX < board.getWidth() && newY >= 0 && newY < board.getHeight()) {
validMoves.add(new Position(newX, newY));
}
}
}
private void addBishopMoves(List<Position> validMoves, Piece piece) {
int x = piece.getX();
int y = piece.getY();
int[][] directions = {{1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
for (int[] dir : directions) {
int dx = dir[0];
int dy = dir[1];
int newX = x + dx;
int newY = y + dy;
while (newX >= 0 && newX < board.getWidth() && newY >= 0 && newY < board.getHeight()) {
validMoves.add(new Position(newX, newY));
Piece targetPiece = board.getPieceAt(newX, newY);
if (targetPiece != null) {
break; // Cannot move beyond a piece
}
newX += dx;
newY += dy;
}
}
}
private void addKingMoves(List<Position> validMoves, Piece piece) {
int x = piece.getX();
int y = piece.getY();
for (int dx = -1; dx <= 1; dx++) {
for (int dy = -1; dy <= 1; dy++) {
if (dx == 0 && dy == 0) continue;
int newX = x + dx;
int newY = y + dy;
if (newX >= 0 && newX < board.getWidth() && newY >= 0 && newY < board.getHeight()) {
validMoves.add(new Position(newX, newY));
}
}
}
}
}