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 Speedy.
17 * </p>
18 * <p>
19 * Nickname: Pinky. Speedy gets his name for an unusual reason. Speedy appears
20 * to try to outsmart Pac-Man and crash into Pac-Man from the opposite
21 * direction. The truth behind this is that when Speedy isn't patrolling the
22 * top-left corner of the maze, he tries to attack Pac-Man by moving to where he
23 * is going to be (that is, a few spaces ahead of Pac-Man's current direction)
24 * instead of right where he is, as Blinky does. It's difficult to use this to
25 * your advantage, but it's possible. If Pinky is coming at you and you face a
26 * different direction, even briefly, he may just turn away and attempt to cut
27 * you off in the new direction while you return to your original direction. In
28 * the original Japanese version, his name is Machibuse/Pinky.
29 * </p>
30 * <p>
31 * <b>AI:</b> When the ghosts are not patrolling their home corners, Pinky wants
32 * to go to the place that is four grid spaces ahead of Pac-Man in the direction
33 * that Pac-Man is facing. If Pac-Man is facing down, Pinky wants to go to the
34 * location exactly four spaces below Pac-Man. Moving towards this place uses
35 * the same logic that Blinky uses to find Pac-Man's exact location. Pinky is
36 * affected by a targeting bug if Pac-Man is facing up - when he moves or faces
37 * up, Pinky tries moving towards a point up, and left, four spaces.
38 * </p>
39 * <p>
40 * <i>Note: In the original arcade series, the ghosts' genders are unspecified
41 * and assumed to be male. In 1999, the USA division of Namco and Namco Hometech
42 * developed the Pac-Man World series and declared Pinky to be female.</i>
43 * </p>
44 * <p>
45 * Source: http://strategywiki.org/wiki/Pac-Man/Getting_Started
46 * </p>
47 *
48 * @author Jeroen Roosen
49 *
50 */
51 public class Pinky extends Ghost {
52
53 private static final int SQUARES_AHEAD = 4;
54
55 /**
56 * The variation in intervals, this makes the ghosts look more dynamic and
57 * less predictable.
58 */
59 private static final int INTERVAL_VARIATION = 50;
60
61 /**
62 * The base movement interval.
63 */
64 private static final int MOVE_INTERVAL = 200;
65
66 /**
67 * Creates a new "Pinky", a.k.a. "Speedy".
68 *
69 * @param spriteMap
70 * The sprites for this ghost.
71 */
72 public Pinky(Map<Direction, Sprite> spriteMap) {
73 super(spriteMap, MOVE_INTERVAL, INTERVAL_VARIATION);
74 }
75
76 /**
77 * {@inheritDoc}
78 *
79 * <p>
80 * When the ghosts are not patrolling their home corners, Pinky wants to go
81 * to the place that is four grid spaces ahead of Pac-Man in the direction
82 * that Pac-Man is facing. If Pac-Man is facing down, Pinky wants to go to
83 * the location exactly four spaces below Pac-Man. Moving towards this place
84 * uses the same logic that Blinky uses to find Pac-Man's exact location.
85 * Pinky is affected by a targeting bug if Pac-Man is facing up - when he
86 * moves or faces up, Pinky tries moving towards a point up, and left, four
87 * spaces.
88 * </p>
89 */
90 @Override
91 public Optional<Direction> nextAiMove() {
92 assert hasSquare();
93
94 Unit player = Navigation.findNearest(Player.class, getSquare());
95 if (player == null) {
96 return Optional.empty();
97 }
98 assert player.hasSquare();
99 Square destination = player.squaresAheadOf(SQUARES_AHEAD);
100
101 List<Direction> path = Navigation.shortestPath(getSquare(), destination, this);
102 if (path != null && !path.isEmpty()) {
103 return Optional.ofNullable(path.get(0));
104 }
105 return Optional.empty();
106 }
107 }