From 2bf326eae243fbcefad256bdbdf642411c22a129 Mon Sep 17 00:00:00 2001 From: jefei Date: Fri, 16 May 2025 19:40:51 +0200 Subject: [PATCH] Castling Done --- saved101 | 9 +++ src/backend/Board.java | 175 +++++++++++++++++++++++++++++++++-------- src/backend/Move.java | 18 +++++ src/backend/Piece.java | 2 +- 4 files changed, 171 insertions(+), 33 deletions(-) create mode 100644 saved101 diff --git a/saved101 b/saved101 new file mode 100644 index 0000000..96fec79 --- /dev/null +++ b/saved101 @@ -0,0 +1,9 @@ +BR,BN,BB,BQ,BK,BB,BN,BR +BP,BP,BP,BP,BP,..,BP,BP +..,..,..,..,..,..,..,.. +..,..,..,..,..,BP,..,.. +..,..,..,..,WP,..,..,.. +..,..,..,..,..,..,..,.. +WP,WP,WP,WP,..,WP,WP,WP +WR,WN,WB,WQ,WK,WB,WN,WR +W diff --git a/src/backend/Board.java b/src/backend/Board.java index 6969ba9..648d84a 100644 --- a/src/backend/Board.java +++ b/src/backend/Board.java @@ -1,5 +1,5 @@ package backend; - +//HI import java.util.ArrayList; import java.util.Stack; @@ -16,6 +16,14 @@ private int selectedX, selectedY; // if so, which square is “in hand”? private int turnNumber = 0; // how many half-moves have been played? private boolean turnWhite = true; // true = White to play, false = Black // ───────────────────────────────────────────────────────────── +private boolean whiteKingMoved = false; +private boolean blackKingMoved = false; +private boolean whiteKingsideRookMoved = false; +private boolean whiteQueensideRookMoved = false; +private boolean blackKingsideRookMoved = false; +private boolean blackQueensideRookMoved = false; + + public String[] toFileRep() { String[] lines = new String[height + 1]; @@ -173,7 +181,6 @@ public String toString() { return sb.toString(); } public void userTouch(int x, int y) { - // 1) Find if you clicked on a piece at (x,y) Piece clicked = null; for (Piece p : Pieces) { if (p.getX() == x && p.getY() == y) { @@ -182,7 +189,6 @@ public void userTouch(int x, int y) { } } - // 2) If nothing is selected, select a piece of the correct color if (!hasSelection) { if (clicked != null && clicked.isWhite() == turnWhite) { hasSelection = true; @@ -192,20 +198,13 @@ public void userTouch(int x, int y) { return; } - // 3) If you click the same square again → deselect if (x == selectedX && y == selectedY) { hasSelection = false; return; } - // 4) If the square is not highlighted (illegal), ignore it - if (!isHighlighted(x, y)) { - return; - } + if (!isHighlighted(x, y)) return; - // 5) Do the move - - // Capture (including en passant) Piece captured = null; for (Piece p : Pieces) { if (p.getX() == x && p.getY() == y) { @@ -214,7 +213,6 @@ public void userTouch(int x, int y) { } } - // Get the piece to move (only declare once!) Piece toMove = null; for (Piece p : Pieces) { if (p.getX() == selectedX && p.getY() == selectedY) { @@ -223,54 +221,93 @@ public void userTouch(int x, int y) { } } - // En passant condition if (captured == null && toMove != null && toMove.getType() == PieceType.Pawn) { int dir = toMove.isWhite() ? -1 : 1; if (lastDoubleStepPawn != null && lastDoubleStepPawn.getX() == x && lastDoubleStepPawn.getY() == y - dir && lastDoubleStepPawn.isWhite() != toMove.isWhite()) { - - Pieces.removeIf(p -> p.getX() == lastDoubleStepPawn.getX() && p.getY() == lastDoubleStepPawn.getY()); - captured = lastDoubleStepPawn; - + Pieces.removeIf(p -> p.getX() == lastDoubleStepPawn.getX() && p.getY() == lastDoubleStepPawn.getY()); + captured = lastDoubleStepPawn; } } - // Normal capture - if (captured != null) { - Pieces.remove(captured); - } + if (captured != null) Pieces.remove(captured); - // Move the selected piece if (toMove != null) { - Pieces.removeIf(p -> p.getX() == selectedX && p.getY() == selectedY); + Pieces.removeIf(p -> p.getX() == selectedX && p.getY() == selectedY); - // Check for promotion boolean isWhite = toMove.isWhite(); PieceType type = toMove.getType(); + + Piece rookPiece = null; + int rookFromX = -1, rookFromY = -1, rookToX = -1, rookToY = -1; + + if (type == PieceType.King) { + if (isWhite) whiteKingMoved = true; + else blackKingMoved = true; + } else if (type == PieceType.Rook) { + if (isWhite && selectedX == 0 && selectedY == 7) whiteQueensideRookMoved = true; + if (isWhite && selectedX == 7 && selectedY == 7) whiteKingsideRookMoved = true; + if (!isWhite && selectedX == 0 && selectedY == 0) blackQueensideRookMoved = true; + if (!isWhite && selectedX == 7 && selectedY == 0) blackKingsideRookMoved = true; + } + + if (type == PieceType.King) { + if (isWhite) { + if (selectedX == 4 && selectedY == 7 && x == 6 && y == 7) { + Pieces.removeIf(p -> p.getX() == 7 && p.getY() == 7); + Pieces.add(new Piece(5, 7, true, PieceType.Rook)); + whiteKingsideRookMoved = true; + rookPiece = new Piece(7, 7, true, PieceType.Rook); + rookFromX = 7; rookFromY = 7; rookToX = 5; rookToY = 7; + } else if (selectedX == 4 && selectedY == 7 && x == 2 && y == 7) { + Pieces.removeIf(p -> p.getX() == 0 && p.getY() == 7); + Pieces.add(new Piece(3, 7, true, PieceType.Rook)); + whiteQueensideRookMoved = true; + rookPiece = new Piece(0, 7, true, PieceType.Rook); + rookFromX = 0; rookFromY = 7; rookToX = 3; rookToY = 7; + } + } else { + if (selectedX == 4 && selectedY == 0 && x == 6 && y == 0) { + Pieces.removeIf(p -> p.getX() == 7 && p.getY() == 0); + Pieces.add(new Piece(5, 0, false, PieceType.Rook)); + blackKingsideRookMoved = true; + rookPiece = new Piece(7, 0, false, PieceType.Rook); + rookFromX = 7; rookFromY = 0; rookToX = 5; rookToY = 0; + } else if (selectedX == 4 && selectedY == 0 && x == 2 && y == 0) { + Pieces.removeIf(p -> p.getX() == 0 && p.getY() == 0); + Pieces.add(new Piece(3, 0, false, PieceType.Rook)); + blackQueensideRookMoved = true; + rookPiece = new Piece(0, 0, false, PieceType.Rook); + rookFromX = 0; rookFromY = 0; rookToX = 3; rookToY = 0; + } + } + } + if (type == PieceType.Pawn && ((isWhite && y == 0) || (!isWhite && y == 7))) { - // Promote to queen Pieces.add(new Piece(x, y, isWhite, PieceType.Queen)); } else { - // Normal move Pieces.add(new Piece(x, y, isWhite, type)); } - // Track if this move is a double pawn move if (type == PieceType.Pawn && Math.abs(y - toMove.getY()) == 2) { lastDoubleStepPawn = new Piece(x, y, isWhite, PieceType.Pawn); } else { lastDoubleStepPawn = null; } - // Update state + Move move; + if (type == PieceType.King && rookPiece != null) { + move = new Move(toMove, x, y, captured, rookPiece, rookFromX, rookFromY, rookToX, rookToY); + } else { + move = new Move(toMove, x, y, captured); + } + + moveHistory.push(move); turnNumber++; turnWhite = !turnWhite; hasSelection = false; - - Move move = new Move(toMove, x, y, captured); // captured may be null - moveHistory.push(move); System.out.println(this); } } @@ -426,6 +463,8 @@ public boolean isHighlighted(int x, int y) { } } + // KING LOGIC + // KING LOGIC // KING LOGIC if (selected.getType() == PieceType.King) { int[][] directions = { @@ -444,12 +483,66 @@ public boolean isHighlighted(int x, int y) { } } } + + // CASTLING — WHITE + if (isWhite && !whiteKingMoved) { + // Kingside: e1 → g1 + if (x == 6 && y == 7 && + !whiteKingsideRookMoved && + getPieceAt(5, 7) == null && + getPieceAt(6, 7) == null && + getPieceAt(7, 7) != null && + getPieceAt(7, 7).getType() == PieceType.Rook && + getPieceAt(7, 7).isWhite()) { + return true; + } + + // Queenside: e1 → c1 + if (x == 2 && y == 7 && + !whiteQueensideRookMoved && + getPieceAt(1, 7) == null && + getPieceAt(2, 7) == null && + getPieceAt(3, 7) == null && + getPieceAt(0, 7) != null && + getPieceAt(0, 7).getType() == PieceType.Rook && + getPieceAt(0, 7).isWhite()) { + return true; + } + } + + // CASTLING — BLACK + if (!isWhite && !blackKingMoved) { + // Kingside: e8 → g8 + if (x == 6 && y == 0 && + !blackKingsideRookMoved && + getPieceAt(5, 0) == null && + getPieceAt(6, 0) == null && + getPieceAt(7, 0) != null && + getPieceAt(7, 0).getType() == PieceType.Rook && + !getPieceAt(7, 0).isWhite()) { + return true; + } + + // Queenside: e8 → c8 + if (x == 2 && y == 0 && + !blackQueensideRookMoved && + getPieceAt(1, 0) == null && + getPieceAt(2, 0) == null && + getPieceAt(3, 0) == null && + getPieceAt(0, 0) != null && + getPieceAt(0, 0).getType() == PieceType.Rook && + !getPieceAt(0, 0).isWhite()) { + return true; + } + } } return false; } + public void undoLastMove() { + if (moveHistory.isEmpty()) return; // Get the last move from the history @@ -474,8 +567,26 @@ public void undoLastMove() { // Clear selection hasSelection = false; -} + // Revert the extra moved piece (e.g. rook in castling) + if (last.getExtraMovedPiece() != null) { + Piece rook = last.getExtraMovedPiece(); + Pieces.removeIf(p -> p.getX() == last.getExtraToX() && p.getY() == last.getExtraToY()); + Pieces.add(new Piece(last.getExtraFromX(), last.getExtraFromY(), rook.isWhite(), rook.getType())); + // 🛠 Restore castling flags too + if (rook.isWhite()) { + if (last.getExtraFromX() == 0 && last.getExtraFromY() == 7) whiteQueensideRookMoved = false; + if (last.getExtraFromX() == 7 && last.getExtraFromY() == 7) whiteKingsideRookMoved = false; + whiteKingMoved = false; // 👈 Also reset king flag + } else { + if (last.getExtraFromX() == 0 && last.getExtraFromY() == 0) blackQueensideRookMoved = false; + if (last.getExtraFromX() == 7 && last.getExtraFromY() == 0) blackKingsideRookMoved = false; + blackKingMoved = false; // 👈 Also reset king flag + } + } + + +} public Board(Board board) { this.width = board.width; diff --git a/src/backend/Move.java b/src/backend/Move.java index b62286e..93a7b6a 100644 --- a/src/backend/Move.java +++ b/src/backend/Move.java @@ -8,6 +8,9 @@ public class Move { private final int toY; private final Piece movedPiece; private final Piece capturedPiece; + private Piece extraMovedPiece; // the rook + private int extraFromX, extraFromY; + private int extraToX, extraToY; // Constructor for a move (with or without capture) public Move(Piece movedPiece, int toX, int toY, Piece capturedPiece) { @@ -18,6 +21,15 @@ public class Move { this.movedPiece = movedPiece; this.capturedPiece = capturedPiece; } + public Move(Piece movedPiece, int toX, int toY, Piece capturedPiece, + Piece extraMovedPiece, int extraFromX, int extraFromY, int extraToX, int extraToY) { + this(movedPiece, toX, toY, capturedPiece); + this.extraMovedPiece = extraMovedPiece; + this.extraFromX = extraFromX; + this.extraFromY = extraFromY; + this.extraToX = extraToX; + this.extraToY = extraToY; +} // Convenience constructor when there's no capture public Move(Piece movedPiece, int toX, int toY) { @@ -48,4 +60,10 @@ public class Move { public Piece getCapturedPiece() { return capturedPiece; } + public Piece getExtraMovedPiece() { return extraMovedPiece; } + public int getExtraFromX() { return extraFromX; } + public int getExtraFromY() { return extraFromY; } + public int getExtraToX() { return extraToX; } + public int getExtraToY() { return extraToY; } + } diff --git a/src/backend/Piece.java b/src/backend/Piece.java index 40d9369..dc30177 100644 --- a/src/backend/Piece.java +++ b/src/backend/Piece.java @@ -29,5 +29,5 @@ public class Piece { public boolean isWhite() { return isWhite; } - + }