From 5215af63f08520d9e2b846a34b2bfb0da8e4050b Mon Sep 17 00:00:00 2001 From: utente Date: Fri, 9 May 2025 09:47:49 +0200 Subject: [PATCH] adding autoplayer,Check on the king, Saved games, En passant --- Chess saved 2 | 9 +++ chess saved 1 | 9 +++ src/backend/AutoPlayer.java | 111 +++++++++++++++++++++++++++++++----- src/backend/Board.java | 4 +- src/backend/CheckKing.java | 64 +++++++++++++++++++++ src/backend/EnPassant.java | 40 +++++++++++++ src/backend/Move.java | 27 +++++++-- 7 files changed, 244 insertions(+), 20 deletions(-) create mode 100644 Chess saved 2 create mode 100644 chess saved 1 create mode 100644 src/backend/CheckKing.java create mode 100644 src/backend/EnPassant.java diff --git a/Chess saved 2 b/Chess saved 2 new file mode 100644 index 0000000..d36c8e2 --- /dev/null +++ b/Chess saved 2 @@ -0,0 +1,9 @@ +BR,BN,BB,BQ,BK,,BN,BR +BP,BP,BP,BP,,BP,BP,BP +,,,,,,, +,,,,WP,,, +,,,,WP,,, +,,,,,WN,, +WP,WP,WP,WP,,BB,WP,WP +WR,WN,WB,WQ,WK,WB,,WR +B diff --git a/chess saved 1 b/chess saved 1 new file mode 100644 index 0000000..6dced5b --- /dev/null +++ b/chess saved 1 @@ -0,0 +1,9 @@ +BR,BN,BB,,BK,BB,BN,BR +BP,BP,BP,BP,,,BP,BP +,,,,BP,BQ,, +,,,,,BP,, +,,,,,,WP, +,,,,,WN,,WB +WP,WP,WP,WP,WP,WP,,WP +WR,WN,WB,WQ,WK,,,WR +W diff --git a/src/backend/AutoPlayer.java b/src/backend/AutoPlayer.java index a48c0c2..5002b87 100644 --- a/src/backend/AutoPlayer.java +++ b/src/backend/AutoPlayer.java @@ -1,17 +1,100 @@ package backend; +import java.util.Set; + 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 = 3; + + public Move computeBestMove(Board board) { + boolean isWhite = board.isTurnWhite(); + int bestValue = Integer.MIN_VALUE; + Move bestMove = null; + + for (Piece piece : board.getPieces()) { + if (piece.isWhite() != isWhite) continue; + + Set moves = board.getValidMoves(piece, false); + for (String moveStr : moves) { + String[] parts = moveStr.split(","); + int toX = Integer.parseInt(parts[0]); + int toY = Integer.parseInt(parts[1]); + + Board newBoard = new Board(board); + newBoard.playMove(new Move(piece.getX(), piece.getY(), toX, toY)); + int value = minimax(newBoard, MAX_DEPTH - 1, Integer.MIN_VALUE, Integer.MAX_VALUE, !isWhite); + + if (value > bestValue) { + bestValue = value; + bestMove = new Move(piece.getX(), piece.getY(), toX, toY); + } + } + } + return bestMove; + } + + private int minimax(Board board, int depth, int alpha, int beta, boolean maximizingPlayer) { + if (depth == 0) { + return evaluateBoard(board); + } + + boolean isWhite = board.isTurnWhite(); + int bestValue = maximizingPlayer ? Integer.MIN_VALUE : Integer.MAX_VALUE; + + for (Piece piece : board.getPieces()) { + if (piece.isWhite() != isWhite) continue; + + Set moves = board.getValidMoves(piece, false); + for (String moveStr : moves) { + String[] parts = moveStr.split(","); + int toX = Integer.parseInt(parts[0]); + int toY = Integer.parseInt(parts[1]); + + Board newBoard = new Board(board); + newBoard.playMove(new Move(piece.getX(), piece.getY(), toX, toY)); + int value = minimax(newBoard, depth - 1, alpha, beta, !maximizingPlayer); + + if (maximizingPlayer) { + bestValue = Math.max(bestValue, value); + alpha = Math.max(alpha, value); + } else { + bestValue = Math.min(bestValue, value); + beta = Math.min(beta, value); + } + + if (beta <= alpha) { + break; + } + } + } + return bestValue; + } + + private int evaluateBoard(Board board) { + int total = 0; + for (Piece piece : board.getPieces()) { + int value = getPieceValue(piece.getType()); + total += piece.isWhite() ? value : -value; + } + return total; + } + + private int getPieceValue(PieceType type) { + switch (type) { + case King: + return 1000; + case Queen: + return 9; + case Rook: + return 5; + case Bishop: + case Knight: + return 3; + case Pawn: + return 1; + default: + return 0; + } + } + } + + diff --git a/src/backend/Board.java b/src/backend/Board.java index cf57355..029276c 100644 --- a/src/backend/Board.java +++ b/src/backend/Board.java @@ -397,7 +397,9 @@ public class Board { } public void playMove(Move move) { - //TODO + movePiece(move.getFromX(), move.getFromY(), move.getToX(), move.getToY()); + isWhiteTurn = !isWhiteTurn; + turnNumber++; } private class MoveRecord { final Piece movedPiece; diff --git a/src/backend/CheckKing.java b/src/backend/CheckKing.java new file mode 100644 index 0000000..7eb94c2 --- /dev/null +++ b/src/backend/CheckKing.java @@ -0,0 +1,64 @@ +package backend; + +import java.util.HashSet; +import java.util.Set; + +public class CheckKing { + + // 1. Check if the king of the given color is under attack + public static boolean isKingInCheck(Board board, boolean white) { + Piece[][] grid = board.getBoardMatrix(); + Piece king = null; + + // Find the king + for (int y = 0; y < board.getHeight(); y++) { + for (int x = 0; x < board.getWidth(); x++) { + Piece piece = grid[y][x]; + if (piece != null && piece.isWhite() == white && piece.getType() == PieceType.King) { + king = piece; + break; + } + } + } + + if (king == null) return false; + + int kingX = king.getX(); + int kingY = king.getY(); + + // Check if any opposing piece can move to the king’s square + for (Piece[] row : grid) { + for (Piece p : row) { + if (p != null && p.isWhite() != white) { + Set moves = board.getValidMoves(p, true); // skip validation + if (moves.contains(kingX + "," + kingY)) { + return true; + } + } + } + } + + return false; + } + + // 2. Filter out any moves that would leave the king in check + public static Set filterLegalMoves(Board board, Piece piece, Set candidateMoves) { + Set legalMoves = new HashSet<>(); + + for (String move : candidateMoves) { + String[] parts = move.split(","); + int toX = Integer.parseInt(parts[0]); + int toY = Integer.parseInt(parts[1]); + + // Create a simulated board to test the move + Board copy = new Board(board); + copy.movePiece(piece.getX(), piece.getY(), toX, toY); + + if (!isKingInCheck(copy, piece.isWhite())) { + legalMoves.add(move); + } + } + + return legalMoves; + } +} diff --git a/src/backend/EnPassant.java b/src/backend/EnPassant.java new file mode 100644 index 0000000..341954d --- /dev/null +++ b/src/backend/EnPassant.java @@ -0,0 +1,40 @@ +package backend; + +public class EnPassant { + private int[] enPassantTarget = null; + + public void updateTarget(Piece piece, int fromY, int toY, int toX) { + if (piece.getType() == PieceType.Pawn && Math.abs(toY - fromY) == 2) { + enPassantTarget = new int[]{toX, (fromY + toY) / 2}; + } else { + enPassantTarget = null; + } + } + + public int[] getTarget() { + return enPassantTarget; + } + + public boolean isEnPassantCapture(Piece piece, int fromX, int toX, int toY, Piece[][] board) { + if (piece.getType() != PieceType.Pawn || board[toY][toX] != null || fromX == toX) { + return false; + } + + if (enPassantTarget != null && enPassantTarget[0] == toX && enPassantTarget[1] == toY) { + int capturedY = piece.isWhite() ? toY + 1 : toY - 1; + Piece adjacent = board[capturedY][toX]; + return adjacent != null && adjacent.getType() == PieceType.Pawn && adjacent.isWhite() != piece.isWhite(); + } + + return false; + } + public void setTarget(int[] target) { + if (target == null) { + this.enPassantTarget = null; + } else { + this.enPassantTarget = new int[]{target[0], target[1]}; + } + } + +} + diff --git a/src/backend/Move.java b/src/backend/Move.java index 7b9ff9b..ff502f6 100644 --- a/src/backend/Move.java +++ b/src/backend/Move.java @@ -1,5 +1,22 @@ -package backend; - -public class Move { - -} +package backend; + +public class Move { + private final int fromX, fromY, toX, toY; + + public Move(int fromX, int fromY, int toX, int toY) { + this.fromX = fromX; + this.fromY = fromY; + this.toX = toX; + this.toY = toY; + } + + public int getFromX() { return fromX; } + public int getFromY() { return fromY; } + public int getToX() { return toX; } + public int getToY() { return toY; } + + @Override + public String toString() { + return "(" + fromX + "," + fromY + ") -> (" + toX + "," + toY + ")"; + } +}