en-passant
This commit is contained in:
parent
0b0ea138a6
commit
5dd5ac50ee
Binary file not shown.
Binary file not shown.
|
|
@ -20,6 +20,11 @@ public class Board {
|
|||
// Add Sound instance
|
||||
private Sound sound;
|
||||
|
||||
// En passant tracking
|
||||
private Integer enPassantX = null; // File where en passant capture is possible
|
||||
private Integer enPassantY = null; // Rank where the pawn that can be captured is located
|
||||
private int enPassantTurn = -1; // Turn number when en passant became possible
|
||||
|
||||
public Board(int colNum, int lineNum) {
|
||||
this.width = colNum;
|
||||
this.height = lineNum;
|
||||
|
|
@ -113,6 +118,7 @@ public class Board {
|
|||
|
||||
public void cleanBoard() {
|
||||
pieces.clear();
|
||||
clearEnPassant();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
|
@ -228,7 +234,13 @@ public class Board {
|
|||
fileRep[y] = line;
|
||||
}
|
||||
|
||||
fileRep[height] = (isWhiteTurn ? "W" : "B") + "," + turnNumber;
|
||||
// Include en passant information in the file representation
|
||||
String enPassantInfo = "";
|
||||
if (enPassantX != null && enPassantY != null) {
|
||||
enPassantInfo = "," + enPassantX + "," + enPassantY + "," + enPassantTurn;
|
||||
}
|
||||
|
||||
fileRep[height] = (isWhiteTurn ? "W" : "B") + "," + turnNumber + enPassantInfo;
|
||||
|
||||
return fileRep;
|
||||
}
|
||||
|
|
@ -282,9 +294,23 @@ public class Board {
|
|||
} else {
|
||||
this.turnNumber = 0;
|
||||
}
|
||||
|
||||
// Parse en passant information
|
||||
if (turnData.length >= 5) {
|
||||
try {
|
||||
this.enPassantX = Integer.parseInt(turnData[2].trim());
|
||||
this.enPassantY = Integer.parseInt(turnData[3].trim());
|
||||
this.enPassantTurn = Integer.parseInt(turnData[4].trim());
|
||||
} catch (NumberFormatException e) {
|
||||
clearEnPassant();
|
||||
}
|
||||
} else {
|
||||
clearEnPassant();
|
||||
}
|
||||
} else {
|
||||
this.turnNumber = 0;
|
||||
this.isWhiteTurn = true;
|
||||
clearEnPassant();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -317,6 +343,11 @@ public class Board {
|
|||
this.highlightedPositions = new ArrayList<>();
|
||||
this.highlightedPositions.addAll(board.highlightedPositions);
|
||||
|
||||
// Copy en passant state
|
||||
this.enPassantX = board.enPassantX;
|
||||
this.enPassantY = board.enPassantY;
|
||||
this.enPassantTurn = board.enPassantTurn;
|
||||
|
||||
// Initialize board history for copy constructor
|
||||
this.boardHistory = new ArrayList<>();
|
||||
|
||||
|
|
@ -372,12 +403,15 @@ public class Board {
|
|||
// Remove it from history
|
||||
boardHistory.remove(boardHistory.size() - 1);
|
||||
|
||||
// Use existing methods to restore state
|
||||
this.width = previousBoard.width;
|
||||
this.height = previousBoard.height;
|
||||
this.turnNumber = previousBoard.turnNumber;
|
||||
this.isWhiteTurn = previousBoard.isWhiteTurn;
|
||||
|
||||
this.enPassantX = previousBoard.enPassantX;
|
||||
this.enPassantY = previousBoard.enPassantY;
|
||||
this.enPassantTurn = previousBoard.enPassantTurn;
|
||||
|
||||
// Use existing getPieces() method to restore pieces
|
||||
this.pieces.clear();
|
||||
for (Piece p : previousBoard.getPieces()) {
|
||||
|
|
@ -395,10 +429,58 @@ public class Board {
|
|||
return !boardHistory.isEmpty();
|
||||
}
|
||||
|
||||
// Add cleanup method to properly dispose of sound resources
|
||||
public void cleanup() {
|
||||
if (sound != null) {
|
||||
sound.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
public void setEnPassant(int x, int y) {
|
||||
this.enPassantX = x;
|
||||
this.enPassantY = y;
|
||||
this.enPassantTurn = this.turnNumber;
|
||||
}
|
||||
|
||||
|
||||
public void clearEnPassant() {
|
||||
this.enPassantX = null;
|
||||
this.enPassantY = null;
|
||||
this.enPassantTurn = -1;
|
||||
}
|
||||
|
||||
public boolean canCaptureEnPassant(int x, int y) {
|
||||
// En passant is only valid for one turn after the double pawn move
|
||||
if (enPassantX == null || enPassantY == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if this is the immediate next turn
|
||||
if (turnNumber != enPassantTurn + 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the position matches
|
||||
return enPassantX == x && enPassantY == y;
|
||||
}
|
||||
|
||||
public void handlePawnDoubleMove(int fromX, int fromY, int toX, int toY) {
|
||||
Piece pawn = getPieceAt(toX, toY);
|
||||
if (pawn != null && pawn.getType() == PieceType.Pawn) {
|
||||
if (Math.abs(toY - fromY) == 2) {
|
||||
setEnPassant(toX, toY);
|
||||
} else {
|
||||
clearEnPassant();
|
||||
}
|
||||
} else {
|
||||
clearEnPassant();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Enpassant.Position getEnPassantTarget() {
|
||||
if (enPassantX != null && enPassantY != null && canCaptureEnPassant(enPassantX, enPassantY)) {
|
||||
return new Enpassant.Position(enPassantX, enPassantY);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,72 @@
|
|||
package backend;
|
||||
|
||||
public class Enpassant {
|
||||
private Board board;
|
||||
|
||||
public Enpassant(Board board) {
|
||||
this.board = board;
|
||||
}
|
||||
|
||||
}
|
||||
public boolean isEnPassantValid(int fromX, int fromY, int toX, int toY) {
|
||||
Piece movingPiece = board.getPieceAt(fromX, fromY);
|
||||
|
||||
if (movingPiece == null || movingPiece.getType() != PieceType.Pawn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Must be a diagonal move
|
||||
if (Math.abs(toX - fromX) != 1 || Math.abs(toY - fromY) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (board.getPieceAt(toX, toY) != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Piece targetPawn = board.getPieceAt(toX, fromY); // Same rank as moving pawn
|
||||
if (targetPawn == null || targetPawn.getType() != PieceType.Pawn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Target pawn must be opposite color
|
||||
if (targetPawn.isWhite() == movingPiece.isWhite()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return board.canCaptureEnPassant(toX, fromY);
|
||||
}
|
||||
|
||||
|
||||
public void executeEnPassant(int fromX, int fromY, int toX, int toY) {
|
||||
Piece movingPawn = board.getPieceAt(fromX, fromY);
|
||||
|
||||
board.removePiece(toX, fromY);
|
||||
board.removePiece(fromX, fromY);
|
||||
board.setPiece(movingPawn.isWhite(), movingPawn.getType(), toX, toY);
|
||||
}
|
||||
|
||||
public Position getCapturedPawnPosition(int toX, int toY) {
|
||||
Piece targetPawn = board.getPieceAt(toX, toY - (board.isTurnWhite() ? -1 : 1));
|
||||
if (targetPawn != null && targetPawn.getType() == PieceType.Pawn) {
|
||||
return new Position(toX, toY - (board.isTurnWhite() ? -1 : 1));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,10 @@ public class Move {
|
|||
private CastlingHandler.CastlingMove castlingMove;
|
||||
private boolean isCastling;
|
||||
|
||||
// En passant-related fields
|
||||
private Enpassant enpassantHandler;
|
||||
private boolean isEnPassant;
|
||||
|
||||
public Move(int fromX, int fromY, int toX, int toY, Board board) {
|
||||
this.fromX = fromX;
|
||||
this.fromY = fromY;
|
||||
|
|
@ -30,6 +34,10 @@ public class Move {
|
|||
this.castlingHandler = new CastlingHandler(board);
|
||||
this.castlingMove = castlingHandler.getCastlingMove(fromX, fromY, toX, toY);
|
||||
this.isCastling = (castlingMove != null);
|
||||
|
||||
// Initialize en passant handler and check if this is an en passant move
|
||||
this.enpassantHandler = new Enpassant(board);
|
||||
this.isEnPassant = enpassantHandler.isEnPassantValid(fromX, fromY, toX, toY);
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
|
|
@ -43,6 +51,11 @@ public class Move {
|
|||
return castlingHandler.isCastlingValid(castlingMove);
|
||||
}
|
||||
|
||||
// Handle en passant validation
|
||||
if (isEnPassant) {
|
||||
return enpassantHandler.isEnPassantValid(fromX, fromY, toX, toY);
|
||||
}
|
||||
|
||||
// Check if the move is in the list of valid moves for this piece
|
||||
List<Position> validMoves = getValidDestinations(movingPiece, board);
|
||||
return containsPosition(validMoves, new Position(toX, toY));
|
||||
|
|
@ -52,6 +65,9 @@ public class Move {
|
|||
if (isCastling) {
|
||||
// Execute castling move
|
||||
castlingHandler.executeCastling(castlingMove);
|
||||
} else if (isEnPassant) {
|
||||
// Execute en passant capture
|
||||
enpassantHandler.executeEnPassant(fromX, fromY, toX, toY);
|
||||
} else {
|
||||
// Remove any piece at the destination (normal capture)
|
||||
if (capturedPiece != null) {
|
||||
|
|
@ -63,6 +79,14 @@ public class Move {
|
|||
board.setPiece(movingPiece.isWhite(), movingPiece.getType(), toX, toY);
|
||||
}
|
||||
|
||||
// Handle en passant state updates for pawn moves
|
||||
if (movingPiece.getType() == PieceType.Pawn && !isEnPassant) {
|
||||
board.handlePawnDoubleMove(fromX, fromY, toX, toY);
|
||||
} else {
|
||||
// Clear en passant for non-pawn moves
|
||||
board.clearEnPassant();
|
||||
}
|
||||
|
||||
// Advance turn
|
||||
board.advanceTurn();
|
||||
}
|
||||
|
|
@ -82,6 +106,10 @@ public class Move {
|
|||
if (tempCastling != null) {
|
||||
tempHandler.executeCastling(tempCastling);
|
||||
}
|
||||
} else if (isEnPassant) {
|
||||
// For en passant, execute the en passant capture
|
||||
Enpassant tempEnpassant = new Enpassant(tempBoard);
|
||||
tempEnpassant.executeEnPassant(fromX, fromY, toX, toY);
|
||||
} else {
|
||||
// Remove any piece at destination (normal capture)
|
||||
tempBoard.removePiece(toX, toY);
|
||||
|
|
@ -111,6 +139,10 @@ public class Move {
|
|||
if (tempCastling != null) {
|
||||
tempHandler.executeCastling(tempCastling);
|
||||
}
|
||||
} else if (isEnPassant) {
|
||||
// For en passant, execute the en passant capture
|
||||
Enpassant tempEnpassant = new Enpassant(tempBoard);
|
||||
tempEnpassant.executeEnPassant(fromX, fromY, toX, toY);
|
||||
} else {
|
||||
// Remove any piece at destination (normal capture)
|
||||
tempBoard.removePiece(toX, toY);
|
||||
|
|
@ -145,6 +177,10 @@ public class Move {
|
|||
if (tempCastling != null) {
|
||||
tempHandler.executeCastling(tempCastling);
|
||||
}
|
||||
} else if (isEnPassant) {
|
||||
// For en passant, execute the en passant capture
|
||||
Enpassant tempEnpassant = new Enpassant(tempBoard);
|
||||
tempEnpassant.executeEnPassant(fromX, fromY, toX, toY);
|
||||
} else {
|
||||
// Remove any piece at destination (normal capture)
|
||||
tempBoard.removePiece(toX, toY);
|
||||
|
|
@ -230,7 +266,7 @@ public class Move {
|
|||
int y = piece.getY();
|
||||
boolean isWhite = piece.isWhite();
|
||||
|
||||
int direction = isWhite ? -1 : 1; // White pawns move up, black pawns move down
|
||||
int direction = isWhite ? -1 : 1; // White pawns move up (decreasing y), black pawns move down (increasing y)
|
||||
|
||||
// Forward movement
|
||||
int newY = y + direction;
|
||||
|
|
@ -249,7 +285,7 @@ public class Move {
|
|||
}
|
||||
}
|
||||
|
||||
// Diagonal captures
|
||||
// Diagonal captures (regular captures)
|
||||
for (int dx = -1; dx <= 1; dx += 2) {
|
||||
int newX = x + dx;
|
||||
if (newX >= 0 && newX < board.getWidth()) {
|
||||
|
|
@ -260,6 +296,29 @@ public class Move {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// En passant captures
|
||||
// Check if there's an opponent pawn adjacent to this pawn that can be captured via en passant
|
||||
for (int dx = -1; dx <= 1; dx += 2) { // Check left and right
|
||||
int adjacentX = x + dx;
|
||||
if (adjacentX >= 0 && adjacentX < board.getWidth()) {
|
||||
// Check if there's an opponent pawn at the same rank
|
||||
Piece adjacentPiece = board.getPieceAt(adjacentX, y);
|
||||
if (adjacentPiece != null &&
|
||||
adjacentPiece.getType() == PieceType.Pawn &&
|
||||
adjacentPiece.isWhite() != isWhite) {
|
||||
|
||||
// Check if this pawn can be captured via en passant
|
||||
if (board.canCaptureEnPassant(adjacentX, y)) {
|
||||
// The capture square is diagonally forward from the capturing pawn
|
||||
int captureY = y + direction;
|
||||
if (captureY >= 0 && captureY < board.getHeight()) {
|
||||
validMoves.add(new Position(adjacentX, captureY));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addRookMoves(List<Position> validMoves, Piece piece, Board board) {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ public class Sound {
|
|||
|
||||
public void playMoveSound() {
|
||||
if (moveSound != null) {
|
||||
// Stop the clip if it's already playing
|
||||
if (moveSound.isRunning()) {
|
||||
moveSound.stop();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue