en passant rule
This commit is contained in:
@@ -3,5 +3,12 @@ package chess.controller;
|
|||||||
import chess.model.Game;
|
import chess.model.Game;
|
||||||
|
|
||||||
public abstract class PlayerCommand extends Command{
|
public abstract class PlayerCommand extends Command{
|
||||||
public abstract CommandResult undo(Game game, OutputSystem outputSystem);
|
|
||||||
|
public CommandResult undo(Game game, OutputSystem outputSystem) {
|
||||||
|
CommandResult result = undoImpl(game, outputSystem);
|
||||||
|
game.updateLastMove();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract CommandResult undoImpl(Game game, OutputSystem outputSystem);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class CastlingCommand extends PlayerCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandResult undo(Game game, OutputSystem outputSystem) {
|
protected CommandResult undoImpl(Game game, OutputSystem outputSystem) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'undo'");
|
throw new UnsupportedOperationException("Unimplemented method 'undo'");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class GrandCastlingCommand extends PlayerCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandResult undo(Game game, OutputSystem outputSystem) {
|
protected CommandResult undoImpl(Game game, OutputSystem outputSystem) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'undo'");
|
throw new UnsupportedOperationException("Unimplemented method 'undo'");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import chess.model.Piece;
|
|||||||
import chess.model.visitor.PiecePathChecker;
|
import chess.model.visitor.PiecePathChecker;
|
||||||
|
|
||||||
public class MoveCommand extends PlayerCommand {
|
public class MoveCommand extends PlayerCommand {
|
||||||
|
|
||||||
private final Move move;
|
private final Move move;
|
||||||
private Piece deadPiece;
|
private Piece deadPiece;
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ public class MoveCommand extends PlayerCommand {
|
|||||||
if (!valid)
|
if (!valid)
|
||||||
return CommandResult.NotAllowed;
|
return CommandResult.NotAllowed;
|
||||||
|
|
||||||
this.deadPiece = board.pieceAt(move.getFinish());
|
this.deadPiece = board.pieceAt(move.getDeadPieceCoords());
|
||||||
board.applyMove(move);
|
board.applyMove(move);
|
||||||
|
|
||||||
if (board.isKingInCheck(game.getPlayerTurn())) {
|
if (board.isKingInCheck(game.getPlayerTurn())) {
|
||||||
@@ -50,14 +50,15 @@ public class MoveCommand extends PlayerCommand {
|
|||||||
return CommandResult.NotAllowed;
|
return CommandResult.NotAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game.pawnShouldBePromoted())
|
if (game.pawnShouldBePromoted())
|
||||||
return CommandResult.ActionNeeded;
|
return CommandResult.ActionNeeded;
|
||||||
|
|
||||||
|
board.setLastMove(this.move);
|
||||||
return CommandResult.Moved;
|
return CommandResult.Moved;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandResult undo(Game game, OutputSystem outputSystem) {
|
protected CommandResult undoImpl(Game game, OutputSystem outputSystem) {
|
||||||
final ChessBoard board = game.getBoard();
|
final ChessBoard board = game.getBoard();
|
||||||
|
|
||||||
board.undoMove(move, deadPiece);
|
board.undoMove(move, deadPiece);
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public class PromoteCommand extends PlayerCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandResult undo(Game game, OutputSystem outputSystem) {
|
protected CommandResult undoImpl(Game game, OutputSystem outputSystem) {
|
||||||
final ChessBoard board = game.getBoard();
|
final ChessBoard board = game.getBoard();
|
||||||
|
|
||||||
Piece promoted = board.pieceAt(this.pieceCoords);
|
Piece promoted = board.pieceAt(this.pieceCoords);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ public class ChessBoard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Cell[][] cells;
|
private final Cell[][] cells;
|
||||||
|
private Move lastVirtualMove;
|
||||||
private Move lastMove;
|
private Move lastMove;
|
||||||
private Piece lastEjectedPiece;
|
private Piece lastEjectedPiece;
|
||||||
|
|
||||||
@@ -35,35 +36,38 @@ public class ChessBoard {
|
|||||||
this.cells[i][j] = new Cell();
|
this.cells[i][j] = new Cell();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.lastVirtualMove = null;
|
||||||
this.lastMove = null;
|
this.lastMove = null;
|
||||||
this.lastEjectedPiece = null;
|
this.lastEjectedPiece = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyMove(Move move) {
|
public void applyMove(Move move) {
|
||||||
assert move.isValid() : "Invalid move !";
|
assert move.isValid() : "Invalid move !";
|
||||||
Piece deadPiece = pieceAt(move.getFinish());
|
Piece deadPiece = pieceAt(move.getDeadPieceCoords());
|
||||||
if (deadPiece != null) {
|
if (deadPiece != null) {
|
||||||
this.lastEjectedPiece = deadPiece;
|
this.lastEjectedPiece = deadPiece;
|
||||||
} else {
|
} else {
|
||||||
this.lastEjectedPiece = null;
|
this.lastEjectedPiece = null;
|
||||||
}
|
}
|
||||||
Piece movingPiece = pieceAt(move.getStart());
|
Piece movingPiece = pieceAt(move.getStart());
|
||||||
pieceComes(movingPiece, move.getFinish());
|
pieceLeaves(move.getDeadPieceCoords());
|
||||||
pieceLeaves(move.getStart());
|
pieceLeaves(move.getStart());
|
||||||
|
pieceComes(movingPiece, move.getFinish());
|
||||||
movingPiece.move();
|
movingPiece.move();
|
||||||
this.lastMove = move;
|
this.lastVirtualMove = move;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void undoLastMove() {
|
public void undoLastMove() {
|
||||||
assert this.lastMove != null: "Can't undo at the beginning!";
|
assert this.lastVirtualMove != null: "Can't undo at the beginning!";
|
||||||
|
|
||||||
undoMove(this.lastMove, this.lastEjectedPiece);
|
undoMove(this.lastVirtualMove, this.lastEjectedPiece);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void undoMove(Move move, Piece deadPiece) {
|
public void undoMove(Move move, Piece deadPiece) {
|
||||||
Piece movingPiece = pieceAt(move.getFinish());
|
Piece movingPiece = pieceAt(move.getFinish());
|
||||||
pieceComes(movingPiece, move.getStart());
|
pieceComes(movingPiece, move.getStart());
|
||||||
pieceComes(deadPiece, move.getFinish());
|
pieceLeaves(move.getFinish());
|
||||||
|
pieceComes(deadPiece, move.getDeadPieceCoords());
|
||||||
movingPiece.unMove();
|
movingPiece.unMove();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,4 +181,12 @@ public class ChessBoard {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Move getLastMove() {
|
||||||
|
return this.lastMove;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastMove(Move lastMove) {
|
||||||
|
this.lastMove = lastMove;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import java.util.EmptyStackException;
|
|||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
import chess.controller.PlayerCommand;
|
import chess.controller.PlayerCommand;
|
||||||
|
import chess.controller.commands.MoveCommand;
|
||||||
import chess.model.visitor.PawnIdentifier;
|
import chess.model.visitor.PawnIdentifier;
|
||||||
|
|
||||||
public class Game {
|
public class Game {
|
||||||
@@ -99,4 +100,14 @@ public class Game {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateLastMove() {
|
||||||
|
if (this.movesHistory.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
PlayerCommand last = this.movesHistory.getLast();
|
||||||
|
if (last instanceof MoveCommand move) {
|
||||||
|
this.board.setLastMove(move.getMove());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ package chess.model;
|
|||||||
public class Move {
|
public class Move {
|
||||||
private final Coordinate start;
|
private final Coordinate start;
|
||||||
private final Coordinate finish;
|
private final Coordinate finish;
|
||||||
|
private Coordinate deadPieceCoords;
|
||||||
|
|
||||||
public Move(Coordinate start, Coordinate finish) {
|
public Move(Coordinate start, Coordinate finish) {
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.finish = finish;
|
this.finish = finish;
|
||||||
|
this.deadPieceCoords = finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
@@ -39,4 +41,16 @@ public class Move {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Coordinate getMiddle() {
|
||||||
|
return Coordinate.fromIndex((getStart().toIndex() + getFinish().toIndex()) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeadPieceCoords(Coordinate deadCoords) {
|
||||||
|
this.deadPieceCoords = deadCoords;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Coordinate getDeadPieceCoords() {
|
||||||
|
return deadPieceCoords;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,31 +35,27 @@ public class PiecePathChecker implements PieceVisitor<Boolean> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean visitPiece(Bishop bishop) {
|
public Boolean visitPiece(Bishop bishop) {
|
||||||
if (!new PermissiveRuleChecker(this.move).isValidFor(bishop))
|
return basicCheck(bishop);
|
||||||
return false;
|
|
||||||
return testPath(bishop.getColor());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean visitPiece(King king) {
|
public Boolean visitPiece(King king) {
|
||||||
if (!new PermissiveRuleChecker(this.move).isValidFor(king))
|
return destCheck(king);
|
||||||
return false;
|
|
||||||
|
|
||||||
Piece destPiece = board.pieceAt(this.move.getFinish());
|
|
||||||
if (destPiece == null)
|
|
||||||
return true;
|
|
||||||
return destPiece.getColor() != king.getColor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean visitPiece(Knight knight) {
|
public Boolean visitPiece(Knight knight) {
|
||||||
if (!new PermissiveRuleChecker(this.move).isValidFor(knight))
|
return destCheck(knight);
|
||||||
return false;
|
}
|
||||||
|
|
||||||
Piece destPiece = board.pieceAt(this.move.getFinish());
|
@Override
|
||||||
if (destPiece == null)
|
public Boolean visitPiece(Queen queen) {
|
||||||
return true;
|
return basicCheck(queen);
|
||||||
return destPiece.getColor() != knight.getColor();
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean visitPiece(Rook rook) {
|
||||||
|
return basicCheck(rook);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -74,6 +70,9 @@ public class PiecePathChecker implements PieceVisitor<Boolean> {
|
|||||||
|
|
||||||
assert moveDirection == Direction.FrontLeft || moveDirection == Direction.FrontRight;
|
assert moveDirection == Direction.FrontLeft || moveDirection == Direction.FrontRight;
|
||||||
|
|
||||||
|
if (checkEnPassant())
|
||||||
|
return true;
|
||||||
|
|
||||||
Piece destPiece = this.board.pieceAt(this.move.getFinish());
|
Piece destPiece = this.board.pieceAt(this.move.getFinish());
|
||||||
if (destPiece == null)
|
if (destPiece == null)
|
||||||
return false;
|
return false;
|
||||||
@@ -81,18 +80,44 @@ public class PiecePathChecker implements PieceVisitor<Boolean> {
|
|||||||
return destPiece.getColor() != pawn.getColor();
|
return destPiece.getColor() != pawn.getColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private boolean checkEnPassant() {
|
||||||
public Boolean visitPiece(Queen queen) {
|
Move lastMove = this.board.getLastMove();
|
||||||
if (!new PermissiveRuleChecker(this.move).isValidFor(queen))
|
|
||||||
|
if (lastMove == null)
|
||||||
return false;
|
return false;
|
||||||
return testPath(queen.getColor());
|
|
||||||
|
Piece pieceToEat = this.board.pieceAt(lastMove.getFinish());
|
||||||
|
|
||||||
|
if (pieceToEat == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Piece pawn = this.board.pieceAt(this.move.getStart());
|
||||||
|
|
||||||
|
if (pieceToEat.getColor() == pawn.getColor())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (lastMove.getMiddle().equals(this.move.getFinish())
|
||||||
|
&& new PawnIdentifier(pieceToEat.getColor()).isPawn(pieceToEat)) {
|
||||||
|
this.move.setDeadPieceCoords(lastMove.getFinish());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private boolean destCheck(Piece piece) {
|
||||||
public Boolean visitPiece(Rook rook) {
|
if (!new PermissiveRuleChecker(this.move).isValidFor(piece))
|
||||||
if (!new PermissiveRuleChecker(this.move).isValidFor(rook))
|
|
||||||
return false;
|
return false;
|
||||||
return testPath(rook.getColor());
|
|
||||||
|
Piece destPiece = board.pieceAt(this.move.getFinish());
|
||||||
|
if (destPiece == null)
|
||||||
|
return true;
|
||||||
|
return destPiece.getColor() != piece.getColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean basicCheck(Piece piece) {
|
||||||
|
if (!new PermissiveRuleChecker(this.move).isValidFor(piece))
|
||||||
|
return false;
|
||||||
|
return testPath(piece.getColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean testPath(Color color) {
|
private boolean testPath(Color color) {
|
||||||
|
|||||||
Reference in New Issue
Block a user