Average Density: 0.04
  1 package nl.tudelft.jpacman.npc.ghost;
  2 
  3 import java.util.List;
  4 import java.util.Map;
  5 import java.util.Optional;
  6 
  7 import nl.tudelft.jpacman.board.Direction;
  8 import nl.tudelft.jpacman.board.Square;
  9 import nl.tudelft.jpacman.board.Unit;
 10 import nl.tudelft.jpacman.level.Player;
 11 import nl.tudelft.jpacman.npc.Ghost;
 12 import nl.tudelft.jpacman.sprite.Sprite;
 13 
 14 /**
 15  * <p>
 16  * An implementation of the classic Pac-Man ghost Shadow.
 17  * </p>
 18  * <p>
 19  * Nickname: Blinky. As his name implies, Shadow is usually a constant shadow on
 20  * Pac-Man's tail. When he's not patrolling the top-right corner of the maze,
 21  * Shadow tries to find the quickest route to Pac-Man's position. Despite the
 22  * fact that Pinky's real name is Speedy, Shadow is actually the fastest of the
 23  * ghosts because of when there are only a few pellets left, Blinky drastically
 24  * speeds up, which can make him quite deadly. In the original Japanese version,
 25  * his name is Oikake/Akabei.
 26  * </p>
 27  * <p>
 28  * <b>AI:</b> When the ghosts are not patrolling in their home corners (Blinky:
 29  * top-right, Pinky: top-left, Inky: bottom-right, Clyde: bottom-left), Blinky
 30  * will attempt to shorten the distance between Pac-Man and himself. If he has
 31  * to choose between shortening the horizontal or vertical distance, he will
 32  * choose to shorten whichever is greatest. For example, if Pac-Man is four grid
 33  * spaces to the left, and seven grid spaces above Blinky, he'll try to move up
 34  * towards Pac-Man before he moves to the left.
 35  * </p>
 36  * <p>
 37  * Source: http://strategywiki.org/wiki/Pac-Man/Getting_Started
 38  * </p>
 39  *
 40  * @author Jeroen Roosen 
 41  *
 42  */
 43 public class Blinky extends Ghost {
 44 
 45     /**
 46      * The variation in intervals, this makes the ghosts look more dynamic and
 47      * less predictable.
 48      */
 49     private static final int INTERVAL_VARIATION = 50;
 50 
 51     /**
 52      * The base movement interval.
 53      */
 54     private static final int MOVE_INTERVAL = 250;
 55 
 56     /**
 57      * Creates a new "Blinky", a.k.a. "Shadow".
 58      *
 59      * @param spriteMap
 60      *            The sprites for this ghost.
 61      */
 62     // TODO Blinky should speed up when there are a few pellets left, but he
 63     // has no way to find out how many there are.
 64     public Blinky(Map<Direction, Sprite> spriteMap) {
 65         super(spriteMap, MOVE_INTERVAL, INTERVAL_VARIATION);
 66     }
 67 
 68     /**
 69      * {@inheritDoc}
 70      *
 71      * <p>
 72      * When the ghosts are not patrolling in their home corners (Blinky:
 73      * top-right, Pinky: top-left, Inky: bottom-right, Clyde: bottom-left),
 74      * Blinky will attempt to shorten the distance between Pac-Man and himself.
 75      * If he has to choose between shortening the horizontal or vertical
 76      * distance, he will choose to shorten whichever is greatest. For example,
 77      * if Pac-Man is four grid spaces to the left, and seven grid spaces above
 78      * Blinky, he'll try to move up towards Pac-Man before he moves to the left.
 79      * </p>
 80      */
 81     @Override
 82     public Optional<Direction> nextAiMove() {
 83         assert hasSquare();
 84 
 85         // TODO Blinky should patrol his corner every once in a while
 86         // TODO Implement his actual behaviour instead of simply chasing.
 87         Unit nearest = Navigation.findNearest(Player.class, getSquare());
 88         if (nearest == null) {
 89             return Optional.empty();
 90         }
 91         assert nearest.hasSquare();
 92         Square target = nearest.getSquare();
 93 
 94         List<Direction> path = Navigation.shortestPath(getSquare(), target, this);
 95         if (path != null && !path.isEmpty()) {
 96             return Optional.ofNullable(path.get(0));
 97         }
 98         return Optional.empty();
 99     }
100 }