package ch.epfl.maze.physical.zoo; import ch.epfl.maze.physical.Animal; import ch.epfl.maze.physical.stragegies.picker.CyclePicker; import ch.epfl.maze.physical.stragegies.picker.SimplePicker; 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 implements SimplePicker, CyclePicker { public static final Direction SMART_PAW = Direction.LEFT; private Direction favoriteDirection; private int rotationCounter; /** * 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.rotationCounter = 0; } /** * Returns the preferred Direction to take according to the current strategy. * * @return The preferred Direction */ @Override public Direction getStartingDirection() { if (this.isBypassingObstacle()) return this.getDirection().unRelativeDirection(Bear.SMART_PAW); else return this.favoriteDirection; } @Override public Direction getRotationDirection() { return Bear.SMART_PAW.reverse(); } /** * Preferably picks the Bear's favorite Direction, * or a Direction following the "paw rule" if bypassing an obstacle, * or any available Direction if the Bear has no preference yet. * * @param choices A set of Direction choices * @return The picked Direction */ @Override public Direction pick(Set choices) { if (this.getDirection() == Direction.NONE) return SimplePicker.super.pick(choices); else if (!choices.contains(this.getDirection()) || this.isBypassingObstacle()) return CyclePicker.super.pick(choices); else return this.favoriteDirection; } /** * 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 = this.getDirection(); Direction dir = this.pick(choices); this.rotationCounter += this.countRotations(dir); return dir; } @Override public Animal copy() { return new Monkey(this.getPosition()); } /** * Checks whether the Bear is currently trying to bypass an obstacle. * * @return T(The Bear is bypassing an obstacle) */ private boolean isBypassingObstacle() { return this.rotationCounter != 0; } }