summaryrefslogtreecommitdiff
path: root/src/ch/epfl/maze/physical/pacman/Ghost.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/ch/epfl/maze/physical/pacman/Ghost.java')
-rw-r--r--src/ch/epfl/maze/physical/pacman/Ghost.java243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/ch/epfl/maze/physical/pacman/Ghost.java b/src/ch/epfl/maze/physical/pacman/Ghost.java
new file mode 100644
index 0000000..f8f511e
--- /dev/null
+++ b/src/ch/epfl/maze/physical/pacman/Ghost.java
@@ -0,0 +1,243 @@
1package ch.epfl.maze.physical.pacman;
2
3import ch.epfl.maze.physical.Daedalus;
4import ch.epfl.maze.physical.Predator;
5import ch.epfl.maze.physical.Prey;
6import ch.epfl.maze.physical.stragegies.picker.RandomPicker;
7import ch.epfl.maze.physical.stragegies.reducer.BackwardReducer;
8import ch.epfl.maze.physical.stragegies.reducer.CostReducer;
9import ch.epfl.maze.util.Direction;
10import ch.epfl.maze.util.Vector2D;
11
12import java.util.EnumSet;
13import java.util.Set;
14
15/**
16 * Predator ghost that have two different modes and a home position in the labyrinth.
17 *
18 * @author Pacien TRAN-GIRARD
19 */
20abstract public class Ghost extends Predator implements BackwardReducer, CostReducer, RandomPicker {
21
22 public enum Mode {
23 CHASE(40),
24 SCATTER(14);
25
26 public static final Mode DEFAULT = CHASE;
27 public final int duration;
28
29 /**
30 * Constructs a new Mode with the given duration.
31 *
32 * @param duration The duration in cycles
33 */
34 Mode(int duration) {
35 this.duration = duration;
36 }
37
38 /**
39 * Returns the next Mode.
40 *
41 * @return The next Mode
42 */
43 public Mode getNext() {
44 switch (this) {
45 case CHASE:
46 return SCATTER;
47 case SCATTER:
48 return CHASE;
49 default:
50 return DEFAULT;
51 }
52 }
53 }
54
55 private static Prey commonPrey;
56
57 private final Vector2D homePosition;
58
59 private Mode mode;
60 private int modeCycle;
61
62 /**
63 * Constructs a predator with a specified position.
64 *
65 * @param position Position of the predator in the labyrinth
66 */
67 public Ghost(Vector2D position) {
68 super(position);
69
70 this.homePosition = position;
71
72 this.mode = Mode.DEFAULT;
73 this.modeCycle = 0;
74 }
75
76 /**
77 * Returns the cost to reach the target by choosing the given Direction by calculating the Euclidean distance.
78 *
79 * @param choice The Direction choice
80 * @param daedalus The Daedalus
81 * @return The Euclidean distance cost
82 */
83 @Override
84 public int getChoiceCost(Direction choice, Daedalus daedalus) {
85 Vector2D target = this.getTargetPosition(daedalus);
86 return (int) (this.getDistanceTo(choice, target) * 100);
87 }
88
89 @Override
90 public Set<Direction> reduce(Set<Direction> choices) {
91 return EnumSet.noneOf(Direction.class);
92 }
93
94 /**
95 * Selects the best Direction in the given choices by minimizing the Euclidean distance to the targeted position
96 * after excluding the provenance if possible.
97 *
98 * @param choices A set of Direction choices
99 * @param daedalus The Daedalus
100 * @return A set of optimal Direction choices
101 */
102 @Override
103 public Set<Direction> reduce(Set<Direction> choices, Daedalus daedalus) {
104 Set<Direction> forwardChoices = choices.size() > 1 ? BackwardReducer.super.reduce(choices) : choices;
105 return CostReducer.super.reduce(forwardChoices, daedalus);
106 }
107
108 @Override
109 public Direction move(Set<Direction> choices, Daedalus daedalus) {
110 this.countCycle();
111
112 Set<Direction> bestChoices = this.reduce(choices, daedalus);
113 return this.pick(bestChoices);
114 }
115
116 /**
117 * Returns the Prey's projected targeted position.
118 *
119 * @param daedalus The Daedalus
120 * @return The projected position
121 */
122 abstract protected Vector2D getPreyTargetPosition(Daedalus daedalus);
123
124 /**
125 * Returns the current Mode.
126 *
127 * @param daedalus The Daedalus
128 * @return The current Mode
129 */
130 protected Mode getMode(Daedalus daedalus) {
131 return this.mode;
132 }
133
134 /**
135 * Returns the position to target according to the current Mode.
136 *
137 * @param daedalus The Daedalus
138 * @return The position to target
139 */
140 protected Vector2D getTargetPosition(Daedalus daedalus) {
141 switch (this.getMode(daedalus)) {
142 case CHASE:
143 return this.getPreyTargetPosition(daedalus);
144 case SCATTER:
145 return this.homePosition;
146 default:
147 return this.homePosition;
148 }
149 }
150
151 /**
152 * Selects a new random Prey to chase in the Daedalus.
153 *
154 * @param daedalus The Daedalus
155 * @return The Chosen One
156 */
157 private static Prey selectAnyPrey(Daedalus daedalus) {
158 if (daedalus.getPreySet().isEmpty()) return null;
159 return daedalus.getPreySet().stream().findAny().get();
160 }
161
162 /**
163 * Sets a random Prey as the common Pre.
164 *
165 * @param daedalus The Daedalus
166 */
167 private static synchronized void setAnyPrey(Daedalus daedalus) {
168 Ghost.commonPrey = Ghost.selectAnyPrey(daedalus);
169 }
170
171 /**
172 * Returns the commonly targeted Prey.
173 *
174 * @param daedalus The Daedalus
175 * @return The common Prey
176 */
177 private static Prey getPrey(Daedalus daedalus) {
178 if (Ghost.commonPrey == null || !daedalus.hasPrey(Ghost.commonPrey))
179 Ghost.setAnyPrey(daedalus);
180
181 return Ghost.commonPrey;
182 }
183
184 /**
185 * Returns the commonly targeted Prey's position.
186 *
187 * @param daedalus The Daedalus
188 * @return The position of the Prey
189 */
190 protected final Vector2D getPreyPosition(Daedalus daedalus) {
191 Prey prey = Ghost.getPrey(daedalus);
192
193 if (prey == null) return this.homePosition;
194 return prey.getPosition();
195 }
196
197 /**
198 * Returns the commonly targeted Prey's Direction.
199 *
200 * @param daedalus The Daedalus
201 * @return The Direction the Prey is facing
202 */
203 protected final Direction getPreyDirection(Daedalus daedalus) {
204 Prey prey = Ghost.getPrey(daedalus);
205
206 if (prey == null) return Direction.NONE;
207 return prey.getDirection();
208 }
209
210 /**
211 * Calculates the Euclidean distance from the adjacent position at the given Direction to the target position.
212 *
213 * @param dir The adjacent Direction
214 * @param targetPosition The targeted position
215 * @return The Euclidean distance between the two positions
216 */
217 private double getDistanceTo(Direction dir, Vector2D targetPosition) {
218 return this
219 .getPosition()
220 .addDirectionTo(dir)
221 .sub(targetPosition)
222 .dist();
223 }
224
225 /**