package chess.model.rules; 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; /** * Check if a move can be done. */ public class PermissiveRuleChecker implements PieceVisitor { private final Move move; public PermissiveRuleChecker(Move move) { this.move = move; assert move.isValid() : "Move is invalid!"; } public boolean isValidFor(Piece piece) { return visit(piece); } @Override public Boolean visitPiece(Bishop bishop) { Direction moveDirection = Direction.findDirection(this.move); switch (moveDirection) { case FrontLeft: case BackLeft: case FrontRight: case BackRight: return true; default: return false; } } @Override public Boolean visitPiece(King king) { return this.move.traversedCells() == 1; } @Override public Boolean visitPiece(Knight knight) { Coordinate piecePos = move.getStart(); final Coordinate[] positions = { new Coordinate(piecePos.getX() - 1, piecePos.getY() - 2), new Coordinate(piecePos.getX() - 1, piecePos.getY() + 2), new Coordinate(piecePos.getX() + 1, piecePos.getY() - 2), new Coordinate(piecePos.getX() + 1, piecePos.getY() + 2), new Coordinate(piecePos.getX() + 2, piecePos.getY() - 1), new Coordinate(piecePos.getX() + 2, piecePos.getY() + 1), new Coordinate(piecePos.getX() - 2, piecePos.getY() - 1), new Coordinate(piecePos.getX() - 2, piecePos.getY() + 1), }; for (int i = 0; i < positions.length; i++) { if (this.move.getFinish().equals(positions[i])) return true; } return false; } @Override public Boolean visitPiece(Pawn pawn) { Direction moveDirection = Direction.findDirection(this.move); int directionIndexOffset = moveDirection.getIndexOffset(); int distance = this.move.traversedCells(); // Revoke moving backwards if (directionIndexOffset * pawn.multiplier() > 0) return false; // Allowing straight moves if (Math.abs(directionIndexOffset) == Math.abs(Direction.Front.getIndexOffset())) { if (pawn.hasMoved()) return distance == 1; return distance == 1 || distance == 2; } // Allowing small diagonal moves if (directionIndexOffset * pawn.multiplier() == Direction.FrontLeft.getIndexOffset() || directionIndexOffset * pawn.multiplier() == Direction.FrontRight.getIndexOffset()) { return distance == 1; } return false; } @Override public Boolean visitPiece(Queen queen) { Direction moveDirection = Direction.findDirection(this.move); return moveDirection != Direction.Unset; } @Override public Boolean visitPiece(Rook rook) { Direction moveDirection = Direction.findDirection(this.move); switch (moveDirection) { case Front: case Back: case Left: case Right: return true; default: return false; } } }