add castling + fix promote undo

This commit is contained in:
2025-04-06 12:33:00 +02:00
parent a2224cf618
commit 6cb1dd826f
5 changed files with 92 additions and 35 deletions

View File

@@ -2,23 +2,62 @@ package chess.controller.commands;
import chess.controller.OutputSystem;
import chess.controller.PlayerCommand;
import chess.model.ChessBoard;
import chess.model.Color;
import chess.model.Coordinate;
import chess.model.Game;
import chess.model.Move;
public class CastlingCommand extends PlayerCommand {
private Move kingMove;
private Move rookMove;
private final boolean bigCastling;
public CastlingCommand(boolean bigCastling) {
this.bigCastling = bigCastling;
}
@Override
public CommandResult execute(Game game, OutputSystem outputSystem) {
// we must promote the pending pawn before
if (game.pawnShouldBePromoted())
return CommandResult.NotAllowed;
return CommandResult.NotAllowed;
final ChessBoard board = game.getBoard();
if (bigCastling && !board.canBigCastle(game.getPlayerTurn()))
return CommandResult.NotAllowed;
if (!bigCastling && !board.canSmallCastle(game.getPlayerTurn()))
return CommandResult.NotAllowed;
int rookBeginX = bigCastling ? 0 : 7;
int rookEndX = bigCastling ? 3 : 5;
int kingBeginX = 4;
int kingEndX = bigCastling ? 2 : 6;
int colorLine = game.getPlayerTurn() == Color.White ? 7 : 0;
Coordinate kingCoords = new Coordinate(kingBeginX, colorLine);
Coordinate rookCoords = new Coordinate(rookBeginX, colorLine);
this.kingMove = new Move(kingCoords, new Coordinate(kingEndX, colorLine));
this.rookMove = new Move(rookCoords, new Coordinate(rookEndX, colorLine));
board.applyMove(this.kingMove);
board.applyMove(this.rookMove);
return CommandResult.Moved;
}
@Override
protected CommandResult undoImpl(Game game, OutputSystem outputSystem) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'undo'");
game.getBoard().undoMove(this.kingMove, null);
game.getBoard().undoMove(this.rookMove, null);
return CommandResult.Moved;
}
}

View File

@@ -1,24 +0,0 @@
package chess.controller.commands;
import chess.controller.OutputSystem;
import chess.controller.PlayerCommand;
import chess.model.Game;
public class GrandCastlingCommand extends PlayerCommand {
@Override
public CommandResult execute(Game game, OutputSystem outputSystem) {
// we must promote the pending pawn before
if (game.pawnShouldBePromoted())
return CommandResult.NotAllowed;
return CommandResult.NotAllowed;
}
@Override
protected CommandResult undoImpl(Game game, OutputSystem outputSystem) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'undo'");
}
}

View File

@@ -9,7 +9,6 @@ import chess.model.Game;
import chess.model.Piece;
import chess.model.pieces.Bishop;
import chess.model.pieces.Knight;
import chess.model.pieces.Pawn;
import chess.model.pieces.Queen;
import chess.model.pieces.Rook;
import chess.model.visitor.PawnIdentifier;
@@ -25,9 +24,12 @@ public class PromoteCommand extends PlayerCommand {
private final PromoteType promoteType;
private Coordinate pieceCoords;
private Piece oldPawn;
public PromoteCommand(PromoteType promoteType) {
this.promoteType = promoteType;
this.pieceCoords = null;
this.oldPawn = null;
}
@Override
@@ -50,6 +52,7 @@ public class PromoteCommand extends PlayerCommand {
if (destY != enemyLine)
return CommandResult.NotAllowed;
this.oldPawn = pawn;
board.pieceComes(createPiece(this.promoteType, pawn.getColor()), this.pieceCoords);
return CommandResult.Moved;
@@ -82,10 +85,11 @@ public class PromoteCommand extends PlayerCommand {
assert promoted != null;
Color player = promoted.getColor();
board.pieceComes(new Pawn(player), this.pieceCoords);
board.pieceComes(this.oldPawn, this.pieceCoords);
return CommandResult.ActionNeeded;
game.getLastAction().undo(game, outputSystem);
return CommandResult.Moved;
}
}

View File

@@ -58,7 +58,7 @@ public class ChessBoard {
}
public void undoLastMove() {
assert this.lastVirtualMove != null: "Can't undo at the beginning!";
assert this.lastVirtualMove != null : "Can't undo at the beginning!";
undoMove(this.lastVirtualMove, this.lastEjectedPiece);
}
@@ -181,6 +181,45 @@ public class ChessBoard {
return result;
}
private boolean canCastle(Color color, int rookX, Direction kingDirection) {
if (isKingInCheck(color))
return false;
int colorLine = color == Color.White ? 7 : 0;
Coordinate kingCoords = new Coordinate(4, colorLine);
Coordinate rookCoords = new Coordinate(rookX, colorLine);
Piece king = pieceAt(kingCoords);
Piece rook = pieceAt(rookCoords);
if (king == null || rook == null || king.hasMoved() || rook.hasMoved())
return false;
for (int step = 1; step <= 2; step++) {
Coordinate dest = Coordinate.fromIndex(kingCoords.toIndex() + step * kingDirection.getIndexOffset());
Piece obstacle = pieceAt(dest);
if (obstacle != null)
return false;
applyMove(new Move(kingCoords, dest));
if (isKingInCheck(color)) {
undoLastMove();
return false;
}
undoLastMove();
}
return true;
}
public boolean canSmallCastle(Color color) {
return canCastle(color, 7, Direction.Right);
}
public boolean canBigCastle(Color color) {
return canCastle(color, 0, Direction.Left);
}
public Move getLastMove() {
return this.lastMove;
}

View File

@@ -20,7 +20,6 @@ import chess.controller.OutputSystem;
import chess.controller.commands.CastlingCommand;
import chess.controller.commands.GetAllowedMovesCommand;
import chess.controller.commands.GetPieceAtCommand;
import chess.controller.commands.GrandCastlingCommand;
import chess.controller.commands.MoveCommand;
import chess.controller.commands.PromoteCommand;
import chess.controller.commands.PromoteCommand.PromoteType;
@@ -61,11 +60,11 @@ public class Window extends JFrame implements OutputSystem {
private void buildButtons(JPanel bottom) {
castlingButton.addActionListener((event) -> {
sendCommand(new CastlingCommand());
sendCommand(new CastlingCommand(false));
});
bigCastlingButton.addActionListener((event) -> {
sendCommand(new GrandCastlingCommand());
sendCommand(new CastlingCommand(true));
});
undoButton.addActionListener((event) -> {