package ch.epfl.maze.physical.zoo; import ch.epfl.maze.physical.Animal; import ch.epfl.maze.util.Direction; import ch.epfl.maze.util.Vector2D; import java.util.Set; /** * Bear A.I. that implements the Pledge Algorithm. * * @author EPFL * @author Pacien TRAN-GIRARD */ public class Bear extends Animal { private Direction favoriteDirection; private Direction currentDirection; private int rightRotationCounter; /** * Constructs a bear with a starting position. * * @param position Starting position of the bear in the labyrinth */ public Bear(Vector2D position) { super(position); this.favoriteDirection = Direction.NONE; this.currentDirection = Direction.NONE; this.rightRotationCounter = 0; } /** * Checks if the Bear is currently trying to bypass an obstacle. * * @return T(The Bear is bypassing an obstacle) */ private boolean isBypassingObstacle() { return this.rightRotationCounter != 0; } /** * Returns the preferred Direction to take according to the current strategy. * * @return The preferred Direction */ private Direction getPreferredDir() { return this.isBypassingObstacle() ? this.currentDirection.rotateLeft() : this.favoriteDirection; } /** * Finds a currentDirection following the "left paw rule". * * @param choices A set of possible directions * @return The currentDirection to take according to the "left paw rule" */ private Direction followLeft(Set choices) { if (choices.isEmpty()) return Direction.NONE; if (choices.size() == 1) return choices.stream().findAny().get(); Direction dir = this.getPreferredDir(); while (!choices.contains(dir)) dir = dir.rotateRight(); return dir; } /** * Moves according to the Pledge Algorithm : the bear tries to move * towards a favorite direction until it hits a wall. In this case, it will * turn right, put its paw on the left wall, count the number of times it * turns right, and subtract to this the number of times it turns left. It * will repeat the procedure when the counter comes to zero, or until it * leaves the maze. */ @Override public Direction move(Set choices) { if (this.favoriteDirection == Direction.NONE) this.favoriteDirection = choices.stream().findAny().get(); Direction newDirection = this.followLeft(choices); if (this.currentDirection.reverse() == newDirection) this.rightRotationCounter += 2; else if (this.currentDirection.rotateRight() == newDirection) this.rightRotationCounter += 1; else if (this.currentDirection.rotateLeft() == newDirection) this.rightRotationCounter -= 1; this.currentDirection = newDirection; return this.currentDirection; } @Override public Animal copy() { return new Monkey(this.getPosition()); } }