final push

This commit is contained in:
cleme 2025-05-23 23:56:06 +02:00
parent 02a7fe387b
commit 97deab60e7
5 changed files with 234 additions and 129 deletions

View File

@ -21,6 +21,7 @@ public class Board {
private Move lastMove = null; private Move lastMove = null;
private Enpassant enpassantHandler; private Enpassant enpassantHandler;
private CastlingHandler castlingHandler;
public Board(int colNum, int lineNum) { public Board(int colNum, int lineNum) {
this.width = colNum; this.width = colNum;
@ -33,6 +34,7 @@ public class Board {
this.sound = new Sound(); this.sound = new Sound();
this.lastMove = null; this.lastMove = null;
this.enpassantHandler = new Enpassant(this); this.enpassantHandler = new Enpassant(this);
this.castlingHandler = new CastlingHandler(this);
} }
public int getWidth() { public int getWidth() {
@ -186,6 +188,12 @@ public class Board {
if (isHighlighted(x, y)) { if (isHighlighted(x, y)) {
saveCurrentState(); saveCurrentState();
CastlingHandler.CastlingMove castlingMove = castlingHandler.getCastlingMove(selectedX, selectedY, x, y);
if (castlingMove != null && castlingHandler.isCastlingValid(castlingMove)) {
castlingHandler.executeCastling(castlingMove);
this.lastMove = new Move(selectedX, selectedY, x, y, this);
sound.playMoveSound();
} else {
Move move = new Move(selectedX, selectedY, x, y, this); Move move = new Move(selectedX, selectedY, x, y, this);
if (move.isValid()) { if (move.isValid()) {
move.execute(); move.execute();
@ -199,6 +207,7 @@ public class Board {
System.out.println("Check!"); System.out.println("Check!");
} }
} }
}
selectedX = null; selectedX = null;
selectedY = null; selectedY = null;
@ -252,6 +261,7 @@ public class Board {
this.sound = new Sound(); this.sound = new Sound();
this.lastMove = null; this.lastMove = null;
this.enpassantHandler = new Enpassant(this); this.enpassantHandler = new Enpassant(this);
this.castlingHandler = new CastlingHandler(this);
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
if (y >= array.length) { if (y >= array.length) {
@ -334,6 +344,7 @@ public class Board {
this.sound = new Sound(); this.sound = new Sound();
this.enpassantHandler = new Enpassant(this); this.enpassantHandler = new Enpassant(this);
this.castlingHandler = new CastlingHandler(this);
} }
private void clearHighlights() { private void clearHighlights() {
@ -367,6 +378,13 @@ public class Board {
} }
} }
if (selectedPiece.getType() == PieceType.King) {
List<CastlingHandler.Position> castlingMoves = castlingHandler.getCastlingPositions(selectedPiece);
for (CastlingHandler.Position castlingPos : castlingMoves) {
convertedMoves.add(new Position(castlingPos.x, castlingPos.y));
}
}
highlightedPositions.clear(); highlightedPositions.clear();
highlightedPositions.addAll(convertedMoves); highlightedPositions.addAll(convertedMoves);
} }
@ -439,6 +457,14 @@ public class Board {
return enpassantHandler; return enpassantHandler;
} }
public CastlingHandler getCastlingHandler() {
return castlingHandler;
}
public List<Board> getBoardHistory() {
return new ArrayList<>(boardHistory);
}
public class Position { public class Position {
public int x; public int x;
public int y; public int y;

View File

@ -11,9 +11,9 @@ public class CastlingHandler {
} }
public class CastlingMove { public class CastlingMove {
public final int kingFromX, kingFromY, kingToX, kingToY; public int kingFromX, kingFromY, kingToX, kingToY;
public final int rookFromX, rookFromY, rookToX, rookToY; public int rookFromX, rookFromY, rookToX, rookToY;
public final boolean isKingside; public boolean isKingside;
public CastlingMove(int kingFromX, int kingFromY, int kingToX, int kingToY, public CastlingMove(int kingFromX, int kingFromY, int kingToX, int kingToY,
int rookFromX, int rookFromY, int rookToX, int rookToY, int rookFromX, int rookFromY, int rookToX, int rookToY,
@ -28,6 +28,12 @@ public class CastlingHandler {
this.rookToY = rookToY; this.rookToY = rookToY;
this.isKingside = isKingside; this.isKingside = isKingside;
} }
public String toString() {
return (isKingside ? "Kingside" : "Queenside") + " Castling: King(" +
kingFromX + "," + kingFromY + ")->(" + kingToX + "," + kingToY +
"), Rook(" + rookFromX + "," + rookFromY + ")->(" + rookToX + "," + rookToY + ")";
}
} }
public class Position { public class Position {
@ -45,15 +51,19 @@ public class CastlingHandler {
Position position = (Position) obj; Position position = (Position) obj;
return x == position.x && y == position.y; return x == position.x && y == position.y;
} }
public int hashCode() {
return 31 * x + y;
}
public String toString() {
return "(" + x + ", " + y + ")";
}
} }
/**
* Checks if castling is possible and returns the castling move details
*/
public CastlingMove getCastlingMove(int fromX, int fromY, int toX, int toY) { public CastlingMove getCastlingMove(int fromX, int fromY, int toX, int toY) {
Piece piece = board.getPieceAt(fromX, fromY); Piece piece = board.getPieceAt(fromX, fromY);
// Must be a king
if (piece == null || piece.getType() != PieceType.King) { if (piece == null || piece.getType() != PieceType.King) {
return null; return null;
} }
@ -61,12 +71,10 @@ public class CastlingHandler {
boolean isWhite = piece.isWhite(); boolean isWhite = piece.isWhite();
int kingRow = isWhite ? 7 : 0; int kingRow = isWhite ? 7 : 0;
// King must be on its starting position
if (fromY != kingRow || fromX != 4) { if (fromY != kingRow || fromX != 4) {
return null; return null;
} }
// Check if this is a castling move (king moves 2 squares horizontally)
if (fromY != toY || Math.abs(toX - fromX) != 2) { if (fromY != toY || Math.abs(toX - fromX) != 2) {
return null; return null;
} }
@ -80,21 +88,16 @@ public class CastlingHandler {
isKingside); isKingside);
} }
/**
* Validates if castling is legal
*/
public boolean isCastlingValid(CastlingMove castling) { public boolean isCastlingValid(CastlingMove castling) {
if (castling == null) return false; if (castling == null) return false;
Piece king = board.getPieceAt(castling.kingFromX, castling.kingFromY); Piece king = board.getPieceAt(castling.kingFromX, castling.kingFromY);
Piece rook = board.getPieceAt(castling.rookFromX, castling.rookFromY); 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 (king == null || king.getType() != PieceType.King) return false;
if (rook == null || rook.getType() != PieceType.Rook) return false; if (rook == null || rook.getType() != PieceType.Rook) return false;
if (king.isWhite() != rook.isWhite()) return false; if (king.isWhite() != rook.isWhite()) return false;
// Check if king or rook have moved (simplified - assumes starting positions)
boolean isWhite = king.isWhite(); boolean isWhite = king.isWhite();
int expectedKingRow = isWhite ? 7 : 0; int expectedKingRow = isWhite ? 7 : 0;
if (castling.kingFromY != expectedKingRow || castling.kingFromX != 4) return false; if (castling.kingFromY != expectedKingRow || castling.kingFromX != 4) return false;
@ -102,7 +105,62 @@ public class CastlingHandler {
if (castling.isKingside && castling.rookFromX != 7) return false; if (castling.isKingside && castling.rookFromX != 7) return false;
if (!castling.isKingside && castling.rookFromX != 0) return false; if (!castling.isKingside && castling.rookFromX != 0) return false;
// Check path is clear between king and rook if (hasKingOrRookMoved(isWhite, castling.isKingside)) {
return false;
}
if (!isPathClear(castling)) {
return false;
}
if (isKingInCheck(isWhite)) {
return false;
}
return !wouldKingPassThroughCheck(castling, isWhite);
}
private boolean hasKingOrRookMoved(boolean isWhite, boolean isKingside) {
List<Board> history = board.getBoardHistory();
if (history.isEmpty()) return false;
int kingRow = isWhite ? 7 : 0;
int rookX = isKingside ? 7 : 0;
for (Board previousBoard : history) {
Piece kingInHistory = previousBoard.getPieceAt(4, kingRow);
Piece rookInHistory = previousBoard.getPieceAt(rookX, kingRow);
if (kingInHistory == null || kingInHistory.getType() != PieceType.King ||
kingInHistory.isWhite() != isWhite) {
return true;
}
if (rookInHistory == null || rookInHistory.getType() != PieceType.Rook ||
rookInHistory.isWhite() != isWhite) {
return true;
}
}
Move lastMove = board.getLastMove();
if (lastMove != null) {
Piece lastMovedPiece = board.getPieceAt(lastMove.getToX(), lastMove.getToY());
if (lastMovedPiece != null) {
if (lastMovedPiece.getType() == PieceType.King && lastMovedPiece.isWhite() == isWhite) {
return true;
}
if (lastMovedPiece.getType() == PieceType.Rook && lastMovedPiece.isWhite() == isWhite) {
if ((isKingside && lastMove.getFromX() == 7) || (!isKingside && lastMove.getFromX() == 0)) {
return true;
}
}
}
}
return false;
}
private boolean isPathClear(CastlingMove castling) {
int startX = Math.min(castling.kingFromX, castling.rookFromX) + 1; int startX = Math.min(castling.kingFromX, castling.rookFromX) + 1;
int endX = Math.max(castling.kingFromX, castling.rookFromX) - 1; int endX = Math.max(castling.kingFromX, castling.rookFromX) - 1;
@ -111,49 +169,42 @@ public class CastlingHandler {
return false; return false;
} }
} }
return true;
// Check that king is not in check
if (isKingInCheck(isWhite)) {
return false;
} }
// Check that king doesn't pass through check private boolean wouldKingPassThroughCheck(CastlingMove castling, boolean isWhite) {
for (int x = castling.kingFromX; x != castling.kingToX + (castling.isKingside ? 1 : -1); int step = castling.isKingside ? 1 : -1;
x += castling.isKingside ? 1 : -1) {
for (int x = castling.kingFromX; x != castling.kingToX + step; x += step) {
if (x == castling.kingFromX) continue;
// Create temporary board with king at this position
Board tempBoard = new Board(board); Board tempBoard = new Board(board);
tempBoard.removePiece(castling.kingFromX, castling.kingFromY); tempBoard.removePiece(castling.kingFromX, castling.kingFromY);
tempBoard.setPiece(isWhite, PieceType.King, x, castling.kingFromY); tempBoard.setPiece(isWhite, PieceType.King, x, castling.kingFromY);
CastlingHandler tempHandler = new CastlingHandler(tempBoard); CastlingHandler tempHandler = new CastlingHandler(tempBoard);
if (tempHandler.isKingInCheck(isWhite)) { if (tempHandler.isKingInCheck(isWhite)) {
return false;
}
}
return true; return true;
} }
}
return false;
}
/**
* Executes the castling move on the board
*/
public void executeCastling(CastlingMove castling) { public void executeCastling(CastlingMove castling) {
if (!isCastlingValid(castling)) {
throw new IllegalArgumentException("Invalid castling move");
}
Piece king = board.getPieceAt(castling.kingFromX, castling.kingFromY); Piece king = board.getPieceAt(castling.kingFromX, castling.kingFromY);
Piece rook = board.getPieceAt(castling.rookFromX, castling.rookFromY); Piece rook = board.getPieceAt(castling.rookFromX, castling.rookFromY);
// Move the king
board.removePiece(castling.kingFromX, castling.kingFromY); 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.removePiece(castling.rookFromX, castling.rookFromY);
board.setPiece(king.isWhite(), king.getType(), castling.kingToX, castling.kingToY);
board.setPiece(rook.isWhite(), rook.getType(), castling.rookToX, castling.rookToY); board.setPiece(rook.isWhite(), rook.getType(), castling.rookToX, castling.rookToY);
} }
/**
* Gets all possible castling moves for a king
*/
public List<Position> getCastlingPositions(Piece king) { public List<Position> getCastlingPositions(Piece king) {
List<Position> castlingMoves = new ArrayList<>(); List<Position> castlingMoves = new ArrayList<>();
@ -164,18 +215,15 @@ public class CastlingHandler {
boolean isWhite = king.isWhite(); boolean isWhite = king.isWhite();
int kingRow = isWhite ? 7 : 0; int kingRow = isWhite ? 7 : 0;
// King must be on starting position
if (king.getX() != 4 || king.getY() != kingRow) { if (king.getX() != 4 || king.getY() != kingRow) {
return castlingMoves; return castlingMoves;
} }
// Check kingside castling
CastlingMove kingsideCastling = getCastlingMove(4, kingRow, 6, kingRow); CastlingMove kingsideCastling = getCastlingMove(4, kingRow, 6, kingRow);
if (isCastlingValid(kingsideCastling)) { if (isCastlingValid(kingsideCastling)) {
castlingMoves.add(new Position(6, kingRow)); castlingMoves.add(new Position(6, kingRow));
} }
// Check queenside castling
CastlingMove queensideCastling = getCastlingMove(4, kingRow, 2, kingRow); CastlingMove queensideCastling = getCastlingMove(4, kingRow, 2, kingRow);
if (isCastlingValid(queensideCastling)) { if (isCastlingValid(queensideCastling)) {
castlingMoves.add(new Position(2, kingRow)); castlingMoves.add(new Position(2, kingRow));
@ -184,8 +232,41 @@ public class CastlingHandler {
return castlingMoves; return castlingMoves;
} }
public List<Position> getAllCastlingMoves(boolean isWhite) {
List<Position> castlingMoves = new ArrayList<>();
int kingRow = isWhite ? 7 : 0;
Piece king = board.getPieceAt(4, kingRow);
if (king != null && king.getType() == PieceType.King && king.isWhite() == isWhite) {
castlingMoves.addAll(getCastlingPositions(king));
}
return castlingMoves;
}
public boolean isCastlingMove(int fromX, int fromY, int toX, int toY) {
return getCastlingMove(fromX, fromY, toX, toY) != null;
}
public boolean wouldCastlingPutKingInCheck(CastlingMove castling) {
if (castling == null) return true;
Board tempBoard = new Board(board);
CastlingHandler tempHandler = new CastlingHandler(tempBoard);
try {
Piece originalKing = board.getPieceAt(castling.kingFromX, castling.kingFromY);
if (originalKing == null) return true;
tempHandler.executeCastling(castling);
return tempHandler.isKingInCheck(originalKing.isWhite());
} catch (Exception e) {
return true;
}
}
public boolean isKingInCheck(boolean isWhiteKing) { public boolean isKingInCheck(boolean isWhiteKing) {
// Find the king's position
Piece king = null; Piece king = null;
for (Piece p : board.getPieces()) { for (Piece p : board.getPieces()) {
if (p.getType() == PieceType.King && p.isWhite() == isWhiteKing) { if (p.getType() == PieceType.King && p.isWhite() == isWhiteKing) {
@ -200,14 +281,11 @@ public class CastlingHandler {
} }
private boolean checkIfKingUnderAttack(boolean isWhiteKing, Piece king) { private boolean checkIfKingUnderAttack(boolean isWhiteKing, Piece king) {
// Check if any opponent piece can attack the king
for (Piece p : board.getPieces()) { for (Piece p : board.getPieces()) {
if (p.isWhite() == isWhiteKing) continue; // Skip pieces of same color if (p.isWhite() == isWhiteKing) continue;
// Get raw moves without check validation
List<Position> attackMoves = getValidDestinations(p); List<Position> attackMoves = getValidDestinations(p);
// If any piece can move to king's position, king is in check
for (Position pos : attackMoves) { for (Position pos : attackMoves) {
if (pos.x == king.getX() && pos.y == king.getY()) { if (pos.x == king.getX() && pos.y == king.getY()) {
return true; return true;
@ -223,7 +301,7 @@ public class CastlingHandler {
switch (piece.getType()) { switch (piece.getType()) {
case Pawn: case Pawn:
addPawnMoves(moves, piece); addPawnAttackMoves(moves, piece);
break; break;
case Rook: case Rook:
addRookMoves(moves, piece); addRookMoves(moves, piece);
@ -246,15 +324,14 @@ public class CastlingHandler {
return moves; return moves;
} }
private void addPawnMoves(List<Position> validMoves, Piece piece) { private void addPawnAttackMoves(List<Position> validMoves, Piece piece) {
int x = piece.getX(); int x = piece.getX();
int y = piece.getY(); int y = piece.getY();
boolean isWhite = piece.isWhite(); boolean isWhite = piece.isWhite();
int direction = isWhite ? -1 : 1; int direction = isWhite ? -1 : 1;
// Diagonal captures only (for attack patterns)
int newY = y + direction; int newY = y + direction;
if (newY >= 0 && newY < board.getHeight()) { if (newY >= 0 && newY < board.getHeight()) {
for (int dx = -1; dx <= 1; dx += 2) { for (int dx = -1; dx <= 1; dx += 2) {
int newX = x + dx; int newX = x + dx;
@ -283,7 +360,7 @@ public class CastlingHandler {
Piece targetPiece = board.getPieceAt(newX, newY); Piece targetPiece = board.getPieceAt(newX, newY);
if (targetPiece != null) { if (targetPiece != null) {
break; // Cannot move beyond a piece break;
} }
newX += dx; newX += dx;
@ -329,7 +406,7 @@ public class CastlingHandler {
Piece targetPiece = board.getPieceAt(newX, newY); Piece targetPiece = board.getPieceAt(newX, newY);
if (targetPiece != null) { if (targetPiece != null) {
break; // Cannot move beyond a piece break;
} }
newX += dx; newX += dx;

View File

@ -12,7 +12,9 @@ public class Move {
private Piece capturedPiece; private Piece capturedPiece;
private Board board; private Board board;
private boolean isEnPassant = false; private boolean isEnPassant = false;
private boolean isCastling = false;
private Piece enPassantCapturedPiece = null; private Piece enPassantCapturedPiece = null;
private CastlingHandler.CastlingMove castlingMove = null;
public Move(int fromX, int fromY, int toX, int toY, Board board) { public Move(int fromX, int fromY, int toX, int toY, Board board) {
this.fromX = fromX; this.fromX = fromX;
@ -23,17 +25,15 @@ public class Move {
this.movingPiece = board.getPieceAt(fromX, fromY); this.movingPiece = board.getPieceAt(fromX, fromY);
this.capturedPiece = board.getPieceAt(toX, toY); this.capturedPiece = board.getPieceAt(toX, toY);
// Check if this is an en passant move
checkEnPassant(); checkEnPassant();
checkCastling();
} }
private void checkEnPassant() { private void checkEnPassant() {
if (movingPiece != null && movingPiece.getType() == PieceType.Pawn) { if (movingPiece != null && movingPiece.getType() == PieceType.Pawn) {
// Utiliser la classe Enpassant pour vérifier
Enpassant enpassantHandler = board.getEnpassantHandler(); Enpassant enpassantHandler = board.getEnpassantHandler();
if (enpassantHandler.isEnPassantValid(fromX, fromY, toX, toY)) { if (enpassantHandler.isEnPassantValid(fromX, fromY, toX, toY)) {
isEnPassant = true; isEnPassant = true;
// Obtenir la position du pion capturé
Enpassant.Position capturedPos = enpassantHandler.getCapturedPawnPosition(toX, toY); Enpassant.Position capturedPos = enpassantHandler.getCapturedPawnPosition(toX, toY);
if (capturedPos != null) { if (capturedPos != null) {
enPassantCapturedPiece = board.getPieceAt(capturedPos.x, capturedPos.y); enPassantCapturedPiece = board.getPieceAt(capturedPos.x, capturedPos.y);
@ -42,102 +42,118 @@ public class Move {
} }
} }
private void checkCastling() {
if (movingPiece != null && movingPiece.getType() == PieceType.King) {
CastlingHandler castlingHandler = board.getCastlingHandler();
castlingMove = castlingHandler.getCastlingMove(fromX, fromY, toX, toY);
if (castlingMove != null && castlingHandler.isCastlingValid(castlingMove)) {
isCastling = true;
}
}
}
public boolean isValid() { public boolean isValid() {
// Check if the moving piece exists
if (movingPiece == null) { if (movingPiece == null) {
return false; return false;
} }
// Check if the move is in the list of valid moves for this piece if (isCastling) {
CastlingHandler castlingHandler = board.getCastlingHandler();
return castlingHandler.isCastlingValid(castlingMove);
}
List<Position> validMoves = getValidDestinations(movingPiece, board); List<Position> validMoves = getValidDestinations(movingPiece, board);
return validMoves.contains(new Position(toX, toY)); return validMoves.contains(new Position(toX, toY));
} }
public void execute() { public void execute() {
if (isEnPassant) { if (isCastling) {
// Utiliser la classe Enpassant pour l'exécution CastlingHandler castlingHandler = board.getCastlingHandler();
castlingHandler.executeCastling(castlingMove);
} else if (isEnPassant) {
Enpassant enpassantHandler = board.getEnpassantHandler(); Enpassant enpassantHandler = board.getEnpassantHandler();
enpassantHandler.executeEnPassant(fromX, fromY, toX, toY); enpassantHandler.executeEnPassant(fromX, fromY, toX, toY);
} else { } else {
// Normal move or capture
if (capturedPiece != null) { if (capturedPiece != null) {
board.removePiece(toX, toY); board.removePiece(toX, toY);
} }
// Move the piece
board.removePiece(fromX, fromY); board.removePiece(fromX, fromY);
board.setPiece(movingPiece.isWhite(), movingPiece.getType(), toX, toY); board.setPiece(movingPiece.isWhite(), movingPiece.getType(), toX, toY);
} }
// Advance turn
board.advanceTurn(); board.advanceTurn();
} }
public boolean putsOwnKingInCheck() { public boolean putsOwnKingInCheck() {
// Create a temporary board to simulate the move
Board tempBoard = new Board(board); Board tempBoard = new Board(board);
// Find the piece in the temp board
Piece tempPiece = tempBoard.getPieceAt(fromX, fromY); Piece tempPiece = tempBoard.getPieceAt(fromX, fromY);
if (tempPiece == null) return true; // Safety check if (tempPiece == null) return true;
if (isEnPassant) { if (isCastling) {
// Simulate en passant on temp board CastlingHandler tempCastlingHandler = tempBoard.getCastlingHandler();
CastlingHandler.CastlingMove tempCastlingMove = tempCastlingHandler.getCastlingMove(fromX, fromY, toX, toY);
if (tempCastlingMove != null) {
return tempCastlingHandler.wouldCastlingPutKingInCheck(tempCastlingMove);
}
return true;
} else if (isEnPassant) {
Enpassant tempEnpassantHandler = tempBoard.getEnpassantHandler(); Enpassant tempEnpassantHandler = tempBoard.getEnpassantHandler();
tempEnpassantHandler.executeEnPassant(fromX, fromY, toX, toY); tempEnpassantHandler.executeEnPassant(fromX, fromY, toX, toY);
} else { } else {
// Normal move simulation
tempBoard.removePiece(toX, toY); tempBoard.removePiece(toX, toY);
tempBoard.removePiece(fromX, fromY); tempBoard.removePiece(fromX, fromY);
tempBoard.setPiece(tempPiece.isWhite(), tempPiece.getType(), toX, toY); tempBoard.setPiece(tempPiece.isWhite(), tempPiece.getType(), toX, toY);
} }
// Check if king is in check after move
return isKingInCheck(tempBoard, tempPiece.isWhite()); return isKingInCheck(tempBoard, tempPiece.isWhite());
} }
public boolean putsOpponentInCheck() { public boolean putsOpponentInCheck() {
// Create a temporary board to simulate the move
Board tempBoard = new Board(board); Board tempBoard = new Board(board);
// Find the piece in the temp board
Piece tempPiece = tempBoard.getPieceAt(fromX, fromY); Piece tempPiece = tempBoard.getPieceAt(fromX, fromY);
if (tempPiece == null) return false; // Safety check if (tempPiece == null) return false;
if (isEnPassant) { if (isCastling) {
// Simulate en passant on temp board CastlingHandler tempCastlingHandler = tempBoard.getCastlingHandler();
CastlingHandler.CastlingMove tempCastlingMove = tempCastlingHandler.getCastlingMove(fromX, fromY, toX, toY);
if (tempCastlingMove != null) {
tempCastlingHandler.executeCastling(tempCastlingMove);
}
} else if (isEnPassant) {
Enpassant tempEnpassantHandler = tempBoard.getEnpassantHandler(); Enpassant tempEnpassantHandler = tempBoard.getEnpassantHandler();
tempEnpassantHandler.executeEnPassant(fromX, fromY, toX, toY); tempEnpassantHandler.executeEnPassant(fromX, fromY, toX, toY);
} else { } else {
// Normal move simulation
tempBoard.removePiece(toX, toY); tempBoard.removePiece(toX, toY);
tempBoard.removePiece(fromX, fromY); tempBoard.removePiece(fromX, fromY);
tempBoard.setPiece(tempPiece.isWhite(), tempPiece.getType(), toX, toY); tempBoard.setPiece(tempPiece.isWhite(), tempPiece.getType(), toX, toY);
} }
// Check if opponent's king is in check after move
return isKingInCheck(tempBoard, !tempPiece.isWhite()); return isKingInCheck(tempBoard, !tempPiece.isWhite());
} }
public boolean putsOpponentInCheckmate() { public boolean putsOpponentInCheckmate() {
// First, check if the move puts the opponent in check
if (!putsOpponentInCheck()) { if (!putsOpponentInCheck()) {
return false; return false;
} }
// Create a temporary board to simulate the move
Board tempBoard = new Board(board); Board tempBoard = new Board(board);
// Find the piece in the temp board
Piece tempPiece = tempBoard.getPieceAt(fromX, fromY); Piece tempPiece = tempBoard.getPieceAt(fromX, fromY);
if (tempPiece == null) return false; // Safety check if (tempPiece == null) return false;
if (isEnPassant) { if (isCastling) {
// Simulate en passant on temp board CastlingHandler tempCastlingHandler = tempBoard.getCastlingHandler();
CastlingHandler.CastlingMove tempCastlingMove = tempCastlingHandler.getCastlingMove(fromX, fromY, toX, toY);
if (tempCastlingMove != null) {
tempCastlingHandler.executeCastling(tempCastlingMove);
}
} else if (isEnPassant) {
Enpassant tempEnpassantHandler = tempBoard.getEnpassantHandler(); Enpassant tempEnpassantHandler = tempBoard.getEnpassantHandler();
tempEnpassantHandler.executeEnPassant(fromX, fromY, toX, toY); tempEnpassantHandler.executeEnPassant(fromX, fromY, toX, toY);
} else { } else {
// Normal move simulation
tempBoard.removePiece(toX, toY); tempBoard.removePiece(toX, toY);
tempBoard.removePiece(fromX, fromY); tempBoard.removePiece(fromX, fromY);
tempBoard.setPiece(tempPiece.isWhite(), tempPiece.getType(), toX, toY); tempBoard.setPiece(tempPiece.isWhite(), tempPiece.getType(), toX, toY);
@ -145,23 +161,19 @@ public class Move {
boolean opponentColor = !tempPiece.isWhite(); boolean opponentColor = !tempPiece.isWhite();
// Try all possible moves for all opponent pieces
for (Piece p : tempBoard.getPieces()) { for (Piece p : tempBoard.getPieces()) {
if (p.isWhite() != opponentColor) continue; // Skip pieces of the wrong color if (p.isWhite() != opponentColor) continue;
List<Position> possibleMoves = getValidDestinations(p, tempBoard); List<Position> possibleMoves = getValidDestinations(p, tempBoard);
for (Position pos : possibleMoves) { for (Position pos : possibleMoves) {
// Create a temporary move
Move testMove = new Move(p.getX(), p.getY(), pos.x, pos.y, tempBoard); Move testMove = new Move(p.getX(), p.getY(), pos.x, pos.y, tempBoard);
// Check if this move would get the opponent out of check
if (!testMove.putsOwnKingInCheck()) { if (!testMove.putsOwnKingInCheck()) {
return false; // Opponent has at least one valid move return false;
} }
} }
} }
// If we get here, opponent has no valid moves
return true; return true;
} }
@ -187,6 +199,7 @@ public class Move {
return moves; return moves;
case King: case King:
addKingMoves(moves, piece, board); addKingMoves(moves, piece, board);
addCastlingMoves(moves, piece, board);
return moves; return moves;
} }
@ -194,10 +207,8 @@ public class Move {
} }
public List<Position> getValidMoves(Piece piece, Board board) { public List<Position> getValidMoves(Piece piece, Board board) {
// Get all possible moves without considering check
List<Position> candidateMoves = getValidDestinations(piece, board); List<Position> candidateMoves = getValidDestinations(piece, board);
// Filter out moves that would leave king in check
List<Position> legalMoves = new ArrayList<>(); List<Position> legalMoves = new ArrayList<>();
for (Position pos : candidateMoves) { for (Position pos : candidateMoves) {
Move move = new Move(piece.getX(), piece.getY(), pos.x, pos.y, board); Move move = new Move(piece.getX(), piece.getY(), pos.x, pos.y, board);
@ -210,7 +221,6 @@ public class Move {
} }
public boolean isKingInCheck(Board board, boolean isWhiteKing) { public boolean isKingInCheck(Board board, boolean isWhiteKing) {
// Find the king's position
Piece king = null; Piece king = null;
for (Piece p : board.getPieces()) { for (Piece p : board.getPieces()) {
if (p.getType() == PieceType.King && p.isWhite() == isWhiteKing) { if (p.getType() == PieceType.King && p.isWhite() == isWhiteKing) {
@ -223,14 +233,11 @@ public class Move {
} }
private boolean checkIfKingUnderAttack(Board board, boolean isWhiteKing, Piece king) { private boolean checkIfKingUnderAttack(Board board, boolean isWhiteKing, Piece king) {
// Check if any opponent piece can attack the king
for (Piece p : board.getPieces()) { for (Piece p : board.getPieces()) {
if (p.isWhite() == isWhiteKing) continue; // Skip pieces of same color if (p.isWhite() == isWhiteKing) continue;
// Get raw moves without check validation
List<Position> attackMoves = getValidDestinations(p, board); List<Position> attackMoves = getValidDestinations(p, board);
// If any piece can move to king's position, king is in check
if (attackMoves.contains(new Position(king.getX(), king.getY()))) { if (attackMoves.contains(new Position(king.getX(), king.getY()))) {
return true; return true;
} }
@ -239,21 +246,31 @@ public class Move {
return false; return false;
} }
private void addCastlingMoves(List<Position> validMoves, Piece piece, Board board) {
if (piece.getType() != PieceType.King) {
return;
}
CastlingHandler castlingHandler = board.getCastlingHandler();
List<CastlingHandler.Position> castlingPositions = castlingHandler.getCastlingPositions(piece);
for (CastlingHandler.Position castlingPos : castlingPositions) {
validMoves.add(new Position(castlingPos.x, castlingPos.y));
}
}
private void addPawnMoves(List<Position> validMoves, Piece piece, Board board) { private void addPawnMoves(List<Position> validMoves, Piece piece, Board board) {
int x = piece.getX(); int x = piece.getX();
int y = piece.getY(); int y = piece.getY();
boolean isWhite = piece.isWhite(); boolean isWhite = piece.isWhite();
int direction = isWhite ? -1 : 1; // White pawns move up, black pawns move down int direction = isWhite ? -1 : 1;
// Forward movement
int newY = y + direction; int newY = y + direction;
if (newY >= 0 && newY < board.getHeight()) { if (newY >= 0 && newY < board.getHeight()) {
// Single square forward
if (board.getPieceAt(x, newY) == null) { if (board.getPieceAt(x, newY) == null) {
validMoves.add(new Position(x, newY)); validMoves.add(new Position(x, newY));
// Initial double move
int startRow = isWhite ? 6 : 1; int startRow = isWhite ? 6 : 1;
if (y == startRow) { if (y == startRow) {
int doubleY = newY + direction; int doubleY = newY + direction;
@ -263,7 +280,6 @@ public class Move {
} }
} }
// Diagonal captures (normal)
for (int dx = -1; dx <= 1; dx += 2) { for (int dx = -1; dx <= 1; dx += 2) {
int newX = x + dx; int newX = x + dx;
if (newX >= 0 && newX < board.getWidth()) { if (newX >= 0 && newX < board.getWidth()) {
@ -275,7 +291,6 @@ public class Move {
} }
} }
// EN PASSANT: Ajouter les mouvements en passant en utilisant la classe Enpassant
Enpassant enpassantHandler = board.getEnpassantHandler(); Enpassant enpassantHandler = board.getEnpassantHandler();
List<Enpassant.Position> enPassantMoves = enpassantHandler.getPossibleEnPassantMoves(x, y); List<Enpassant.Position> enPassantMoves = enpassantHandler.getPossibleEnPassantMoves(x, y);
for (Enpassant.Position enPos : enPassantMoves) { for (Enpassant.Position enPos : enPassantMoves) {
@ -288,7 +303,6 @@ public class Move {
int y = piece.getY(); int y = piece.getY();
boolean isWhite = piece.isWhite(); boolean isWhite = piece.isWhite();
// Directions: horizontal and vertical
int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
for (int[] dir : directions) { for (int[] dir : directions) {
@ -303,15 +317,12 @@ public class Move {
Piece targetPiece = board.getPieceAt(newX, newY); Piece targetPiece = board.getPieceAt(newX, newY);
if (targetPiece == null) { if (targetPiece == null) {
// Empty square
validMoves.add(new Position(newX, newY)); validMoves.add(new Position(newX, newY));
} else { } else {
// Occupied square
if (targetPiece.isWhite() != isWhite) { if (targetPiece.isWhite() != isWhite) {
// Capture opponent's piece
validMoves.add(new Position(newX, newY)); validMoves.add(new Position(newX, newY));
} }
continueInDirection = false; // Cannot move beyond a piece continueInDirection = false;
} }
if (continueInDirection) { if (continueInDirection) {
@ -327,7 +338,6 @@ public class Move {
int y = piece.getY(); int y = piece.getY();
boolean isWhite = piece.isWhite(); boolean isWhite = piece.isWhite();
// All possible knight moves: L-shapes
int[][] knightMoves = { int[][] knightMoves = {
{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2}, {-2, -1}, {-2, 1}, {-1, -2}, {-1, 2},
{1, -2}, {1, 2}, {2, -1}, {2, 1} {1, -2}, {1, 2}, {2, -1}, {2, 1}
@ -341,7 +351,6 @@ public class Move {
Piece targetPiece = board.getPieceAt(newX, newY); Piece targetPiece = board.getPieceAt(newX, newY);
if (targetPiece == null || targetPiece.isWhite() != isWhite) { if (targetPiece == null || targetPiece.isWhite() != isWhite) {
// Empty square or can capture opponent's piece
validMoves.add(new Position(newX, newY)); validMoves.add(new Position(newX, newY));
} }
} }
@ -353,7 +362,6 @@ public class Move {
int y = piece.getY(); int y = piece.getY();
boolean isWhite = piece.isWhite(); boolean isWhite = piece.isWhite();
// Directions: diagonals
int[][] directions = {{1, 1}, {1, -1}, {-1, 1}, {-1, -1}}; int[][] directions = {{1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
for (int[] dir : directions) { for (int[] dir : directions) {
@ -368,15 +376,12 @@ public class Move {
Piece targetPiece = board.getPieceAt(newX, newY); Piece targetPiece = board.getPieceAt(newX, newY);
if (targetPiece == null) { if (targetPiece == null) {
// Empty square
validMoves.add(new Position(newX, newY)); validMoves.add(new Position(newX, newY));
} else { } else {
// Occupied square
if (targetPiece.isWhite() != isWhite) { if (targetPiece.isWhite() != isWhite) {
// Capture opponent's piece
validMoves.add(new Position(newX, newY)); validMoves.add(new Position(newX, newY));
} }
continueInDirection = false; // Cannot move beyond a piece continueInDirection = false;
} }
if (continueInDirection) { if (continueInDirection) {
@ -392,10 +397,9 @@ public class Move {
int y = piece.getY(); int y = piece.getY();
boolean isWhite = piece.isWhite(); boolean isWhite = piece.isWhite();
// All adjacent squares
for (int dx = -1; dx <= 1; dx++) { for (int dx = -1; dx <= 1; dx++) {
for (int dy = -1; dy <= 1; dy++) { for (int dy = -1; dy <= 1; dy++) {
if (dx == 0 && dy == 0) continue; // Skip the current position if (dx == 0 && dy == 0) continue;
int newX = x + dx; int newX = x + dx;
int newY = y + dy; int newY = y + dy;
@ -404,7 +408,6 @@ public class Move {
Piece targetPiece = board.getPieceAt(newX, newY); Piece targetPiece = board.getPieceAt(newX, newY);
if (targetPiece == null || targetPiece.isWhite() != isWhite) { if (targetPiece == null || targetPiece.isWhite() != isWhite) {
// Empty square or can capture opponent's piece
validMoves.add(new Position(newX, newY)); validMoves.add(new Position(newX, newY));
} }
} }
@ -421,7 +424,6 @@ public class Move {
this.y = y; this.y = y;
} }
@Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false; if (obj == null || getClass() != obj.getClass()) return false;
@ -429,19 +431,19 @@ public class Move {
return x == position.x && y == position.y; return x == position.x && y == position.y;
} }
@Override
public int hashCode() { public int hashCode() {
return 31 * x + y; return 31 * x + y;
} }
} }
// Getters
public int getFromX() { return fromX; } public int getFromX() { return fromX; }
public int getFromY() { return fromY; } public int getFromY() { return fromY; }
public int getToX() { return toX; } public int getToX() { return toX; }
public int getToY() { return toY; } public int getToY() { return toY; }
public boolean isEnPassant() { return isEnPassant; } public boolean isEnPassant() { return isEnPassant; }
public boolean isCastling() { return isCastling; }
public Piece getMovingPiece() { return movingPiece; } public Piece getMovingPiece() { return movingPiece; }
public Piece getCapturedPiece() { return capturedPiece; } public Piece getCapturedPiece() { return capturedPiece; }
public Piece getEnPassantCapturedPiece() { return enPassantCapturedPiece; } public Piece getEnPassantCapturedPiece() { return enPassantCapturedPiece; }
public CastlingHandler.CastlingMove getCastlingMove() { return castlingMove; }
} }