diff --git a/src/backend/Board.java b/src/backend/Board.java index 474b9bd..2b95b27 100644 --- a/src/backend/Board.java +++ b/src/backend/Board.java @@ -19,6 +19,28 @@ public class Board { this.pieces = new ArrayList<>(); //TODO } + + public Board(Board other) { + this.width = other.width; + this.height = other.height; + this.turnNumber = other.turnNumber; + this.turnWhite = other.turnWhite; + this.selected = other.selected != null ? new int[]{other.selected[0], other.selected[1]} : null; + + this.pieces = new ArrayList<>(); + for (Piece p : other.pieces) { + this.pieces.add(new Piece(p)); // uses Piece copy constructor (next step) + } + + this.highlighted = new ArrayList<>(); + for (int[] pos : other.highlighted) { + this.highlighted.add(new int[]{pos[0], pos[1]}); + } + + this.moveHistory = new ArrayList<>(other.moveHistory); + } + + public int getWidth() { //TODO @@ -112,10 +134,57 @@ public class Board { return sb.toString(); } - + + public ArrayList getPieces() { return pieces; } + + public Piece getKing(boolean isWhite) { + for (Piece p : pieces) { + if (p.isWhite() == isWhite && p.getType() == PieceType.King) { + return p; + } + } + return null; + } + + public boolean isInCheck(boolean whitePlayer) { + Piece king = getKing(whitePlayer); + if (king == null) return false; + + int kingX = king.getX(); + int kingY = king.getY(); + + for (Piece piece : pieces) { + if (piece.isWhite() != whitePlayer) { + ArrayList enemyMoves = getLegalMoves(piece, false); // disable check validation + for (int[] move : enemyMoves) { + if (move[0] == kingX && move[1] == kingY) { + return true; + } + } + } + } + return false; + } + + + public boolean isCheckmate(boolean whitePlayer) { + if (!isInCheck(whitePlayer)) return false; + + for (Piece p : pieces) { + if (p.isWhite() == whitePlayer) { + ArrayList legalMoves = getLegalMoves(p); + if (!legalMoves.isEmpty()) return false; + } + } + + return true; + } + + + public void userTouch(int x, int y) { Piece clickedPiece = getPieceAt(x, y); @@ -149,34 +218,34 @@ public class Board { public ArrayList getLegalMoves(Piece piece) { + return getLegalMoves(piece, true); // default: check for king safety + } + + public ArrayList getLegalMoves(Piece piece, boolean validateCheck) { ArrayList moves = new ArrayList<>(); int x = piece.getX(), y = piece.getY(); int dir = piece.isWhite() ? 1 : -1; switch (piece.getType()) { case Pawn: - int forwardY = y + dir; + int forwardY = y + dir; - // Move one square forward if it's empty if (isInBounds(x, forwardY) && getPieceAt(x, forwardY) == null) { - moves.add(new int[] {x, forwardY}); - - // Move two squares forward if at starting position and both squares are empty + moves.add(new int[]{x, forwardY}); int twoForwardY = y + 2 * dir; boolean atStartingRank = (piece.isWhite() && y == 1) || (!piece.isWhite() && y == 6); if (atStartingRank && isInBounds(x, twoForwardY) && getPieceAt(x, twoForwardY) == null) { - moves.add(new int[] {x, twoForwardY}); + moves.add(new int[]{x, twoForwardY}); } } - // Capture diagonally Piece diagLeft = getPieceAt(x - 1, forwardY); if (diagLeft != null && diagLeft.isWhite() != piece.isWhite()) - moves.add(new int[] {x - 1, forwardY}); + moves.add(new int[]{x - 1, forwardY}); Piece diagRight = getPieceAt(x + 1, forwardY); if (diagRight != null && diagRight.isWhite() != piece.isWhite()) - moves.add(new int[] {x + 1, forwardY}); + moves.add(new int[]{x + 1, forwardY}); break; case Rook: @@ -229,8 +298,25 @@ public class Board { } break; } - return moves; + + if (!validateCheck) return moves; + + // Filter out moves that put own king in check + ArrayList legalMoves = new ArrayList<>(); + for (int[] move : moves) { + Board copy = new Board(this); + Piece p = copy.getPieceAt(x, y); + Piece captured = copy.getPieceAt(move[0], move[1]); + Move testMove = new Move(p, x, y, move[0], move[1], captured); + copy.playMove(testMove); + + if (!copy.isInCheck(piece.isWhite())) { + legalMoves.add(move); + } + } + return legalMoves; } + private void addLinearMoves(ArrayList moves, Piece piece, int dx, int dy) { int x = piece.getX(), y = piece.getY(); @@ -314,22 +400,6 @@ public void undoLastMove() { selected = null; highlighted.clear(); } - - public Board(Board board) { - if (moveHistory.isEmpty()) return; - - Move lastMove = moveHistory.remove(moveHistory.size() - 1); - Piece movedPiece = lastMove.getPieceMoved(); - movedPiece.setPosition(lastMove.getFromX(), lastMove.getFromY()); - - if (lastMove.getPieceCaptured() != null) { - pieces.add(lastMove.getPieceCaptured()); - } - - turnWhite = !turnWhite; - turnNumber--; - - } public void playMove(Move move) { Piece piece = move.getPieceMoved(); diff --git a/src/backend/Game.java b/src/backend/Game.java index 3834699..c6ae7ea 100644 --- a/src/backend/Game.java +++ b/src/backend/Game.java @@ -109,5 +109,7 @@ public class Game extends Thread { public void toggleAI(boolean isWhite) { this.activationAIFlags[isWhite?1:0] = !this.activationAIFlags[isWhite?1:0]; } + + } diff --git a/src/backend/Piece.java b/src/backend/Piece.java index 95b1105..c00a910 100644 --- a/src/backend/Piece.java +++ b/src/backend/Piece.java @@ -36,6 +36,13 @@ public class Piece { public void setPosition(int x , int y) { this.x=x; this.y=y; - } + } + public Piece(Piece other) { + this.isWhite = other.isWhite; + this.type = other.type; + this.x = other.x; + this.y = other.y; + } + }