package chess.model.visitor; import chess.model.ChessBoard; import chess.model.Color; import chess.model.Coordinate; import chess.model.Direction; import chess.model.Move; import chess.model.Piece; import chess.model.PieceVisitor; import chess.model.pieces.Bishop; import chess.model.pieces.King; import chess.model.pieces.Knight; import chess.model.pieces.Pawn; import chess.model.pieces.Queen; import chess.model.pieces.Rook; public class PiecePathChecker implements PieceVisitor { private final ChessBoard board; private final Move move; public PiecePathChecker(ChessBoard board, Move move) { this.move = move; this.board = board; } public boolean isValid() { if (this.move.getStart().equals(this.move.getFinish())) return false; Piece piece = this.board.pieceAt(move.getStart()); if (piece == null) return false; return visit(piece); } @Override public Boolean visitPiece(Bishop bishop) { if (!new PermissiveRuleChecker(this.move).isValidFor(bishop)) return false; return testPath(bishop.getColor()); } @Override public Boolean visitPiece(King king) { if (!new PermissiveRuleChecker(this.move).isValidFor(king)) return false; Piece destPiece = board.pieceAt(this.move.getFinish()); if (destPiece == null) return true; return destPiece.getColor() != king.getColor(); } @Override public Boolean visitPiece(Knight knight) { if (!new PermissiveRuleChecker(this.move).isValidFor(knight)) return false; Piece destPiece = board.pieceAt(this.move.getFinish()); if (destPiece == null) return true; return destPiece.getColor() != knight.getColor(); } @Override public Boolean visitPiece(Pawn pawn) { if (!new PermissiveRuleChecker(this.move).isValidFor(pawn)) return false; Direction moveDirection = Direction.fromInt(Direction.findDirection(move).getIndexOffset() * pawn.multiplier()); if (moveDirection == Direction.Front) return testPath(pawn.getColor()) && this.board.pieceAt(this.move.getFinish()) == null; assert moveDirection == Direction.FrontLeft || moveDirection == Direction.FrontRight; Piece destPiece = this.board.pieceAt(this.move.getFinish()); if (destPiece == null) return false; return destPiece.getColor() != pawn.getColor(); } @Override public Boolean visitPiece(Queen queen) { if (!new PermissiveRuleChecker(this.move).isValidFor(queen)) return false; return testPath(queen.getColor()); } @Override public Boolean visitPiece(Rook rook) { if (!new PermissiveRuleChecker(this.move).isValidFor(rook)) return false; return testPath(rook.getColor()); } private boolean testPath(Color color) { Direction moveDirection = Direction.findDirection(this.move); int distance = this.move.traversedCells(); int stepIndex = move.getStart().toIndex(); for (int step = 0; step < distance; step++) { stepIndex += moveDirection.getIndexOffset(); if (Coordinate.fromIndex(stepIndex).equals(move.getFinish())) { Piece pieceDest = this.board.pieceAt(move.getFinish()); if (pieceDest == null) return true; return pieceDest.getColor() != color; } if (!this.board.isCellEmpty(Coordinate.fromIndex(stepIndex))) return false; } return false; } }