package escape.validation; import escape.Board; import escape.enumerations.LocationType; import escape.enumerations.Player; import escape.exception.EscapeException; import escape.util.GamePiece; import escape.util.Location; import static escape.interfaces.EscapePiece.PieceAttributeID.*; public class MoveValidator { public boolean isValid(Board board, Location from, Location to, Player player, boolean remove) throws EscapeException{ return pieceExists(board, from, to) && isOwned(board, from, player) && withinBounds(board, from, to) && validDest(board,from, to, remove) && inRange(board, from, to); } /** * Checks that there is a piece at a point and that we are not moving in place * * @param board * @param from * @param to * @return true if piece exists and we are moving. * @throws EscapeException */ private boolean pieceExists(Board board, Location from, Location to) throws EscapeException{ if ((from.getX() != to.getX() || from.getY() != to.getY()) && board.pieceAt(from) != null) { return true; } if(!(from.getX() != to.getX() || from.getY() != to.getY())){ throw new EscapeException("Cannot move in place"); } if(board.pieceAt(from) == null){ throw new EscapeException("There is no piece on this space"); } return false; } /** * Checks for ownership of a piece at the given location * @param board * @param from * @param player * @return true if owned * @throws EscapeException */ private boolean isOwned(Board board, Location from, Player player) throws EscapeException{ Player owner = board.pieceAt(from).getPlayer(); if(owner == null || owner != player){ throw new EscapeException("This piece is not owned by the current player"); } return true; } /** * Checks that our move stays within the board bounds * I wrote this before I remembered that we don't have to check for it * @param board * @param from * @param to * @return true if in bounds, false otherwise * @throws EscapeException */ private boolean withinBounds(Board board, Location from, Location to) throws EscapeException{ boolean fromIn = false; boolean toIn = false; switch (board.getBoardType()) { case SQUARE: fromIn = (from.getX() <= board.getMaxX() && from.getX() > 0) && (from.getY() <= board.getMaxY() && from.getY() > 0); toIn = (to.getX() <= board.getMaxX() && to.getX() > 0) && (to.getY() <= board.getMaxY() && to.getY() > 0); break; case HEX: fromIn = (from.getX() <= board.getMaxX() && from.getX() >= (-1 * board.getMaxX())) && (from.getY() <= board.getMaxY() && from.getY() >= (-1 * board.getMaxY())); toIn = (from.getX() <= board.getMaxX() && from.getX() >= (-1 * board.getMaxX())) && (from.getY() <= board.getMaxY() && from.getY() >= (-1 * board.getMaxY())); break; } if(!(fromIn && toIn)){ throw new EscapeException("Out of bounds"); } return true; } /** * Asks PathFinder if a path exists that is in the Piece's range. * @param board * @param from * @param to * @return true if 'to' is in range, false otherwise * @throws EscapeException */ private boolean inRange(Board board, Location from, Location to) throws EscapeException{ PathFinder pathFinder = new PathFinder(); if(!pathFinder.getPath(board, from, to)){ throw new EscapeException("No path available"); } return true; } /** * Checks if the destination is valid (not occupied by a piece or block) * If destination has a piece, only valid if remove is active * @param board * @param to * @return true if destination is valid, false otherwise * @throws EscapeException */ private boolean validDest(Board board, Location from, Location to, boolean removeActive) throws EscapeException{ GamePiece piece = board.pieceAt(to); Player owner = board.pieceAt(from).getPlayer(); LocationType type = board.getLocationType(to); if(type == LocationType.BLOCK){ throw new EscapeException("Cannot land on Block locations"); } else if((piece != null && owner!= null) && piece.getPlayer() != owner && removeActive){ return true; } if(piece != null){ throw new EscapeException("Cannot land on a piece"); } else return true; } }