diff --git a/src/backend/Board.java b/src/backend/Board.java index c681aab..5c2a741 100644 --- a/src/backend/Board.java +++ b/src/backend/Board.java @@ -144,7 +144,8 @@ public class Board { selectedX = x; selectedY = y; hasSelectedPiece = true; - highlightedSquares = moveHelper.getValidMoves(clicked, board, width, height, enPassantTarget); + highlightedSquares = moveHelper.getValidMoves(clicked, board, width, height, enPassantTarget, this); + } } else { // Check if clicked again on the same square to unselect @@ -168,6 +169,28 @@ public class Board { board[selectedX][selectedY] = null; selectedPiece.setX(x); selectedPiece.setY(y); + selectedPiece.setMoved(true); // ✅ Marque la pièce comme ayant bougé + + // Déplacement de la tour si roque + if (selectedPiece.getType() == PieceType.King && Math.abs(x - selectedX) == 2) { + + if (x > selectedX) { + // Petit roque (côté roi) + Piece rook = board[7][y]; + board[5][y] = rook; + board[7][y] = null; + rook.setX(5); + rook.setMoved(true); + } else { + // Grand roque (côté dame) + Piece rook = board[0][y]; + board[3][y] = rook; + board[0][y] = null; + rook.setX(3); + rook.setMoved(true); + } + } + // If en passant, remove the captured pawn if (isEnPassant) { @@ -253,6 +276,36 @@ public class Board { } return false; } + + public boolean isInCheck(boolean white) { + // Trouver le roi + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + Piece p = board[x][y]; + if (p != null && p.getType() == PieceType.King && p.isWhite() == white) { + return isSquareAttacked(x, y, !white); + } + } + } + return false; + } + + public boolean isSquareAttacked(int x, int y, boolean byWhite) { + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + Piece p = board[i][j]; + if (p != null && p.isWhite() == byWhite) { + ArrayList moves = moveHelper.getValidMoves(p, board, width, height, enPassantTarget, this); + for (int[] m : moves) { + if (m[0] == x && m[1] == y) { + return true; + } + } + } + } + } + return false; + } public void undoLastMove() { // TODO diff --git a/src/backend/Move.java b/src/backend/Move.java index 9a806b2..b927245 100644 --- a/src/backend/Move.java +++ b/src/backend/Move.java @@ -3,99 +3,142 @@ package backend; import java.util.ArrayList; public class Move { + + private boolean canCastle(Board boardObj, Piece[][] board, int kingX, int kingY, int rookX, int rookY, boolean isWhite, int width, int height) { + Piece rook = board[rookX][rookY]; + if (rook == null || rook.getType() != PieceType.Rook || rook.isWhite() != isWhite || rook.hasMoved()) { + return false; + } - public ArrayList getValidMoves(Piece piece, Piece[][] board, int width, int height, int[] enPassantTarget) { - ArrayList moves = new ArrayList<>(); - int x = piece.getX(); - int y = piece.getY(); - PieceType type = piece.getType(); - boolean isWhite = piece.isWhite(); + // Pas de pièces entre roi et tour + int dir = (rookX > kingX) ? 1 : -1; + for (int i = kingX + dir; i != rookX; i += dir) { + if (board[i][kingY] != null) { + return false; + } + } - if (type == PieceType.Pawn) { - int dir = isWhite ? 1 : -1; - int startRow = isWhite ? 1 : 6; + // Le roi ne doit pas être en échec ni traverser une case attaquée + for (int i = 0; i <= 2; i++) { + int stepX = kingX + i * dir; + if (boardObj.isSquareAttacked(stepX, kingY, !isWhite)) { + return false; + } + } - int oneStep = y + dir; - if (inBounds(x, oneStep, width, height) && board[x][oneStep] == null) { - moves.add(new int[]{x, oneStep}); + return !boardObj.isInCheck(isWhite); + } - int twoStep = y + 2 * dir; - if (y == startRow && inBounds(x, twoStep, width, height) && board[x][twoStep] == null && board[x][oneStep] == null) { - moves.add(new int[]{x, twoStep}); - } - } - for (int dx : new int[]{-1, 1}) { - int nx = x + dx; - int ny = y + dir; - if (inBounds(nx, ny, width, height)) { - if (board[nx][ny] != null && board[nx][ny].isWhite() != isWhite) { - moves.add(new int[]{nx, ny}); - } else if (enPassantTarget != null && enPassantTarget[0] == nx && enPassantTarget[1] == ny) { - int pawnY = y; - if (board[nx][pawnY] != null && board[nx][pawnY].getType() == PieceType.Pawn && board[nx][pawnY].isWhite() != isWhite) { - moves.add(new int[]{nx, ny}); - } - } - } - } - } + public ArrayList getValidMoves(Piece piece, Piece[][] board, int width, int height, int[] enPassantTarget, Board boardObj) { + ArrayList moves = new ArrayList<>(); + int x = piece.getX(); + int y = piece.getY(); + PieceType type = piece.getType(); + boolean isWhite = piece.isWhite(); - else if (type == PieceType.Knight) { - int[][] jumps = {{2, 1}, {1, 2}, {-1, 2}, {-2, 1}, - {-2, -1}, {-1, -2}, {1, -2}, {2, -1}}; - for (int[] j : jumps) { - int nx = x + j[0], ny = y + j[1]; - if (inBounds(nx, ny, width, height)) { - if (board[nx][ny] == null || board[nx][ny].isWhite() != isWhite) { - moves.add(new int[]{nx, ny}); - } - } - } - } + if (type == PieceType.Pawn) { + int dir = isWhite ? 1 : -1; + int startRow = isWhite ? 1 : 6; - else if (type == PieceType.Bishop || type == PieceType.Rook || type == PieceType.Queen) { - int[][] dirs; - if (type == PieceType.Bishop) { - dirs = new int[][]{{1,1}, {-1,1}, {-1,-1}, {1,-1}}; - } else if (type == PieceType.Rook) { - dirs = new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}}; - } else { // Queen - dirs = new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}, {1,1}, {-1,1}, {-1,-1}, {1,-1}}; - } + int oneStep = y + dir; + if (inBounds(x, oneStep, width, height) && board[x][oneStep] == null) { + moves.add(new int[]{x, oneStep}); - for (int[] d : dirs) { - int nx = x + d[0], ny = y + d[1]; - while (inBounds(nx, ny, width, height)) { - if (board[nx][ny] == null) { - moves.add(new int[]{nx, ny}); - } else { - if (board[nx][ny].isWhite() != isWhite) { - moves.add(new int[]{nx, ny}); - } - break; - } - nx += d[0]; ny += d[1]; - } - } - } + int twoStep = y + 2 * dir; + if (y == startRow && inBounds(x, twoStep, width, height) && board[x][twoStep] == null && board[x][oneStep] == null) { + moves.add(new int[]{x, twoStep}); + } + } - else if (type == PieceType.King) { - int[][] dirs = {{1,0}, {-1,0}, {0,1}, {0,-1}, {1,1}, {-1,1}, {-1,-1}, {1,-1}}; - for (int[] d : dirs) { - int nx = x + d[0], ny = y + d[1]; - if (inBounds(nx, ny, width, height)) { - if (board[nx][ny] == null || board[nx][ny].isWhite() != isWhite) { - moves.add(new int[]{nx, ny}); - } - } - } + for (int dx : new int[]{-1, 1}) { + int nx = x + dx; + int ny = y + dir; + if (inBounds(nx, ny, width, height)) { + if (board[nx][ny] != null && board[nx][ny].isWhite() != isWhite) { + moves.add(new int[]{nx, ny}); + } else if (enPassantTarget != null && enPassantTarget[0] == nx && enPassantTarget[1] == ny) { + int pawnY = y; + if (board[nx][pawnY] != null && board[nx][pawnY].getType() == PieceType.Pawn && board[nx][pawnY].isWhite() != isWhite) { + moves.add(new int[]{nx, ny}); + } + } + } + } + } - // Tu peux ajouter ici le roque (castling) si tu veux, mais tu dois gérer hasMoved, menace, etc. - } + else if (type == PieceType.Knight) { + int[][] jumps = { + {2, 1}, {1, 2}, {-1, 2}, {-2, 1}, + {-2, -1}, {-1, -2}, {1, -2}, {2, -1} + }; + for (int[] j : jumps) { + int nx = x + j[0], ny = y + j[1]; + if (inBounds(nx, ny, width, height)) { + if (board[nx][ny] == null || board[nx][ny].isWhite() != isWhite) { + moves.add(new int[]{nx, ny}); + } + } + } + } + + else if (type == PieceType.Bishop || type == PieceType.Rook || type == PieceType.Queen) { + int[][] dirs; + if (type == PieceType.Bishop) { + dirs = new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}; + } else if (type == PieceType.Rook) { + dirs = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; + } else { // Queen + dirs = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {-1, 1}, {-1, -1}, {1, -1}}; + } + + for (int[] d : dirs) { + int nx = x + d[0], ny = y + d[1]; + while (inBounds(nx, ny, width, height)) { + if (board[nx][ny] == null) { + moves.add(new int[]{nx, ny}); + } else { + if (board[nx][ny].isWhite() != isWhite) { + moves.add(new int[]{nx, ny}); + } + break; + } + nx += d[0]; + ny += d[1]; + } + } + } + + else if (type == PieceType.King) { + int[][] dirs = { + {1, 0}, {-1, 0}, {0, 1}, {0, -1}, + {1, 1}, {-1, 1}, {-1, -1}, {1, -1} + }; + for (int[] d : dirs) { + int nx = x + d[0], ny = y + d[1]; + if (inBounds(nx, ny, width, height)) { + if (board[nx][ny] == null || board[nx][ny].isWhite() != isWhite) { + moves.add(new int[]{nx, ny}); + } + } + } + + if (!piece.hasMoved()) { + int row = isWhite ? 0 : 7; + + if (canCastle(boardObj, board, x, y, 7, row, isWhite, width, height)) { + moves.add(new int[]{x + 2, y}); + } + + if (canCastle(boardObj, board, x, y, 0, row, isWhite, width, height)) { + moves.add(new int[]{x - 2, y}); + } + } + } + + return moves; + } - return moves; - } private boolean inBounds(int x, int y, int width, int height) { return x >= 0 && x < width && y >= 0 && y < height; diff --git a/src/backend/Piece.java b/src/backend/Piece.java index e0c2ea9..290eb47 100644 --- a/src/backend/Piece.java +++ b/src/backend/Piece.java @@ -82,5 +82,14 @@ public boolean isWhite() { return isWhite; +} +private boolean hasMoved = false; + +public boolean hasMoved() { + return hasMoved; +} + +public void setMoved(boolean moved) { + this.hasMoved = moved; } }