public void undoLastMove() { // Check that we have a move to undo if (moves.isEmpty()) { throw new InternalError("No move available to undo"); } final Move lastMove = getLastMove(); final Point from = lastMove.getFrom(); final Point to = lastMove.getTo(); final Piece piece = lastMove.getPiece(); squares[from.getX()][from.getY()].setPiece(piece); if (lastMove.isLeftCastling()) { squares[to.getX()][to.getY()].setPiece(null); if (piece.getColor() == Color.W) { setPiece(Piece.WHITE_ROOK, King.W_LEFT_ROOK); setPiece(null, to.incrementX(1)); } else { setPiece(Piece.BLACK_ROOK, King.B_LEFT_ROOK); setPiece(null, to.incrementX(1)); } } else if (lastMove.isRightCastling()) { squares[to.getX()][to.getY()].setPiece(null); if (piece.getColor() == Color.W) { setPiece(Piece.WHITE_ROOK, King.W_RIGHT_ROOK); setPiece(null, to.decrementX(1)); } else { setPiece(Piece.BLACK_ROOK, King.B_RIGHT_ROOK); setPiece(null, to.decrementX(1)); } } else { final Piece captured = lastMove.getCaptured(); // Undoing an en passant move? if (lastMove.isEnPassant()) { if (captured.getColor() == Color.B) { squares[to.getX()][to.getY() - 1].setPiece(captured); } else { squares[to.getX()][to.getY() + 1].setPiece(captured); } squares[to.getX()][to.getY()].setPiece(null); } else { squares[to.getX()][to.getY()].setPiece(captured); } // Keep track of the kings if (piece == WHITE_KING) { whiteKing = squares[from.getX()][from.getY()]; } else if (piece == BLACK_KING) { blackKing = squares[from.getX()][from.getY()]; } } // Remove move from history moves.remove(moves.size() - 1); }