ai trial
This commit is contained in:
parent
5dd5ac50ee
commit
5f02aeed3e
|
|
@ -1,2 +1 @@
|
|||
/backend/
|
||||
/windowInterface/
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,17 +1,99 @@
|
|||
package backend;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AutoPlayer {
|
||||
|
||||
|
||||
/**
|
||||
* returns the best Move to try on provided board for active player
|
||||
* @param board
|
||||
* @return
|
||||
*/
|
||||
public Move computeBestMove(Board board) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static final int MAX_DEPTH = 2;
|
||||
|
||||
public Move computeBestMove(Board board) {
|
||||
List<Move> legalMoves = getAllLegalMoves(board);
|
||||
if (legalMoves.isEmpty()) return null;
|
||||
|
||||
int bestScore = Integer.MIN_VALUE;
|
||||
Move bestMove = null;
|
||||
|
||||
for (Move move : legalMoves) {
|
||||
Board tempBoard = new Board(board);
|
||||
Move simulated = new Move(move.getFromX(), move.getFromY(), move.getToX(), move.getToY(), tempBoard);
|
||||
tempBoard.playMove(simulated);
|
||||
|
||||
int score = -negamax(tempBoard, MAX_DEPTH - 1, !board.isTurnWhite());
|
||||
if (score > bestScore) {
|
||||
bestScore = score;
|
||||
bestMove = move;
|
||||
}
|
||||
}
|
||||
|
||||
return bestMove;
|
||||
}
|
||||
|
||||
private int negamax(Board board, int depth, boolean isWhite) {
|
||||
if (depth == 0) {
|
||||
return evaluate(board, isWhite);
|
||||
}
|
||||
|
||||
int max = Integer.MIN_VALUE;
|
||||
for (Move move : getAllLegalMoves(board)) {
|
||||
Board tempBoard = new Board(board);
|
||||
Move simulated = new Move(move.getFromX(), move.getFromY(), move.getToX(), move.getToY(), tempBoard);
|
||||
tempBoard.playMove(simulated);
|
||||
int score = -negamax(tempBoard, depth - 1, !isWhite);
|
||||
max = Math.max(max, score);
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
private int evaluate(Board board, boolean isWhite) {
|
||||
int score = 0;
|
||||
|
||||
for (Piece p : board.getPieces()) {
|
||||
int value = switch (p.getType()) {
|
||||
case Pawn -> 1;
|
||||
case Knight, Bishop -> 3;
|
||||
case Rook -> 5;
|
||||
case Queen -> 9;
|
||||
case King -> 100;
|
||||
};
|
||||
|
||||
int developmentBonus = 0;
|
||||
|
||||
// Encourage developing minor pieces
|
||||
if (p.getType() != PieceType.Pawn && p.getType() != PieceType.King) {
|
||||
if ((p.isWhite() && p.getY() < 6) || (!p.isWhite() && p.getY() > 1)) {
|
||||
developmentBonus += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Encourage center control
|
||||
if (p.getX() >= 2 && p.getX() <= 5 && p.getY() >= 2 && p.getY() <= 5) {
|
||||
developmentBonus += 1;
|
||||
}
|
||||
|
||||
int pieceScore = value + developmentBonus;
|
||||
score += (p.isWhite() == isWhite ? pieceScore : -pieceScore);
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
private List<Move> getAllLegalMoves(Board board) {
|
||||
List<Move> legalMoves = new ArrayList<>();
|
||||
boolean isWhite = board.isTurnWhite();
|
||||
|
||||
for (Piece piece : board.getPieces()) {
|
||||
if (piece.isWhite() == isWhite) {
|
||||
List<Move.Position> validMoves = new Move(0, 0, 0, 0, board).getValidMoves(piece, board);
|
||||
for (Move.Position pos : validMoves) {
|
||||
Move move = new Move(piece.getX(), piece.getY(), pos.x, pos.y, board);
|
||||
if (move.isValid() && !move.putsOwnKingInCheck()) {
|
||||
legalMoves.add(move);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return legalMoves;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,11 +20,6 @@ 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;
|
||||
|
|
@ -47,6 +42,15 @@ public class Board {
|
|||
public int getTurnNumber() {
|
||||
return turnNumber;
|
||||
}
|
||||
public void playMove(Move move) {
|
||||
if (move != null && move.isValid() && !move.putsOwnKingInCheck()) {
|
||||
move.execute();
|
||||
System.out.println("AI plays: " + move.getFromX() + "," + move.getFromY() + " -> " + move.getToX() + "," + move.getToY());
|
||||
} else {
|
||||
System.out.println("Invalid AI move.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isTurnWhite() {
|
||||
return isWhiteTurn;
|
||||
|
|
@ -118,7 +122,6 @@ public class Board {
|
|||
|
||||
public void cleanBoard() {
|
||||
pieces.clear();
|
||||
clearEnPassant();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
|
@ -234,13 +237,7 @@ public class Board {
|
|||
fileRep[y] = line;
|
||||
}
|
||||
|
||||
// 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;
|
||||
fileRep[height] = (isWhiteTurn ? "W" : "B") + "," + turnNumber;
|
||||
|
||||
return fileRep;
|
||||
}
|
||||
|
|
@ -294,23 +291,9 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -343,11 +326,6 @@ 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<>();
|
||||
|
||||
|
|
@ -378,17 +356,6 @@ public class Board {
|
|||
highlightedPositions.addAll(validMoves);
|
||||
}
|
||||
|
||||
public void playMove(Move move) {
|
||||
if (move.isValid() && !move.putsOwnKingInCheck()) {
|
||||
// SAVE STATE BEFORE MOVE
|
||||
saveCurrentState();
|
||||
|
||||
move.execute();
|
||||
|
||||
// Play the move sound using instance method
|
||||
sound.playMoveSound();
|
||||
}
|
||||
}
|
||||
|
||||
// UNDO METHODS USING ARRAYLIST
|
||||
private void saveCurrentState() {
|
||||
|
|
@ -403,15 +370,12 @@ 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()) {
|
||||
|
|
@ -429,58 +393,10 @@ 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -49,7 +49,9 @@ public class Game extends Thread {
|
|||
|
||||
private void aiPlayerTurn() {
|
||||
if(isAITurn()) {
|
||||
board.playMove(aiPlayer.computeBestMove(new Board(board)));
|
||||
Move move = aiPlayer.computeBestMove(board); // Use the real board
|
||||
board.playMove(move);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -106,5 +108,6 @@ public class Game extends Thread {
|
|||
public void toggleAI(boolean isWhite) {
|
||||
this.activationAIFlags[isWhite?1:0] = !this.activationAIFlags[isWhite?1:0];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,14 +12,6 @@ public class Move {
|
|||
private Piece capturedPiece;
|
||||
private Board board;
|
||||
|
||||
// Castling-related fields
|
||||
private CastlingHandler castlingHandler;
|
||||
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;
|
||||
|
|
@ -29,15 +21,6 @@ public class Move {
|
|||
this.board = board;
|
||||
this.movingPiece = board.getPieceAt(fromX, fromY);
|
||||
this.capturedPiece = board.getPieceAt(toX, toY);
|
||||
|
||||
// Initialize castling handler and check if this is a castling 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() {
|
||||
|
|
@ -46,46 +29,20 @@ public class Move {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Handle castling validation
|
||||
if (isCastling) {
|
||||
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));
|
||||
return validMoves.contains(new Position(toX, toY));
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
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) {
|
||||
board.removePiece(toX, toY);
|
||||
}
|
||||
|
||||
// Move the piece (remove from original position, add to new position)
|
||||
board.removePiece(fromX, fromY);
|
||||
board.setPiece(movingPiece.isWhite(), movingPiece.getType(), toX, toY);
|
||||
// Remove any piece at the destination (normal capture)
|
||||
if (capturedPiece != null) {
|
||||
board.removePiece(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();
|
||||
}
|
||||
// Move the piece (remove from original position, add to new position)
|
||||
board.removePiece(fromX, fromY);
|
||||
board.setPiece(movingPiece.isWhite(), movingPiece.getType(), toX, toY);
|
||||
|
||||
// Advance turn
|
||||
board.advanceTurn();
|
||||
|
|
@ -99,29 +56,15 @@ public class Move {
|
|||
Piece tempPiece = tempBoard.getPieceAt(fromX, fromY);
|
||||
if (tempPiece == null) return true; // Safety check
|
||||
|
||||
if (isCastling) {
|
||||
// For castling, we need to check the castling move specifically
|
||||
CastlingHandler tempHandler = new CastlingHandler(tempBoard);
|
||||
CastlingHandler.CastlingMove tempCastling = tempHandler.getCastlingMove(fromX, fromY, toX, toY);
|
||||
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);
|
||||
|
||||
// Move the piece
|
||||
tempBoard.removePiece(fromX, fromY);
|
||||
tempBoard.setPiece(tempPiece.isWhite(), tempPiece.getType(), toX, toY);
|
||||
}
|
||||
// Remove any piece at destination (normal capture)
|
||||
tempBoard.removePiece(toX, toY);
|
||||
|
||||
// Move the piece
|
||||
tempBoard.removePiece(fromX, fromY);
|
||||
tempBoard.setPiece(tempPiece.isWhite(), tempPiece.getType(), toX, toY);
|
||||
|
||||
// Check if king is in check after move
|
||||
CastlingHandler tempHandler = new CastlingHandler(tempBoard);
|
||||
return tempHandler.isKingInCheck(tempPiece.isWhite());
|
||||
return isKingInCheck(tempBoard, tempPiece.isWhite());
|
||||
}
|
||||
|
||||
public boolean putsOpponentInCheck() {
|
||||
|
|
@ -132,29 +75,15 @@ public class Move {
|
|||
Piece tempPiece = tempBoard.getPieceAt(fromX, fromY);
|
||||
if (tempPiece == null) return false; // Safety check
|
||||
|
||||
if (isCastling) {
|
||||
// For castling, execute the castling move
|
||||
CastlingHandler tempHandler = new CastlingHandler(tempBoard);
|
||||
CastlingHandler.CastlingMove tempCastling = tempHandler.getCastlingMove(fromX, fromY, toX, toY);
|
||||
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);
|
||||
|
||||
// Move the piece
|
||||
tempBoard.removePiece(fromX, fromY);
|
||||
tempBoard.setPiece(tempPiece.isWhite(), tempPiece.getType(), toX, toY);
|
||||
}
|
||||
// Remove any piece at destination (normal capture)
|
||||
tempBoard.removePiece(toX, toY);
|
||||
|
||||
// Move the piece
|
||||
tempBoard.removePiece(fromX, fromY);
|
||||
tempBoard.setPiece(tempPiece.isWhite(), tempPiece.getType(), toX, toY);
|
||||
|
||||
// Check if opponent's king is in check after move
|
||||
CastlingHandler tempHandler = new CastlingHandler(tempBoard);
|
||||
return tempHandler.isKingInCheck(!tempPiece.isWhite());
|
||||
return isKingInCheck(tempBoard, !tempPiece.isWhite());
|
||||
}
|
||||
|
||||
public boolean putsOpponentInCheckmate() {
|
||||
|
|
@ -170,25 +99,12 @@ public class Move {
|
|||
Piece tempPiece = tempBoard.getPieceAt(fromX, fromY);
|
||||
if (tempPiece == null) return false; // Safety check
|
||||
|
||||
if (isCastling) {
|
||||
// For castling, execute the castling move
|
||||
CastlingHandler tempHandler = new CastlingHandler(tempBoard);
|
||||
CastlingHandler.CastlingMove tempCastling = tempHandler.getCastlingMove(fromX, fromY, toX, toY);
|
||||
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);
|
||||
|
||||
// Move the piece
|
||||
tempBoard.removePiece(fromX, fromY);
|
||||
tempBoard.setPiece(tempPiece.isWhite(), tempPiece.getType(), toX, toY);
|
||||
}
|
||||
// Remove any piece at destination (normal capture)
|
||||
tempBoard.removePiece(toX, toY);
|
||||
|
||||
// Move the piece
|
||||
tempBoard.removePiece(fromX, fromY);
|
||||
tempBoard.setPiece(tempPiece.isWhite(), tempPiece.getType(), toX, toY);
|
||||
|
||||
boolean opponentColor = !tempPiece.isWhite();
|
||||
|
||||
|
|
@ -218,23 +134,23 @@ public class Move {
|
|||
switch (piece.getType()) {
|
||||
case Pawn:
|
||||
addPawnMoves(moves, piece, board);
|
||||
break;
|
||||
return moves;
|
||||
case Rook:
|
||||
addRookMoves(moves, piece, board);
|
||||
break;
|
||||
return moves;
|
||||
case Knight:
|
||||
addKnightMoves(moves, piece, board);
|
||||
break;
|
||||
return moves;
|
||||
case Bishop:
|
||||
addBishopMoves(moves, piece, board);
|
||||
break;
|
||||
return moves;
|
||||
case Queen:
|
||||
addRookMoves(moves, piece, board);
|
||||
addBishopMoves(moves, piece, board);
|
||||
break;
|
||||
return moves;
|
||||
case King:
|
||||
addKingMoves(moves, piece, board);
|
||||
break;
|
||||
return moves;
|
||||
}
|
||||
|
||||
return moves;
|
||||
|
|
@ -257,8 +173,33 @@ public class Move {
|
|||
}
|
||||
|
||||
public boolean isKingInCheck(Board board, boolean isWhiteKing) {
|
||||
CastlingHandler handler = new CastlingHandler(board);
|
||||
return handler.isKingInCheck(isWhiteKing);
|
||||
// Find the king's position
|
||||
Piece king = null;
|
||||
for (Piece p : board.getPieces()) {
|
||||
if (p.getType() == PieceType.King && p.isWhite() == isWhiteKing) {
|
||||
king = p;
|
||||
return checkIfKingUnderAttack(board, isWhiteKing, king);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkIfKingUnderAttack(Board board, 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, board);
|
||||
|
||||
// If any piece can move to king's position, king is in check
|
||||
if (attackMoves.contains(new Position(king.getX(), king.getY()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addPawnMoves(List<Position> validMoves, Piece piece, Board board) {
|
||||
|
|
@ -266,7 +207,7 @@ public class Move {
|
|||
int y = piece.getY();
|
||||
boolean isWhite = piece.isWhite();
|
||||
|
||||
int direction = isWhite ? -1 : 1; // White pawns move up (decreasing y), black pawns move down (increasing y)
|
||||
int direction = isWhite ? -1 : 1; // White pawns move up, black pawns move down
|
||||
|
||||
// Forward movement
|
||||
int newY = y + direction;
|
||||
|
|
@ -285,7 +226,7 @@ public class Move {
|
|||
}
|
||||
}
|
||||
|
||||
// Diagonal captures (regular captures)
|
||||
// Diagonal captures
|
||||
for (int dx = -1; dx <= 1; dx += 2) {
|
||||
int newX = x + dx;
|
||||
if (newX >= 0 && newX < board.getWidth()) {
|
||||
|
|
@ -296,29 +237,6 @@ 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) {
|
||||
|
|
@ -428,8 +346,9 @@ public class Move {
|
|||
private void addKingMoves(List<Position> validMoves, Piece piece, Board board) {
|
||||
int x = piece.getX();
|
||||
int y = piece.getY();
|
||||
boolean isWhite = piece.isWhite();
|
||||
|
||||
// All adjacent squares (normal king moves)
|
||||
// All adjacent squares
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dy = -1; dy <= 1; dy++) {
|
||||
if (dx == 0 && dy == 0) continue; // Skip the current position
|
||||
|
|
@ -440,30 +359,13 @@ public class Move {
|
|||
if (newX >= 0 && newX < board.getWidth() && newY >= 0 && newY < board.getHeight()) {
|
||||
Piece targetPiece = board.getPieceAt(newX, newY);
|
||||
|
||||
if (targetPiece == null || targetPiece.isWhite() != piece.isWhite()) {
|
||||
if (targetPiece == null || targetPiece.isWhite() != isWhite) {
|
||||
// Empty square or can capture opponent's piece
|
||||
validMoves.add(new Position(newX, newY));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add castling moves
|
||||
CastlingHandler handler = new CastlingHandler(board);
|
||||
List<CastlingHandler.Position> castlingPositions = handler.getCastlingPositions(piece);
|
||||
for (CastlingHandler.Position castlingPos : castlingPositions) {
|
||||
validMoves.add(new Position(castlingPos.x, castlingPos.y));
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to check if a list contains a position
|
||||
private boolean containsPosition(List<Position> positions, Position target) {
|
||||
for (Position pos : positions) {
|
||||
if (pos.x == target.x && pos.y == target.y) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public class Position {
|
||||
|
|
@ -475,6 +377,7 @@ public class Move {
|
|||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null || getClass() != obj.getClass()) return false;
|
||||
|
|
@ -482,4 +385,9 @@ public class Move {
|
|||
return x == position.x && y == position.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
public int getFromX() { return fromX; }
|
||||
public int getFromY() { return fromY; }
|
||||
public int getToX() { return toX; }
|
||||
public int getToY() { return toY; }
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,4 +32,11 @@ public class Piece {
|
|||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
public Piece(boolean isWhite, PieceType type, int x, int y) {
|
||||
this.isWhite = isWhite;
|
||||
this.type = type;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue