adding autoplayer,Check on the king, Saved games, En passant
This commit is contained in:
parent
f53bc258b4
commit
5215af63f0
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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<String> 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<String> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<String> 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<String> filterLegalMoves(Board board, Piece piece, Set<String> candidateMoves) {
|
||||
Set<String> 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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]};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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 + ")";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue