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 }