Castling Done

This commit is contained in:
jefei 2025-05-16 19:40:51 +02:00
parent b20a1a1c9c
commit 2bf326eae2
4 changed files with 171 additions and 33 deletions

9
saved101 Normal file
View File

@ -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

View File

@ -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;
}
}
// 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);
// 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,9 +567,27 @@ 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;
this.height = board.height;

View File

@ -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; }
}