1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sf.magicproject.stack;
20
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import net.sf.magicproject.clickable.ability.Ability;
25 import net.sf.magicproject.clickable.targetable.Targetable;
26 import net.sf.magicproject.event.Targeted;
27 import net.sf.magicproject.test.Test;
28 import net.sf.magicproject.token.IdTargets;
29 import net.sf.magicproject.tools.Log;
30
31 /***
32 * MTargetedList.java Created on 8 oct. 2003 represents list of targets :
33 * player(s) and/or card(s).
34 *
35 * @see net.sf.magicproject.xml.tbs.Card
36 * @see net.sf.magicproject.clickable.targetable.player.Player
37 * @since 0.2
38 * @since 0.53 manage the abortion when resoving a spell
39 * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
40 */
41 public class TargetedList {
42
43 /***
44 * Creates a new instance of MTargetedList
45 *
46 * @param source
47 * the source of this list of targets
48 */
49 public TargetedList(Ability source) {
50 super();
51
52 this.source = source;
53 }
54
55 /***
56 * Add a player/card to the targeted list <br>
57 * If the current target options indicates that an event has to be generated
58 * when a target is choosen, the event Targeted is dispatched.
59 *
60 * @param eventOption
61 * is the event mode : Force, default, none. Depending this value,
62 * the added target will be rechecked before resolution process
63 * @param targeted
64 * the player to add to the list
65 * @param test
66 * is the used filter. All objects making false this test are removed
67 * from the specified list and from the constraint really targeted
68 * list.
69 * @param raiseEvent
70 * if false, is any case, no event can be triggered.
71 */
72 public void addTarget(int eventOption, Targetable targeted, Test test,
73 boolean raiseEvent) {
74 if (list.contains(targeted)) {
75 Log.warn("The target " + targeted + " is already in the target list");
76 }
77 list.add(targeted);
78 if (eventOption != IdTargets.RAISE_EVENT_NOT) {
79
80 if (reallyTargeted == null) {
81 reallyTargeted = new ArrayList<Targetable>();
82 reallyTargetedTest = new ArrayList<Test>();
83 }
84 reallyTargeted.add(targeted);
85 reallyTargetedTest.add(test);
86 if (raiseEvent) {
87 Targeted.dispatchEvent(source.getCard(), targeted);
88 }
89 }
90 }
91
92 /***
93 * Return the target placed at index
94 *
95 * @param index
96 * the target register to extract from the list
97 * @return the target placed at index
98 */
99 public Targetable get(int index) {
100 return list.get(index);
101 }
102
103 /***
104 * Return the last target
105 *
106 * @return the last target
107 */
108 public Targetable getLast() {
109 return get(size() - 1);
110 }
111
112 /***
113 * Return the first target
114 *
115 * @return the first target
116 */
117 public Targetable getFirst() {
118 return get(0);
119 }
120
121 /***
122 * Remove the last target
123 */
124 public void removeLast() {
125 remove(size() - 1);
126 }
127
128 /***
129 * Return a target from the list
130 *
131 * @param index
132 * the index of the element to be removed.
133 */
134 public void remove(int index) {
135 if (reallyTargeted != null) {
136 Targetable removed = list.remove(index);
137 final int indexOf = reallyTargeted.indexOf(removed);
138 if (indexOf != -1) {
139 reallyTargeted.remove(indexOf);
140 reallyTargetedTest.remove(indexOf);
141 }
142 } else {
143 list.remove(index);
144 }
145 }
146
147 /***
148 * Return the specified target from the list
149 *
150 * @param target
151 * the target to be removed.
152 */
153 public void remove(Targetable target) {
154 list.remove(target);
155 if (reallyTargeted != null) {
156 final int indexOf = reallyTargeted.indexOf(target);
157 if (indexOf != -1) {
158 reallyTargeted.remove(indexOf);
159 reallyTargetedTest.remove(indexOf);
160 }
161 }
162 }
163
164 /***
165 * Return the specified target from the list
166 *
167 * @param target
168 * the target to be removed.
169 */
170 public void removeTargeted(Targetable target) {
171 list.remove(target);
172 if (reallyTargeted != null) {
173 final int indexOf = reallyTargeted.lastIndexOf(target);
174 if (indexOf != -1) {
175 reallyTargeted.remove(indexOf);
176 reallyTargetedTest.remove(indexOf);
177 }
178 }
179 }
180
181 /***
182 * Remove all component but the first.
183 */
184 public void removeQueue() {
185 for (int i = list.size(); i-- > 1;) {
186 remove(i);
187 }
188 }
189
190 /***
191 * Remove all component but the last.
192 */
193 public void removeTail() {
194 for (int i = list.size() - 1; i-- > 0;) {
195 remove(i);
196 }
197 }
198
199 /***
200 * Indicates if there are targets
201 *
202 * @return true if there are targets
203 */
204 public boolean isEmpty() {
205 return list.isEmpty();
206 }
207
208 /***
209 * Retourne la taille de la liste
210 *
211 * @return number of targets
212 */
213 public int size() {
214 return list.size();
215 }
216
217 /***
218 * Indicates that we're no longer looking for the targets
219 */
220 public void clear() {
221 list.clear();
222 if (reallyTargeted != null) {
223 reallyTargeted.clear();
224 reallyTargetedTest.clear();
225 }
226 }
227
228 /***
229 * Recheck the whole list of targets added with raised event.
230 *
231 * @param ability
232 * is the ability owning this request. The card component of this
233 * ability should correspond to the card owning this request too.
234 * @return the amount of remaining object making true the specified test.
235 */
236 public int recheckList(Ability ability) {
237 if (reallyTargeted == null || reallyTargeted.size() == 0) {
238 return 1;
239 }
240 for (int i = reallyTargeted.size(); i-- > 0;) {
241 final Targetable tested = reallyTargeted.get(i);
242 if (!reallyTargetedTest.get(i).test(ability, tested)) {
243
244 list.remove(tested);
245 reallyTargeted.remove(i);
246 reallyTargetedTest.remove(i);
247 }
248 }
249 return reallyTargeted.size();
250 }
251
252 /***
253 * Return a clone of this list.
254 *
255 * @return a clone of this list.
256 */
257 public TargetedList cloneList() {
258 TargetedList clone = new TargetedList(source);
259 clone.list = new ArrayList<Targetable>(list);
260 clone.reallyTargeted = reallyTargeted == null ? null
261 : new ArrayList<Targetable>(reallyTargeted);
262 clone.reallyTargetedTest = reallyTargetedTest == null ? null
263 : new ArrayList<Test>(reallyTargetedTest);
264 return clone;
265
266 }
267
268 @Override
269 public String toString() {
270 return list.toString();
271 }
272
273 /***
274 * represents all targeted card(s) and/or player(s)
275 */
276 public List<Targetable> list = new ArrayList<Targetable>();
277
278 /***
279 * indicates if currently, all targets have been aborted.
280 */
281
282 /***
283 * Indicates if target was really targeted. Item is null is was not really
284 * targeted, non-null otherwise
285 */
286 private List<Targetable> reallyTargeted;
287
288 /***
289 * Indicates if target was really targeted. Item is null is was not really
290 * targeted, non-null otherwise
291 */
292 private List<Test> reallyTargetedTest;
293
294 /***
295 * Source of this target spell/ability
296 */
297 public Ability source;
298 }