1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package net.sf.magicproject.event;
22
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.util.ArrayList;
26 import java.util.EnumMap;
27 import java.util.List;
28 import java.util.Map;
29
30 import net.sf.magicproject.clickable.ability.Ability;
31 import net.sf.magicproject.clickable.ability.Priority;
32 import net.sf.magicproject.clickable.ability.ReplacementAbility;
33 import net.sf.magicproject.clickable.targetable.Targetable;
34 import net.sf.magicproject.clickable.targetable.card.MCard;
35 import net.sf.magicproject.clickable.targetable.card.TriggeredCard;
36 import net.sf.magicproject.event.context.ContextEventListener;
37 import net.sf.magicproject.stack.EventManager;
38 import net.sf.magicproject.test.Test;
39 import net.sf.magicproject.test.TestFactory;
40 import net.sf.magicproject.token.IdTokens;
41 import net.sf.magicproject.tools.RevertedArrayList;
42
43 /***
44 * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
45 * @since 0.53 support additional check registers
46 * @see Event
47 */
48 public abstract class MEventListener implements RegisterableEvent {
49
50 /***
51 * Create an instance of MEventListener by reading a file Offset's file must
52 * pointing on the first byte of this event <br>
53 * <ul>
54 * Structure of InputStream : Data[size]
55 * <li>idEvent [1]</li>
56 * <li>idZone [1]</li>
57 * <li>test [...]</li>
58 * <li>event's fields [...]</li>
59 * </ul>
60 *
61 * @param inputFile
62 * is the file containing this event
63 * @param card
64 * is the card owning this event
65 * @throws IOException
66 * if error occurred during the reading process from the specified
67 * input stream
68 * @see Event
69 * @see net.sf.magicproject.token.IdZones
70 */
71 protected MEventListener(InputStream inputFile, MCard card)
72 throws IOException {
73
74 this.idZone = inputFile.read();
75 this.card = card;
76 this.test = TestFactory.readNextTest(inputFile);
77 }
78
79 /***
80 * Creates a new instance of CanICast specifying all attributes of this class.
81 * All parameters are copied, not cloned. So this new object shares the card
82 * and the specified codes
83 *
84 * @param idZone
85 * the place constraint to activate this event
86 * @param test
87 * the test of this event
88 * @param card
89 * is the card owning this card
90 */
91 protected MEventListener(int idZone, Test test, MCard card) {
92 this.idZone = idZone;
93 this.card = card;
94 this.test = test;
95 }
96
97 /***
98 * Return the HTML code representing this ability.
99 *
100 * @param ability
101 * is the attached ability.
102 * @param context
103 * the context needed by event activated
104 * @return the HTML code representing this ability.
105 * @since 0.85 Event is displayed
106 */
107 public String toHtmlString(Ability ability, ContextEventListener context) {
108 return "event-" + getClass().getSimpleName();
109 }
110
111 /***
112 * Return the idEvent of this event
113 *
114 * @return the idEvent of this event
115 */
116 public abstract Event getIdEvent();
117
118 public abstract void registerToManager(Ability ability);
119
120 public abstract void removeFromManager(Ability ability);
121
122 /***
123 * Return a copy of this with the specified owner
124 *
125 * @param card
126 * is the card of the ability of this event
127 * @return copy of this event
128 */
129 public abstract MEventListener clone(MCard card);
130
131 /***
132 * return idZone of this card, whitout any code tap, untapped..)
133 *
134 * @return idZone of this card, whitout any code tap, untapped..)
135 */
136 public int getIdPlace() {
137 return MCard.getIdZone(idZone, null);
138 }
139
140 /***
141 * Tell if the card is well placed for this event to be playable
142 *
143 * @return true if the card is well placed for this event to be playable
144 */
145 public boolean isWellPlaced() {
146 return card.isSameIdZone(idZone);
147 }
148
149 /***
150 * Tell if the card is well placed for this event to be playable
151 *
152 * @param idZone
153 * the supposed zone where card is.
154 * @return true if the card is well placed for this event to be playable
155 */
156 public boolean isWellPlaced(int idZone) {
157 return this.idZone == idZone;
158 }
159
160 /***
161 * Tell if the event still activated before to be added to the stack
162 *
163 * @param previousContext
164 * @param ability
165 * is the ability owning this test. The card component of this
166 * ability should correspond to the card owning this test too.
167 * @return true if the current event match with this event
168 */
169 public boolean reCheck(ContextEventListener previousContext, Ability ability) {
170 return true;
171 }
172
173 /***
174 * Tell if the event still activated before to be added to the stack
175 *
176 * @param triggered
177 * the triggered card.
178 * @return true if the current event match with this event
179 */
180 public boolean reCheck(TriggeredCard triggered) {
181 return reCheck(triggered.getAbilityContext(), triggered.triggeredAbility);
182 }
183
184 /***
185 * Tell if the current event matches with this event. If there is an
186 * additional code to check, it'would be checked if the main event matches
187 * with the main event
188 *
189 * @param ability
190 * is the ability owning this test. The card component of this
191 * ability should correspond to the card owning this test too.
192 * @param tested
193 * the tested component
194 * @return true if the current event match with this event
195 */
196 protected boolean test(Ability ability, Targetable tested) {
197 return test == null || test.test(ability, tested);
198 }
199
200 /***
201 * ONLY for ID__CAN_CAST_CARD event evaluates the code condition, and tell if
202 * we can cast a spell
203 *
204 * @param idActivePlayer
205 * the active player identifiant
206 * @param idCard
207 * is the idCard we would cast
208 * @return true if we can cast a spell
209 */
210 protected boolean canIcastCondition(int idActivePlayer, int idCard) {
211 if (idCard == IdTokens.MYSELF) {
212 return EventManager.currentPhaseType().canICast(idActivePlayer,
213 card.getIdCard());
214 }
215 return EventManager.currentPhaseType().canICast(idActivePlayer, idCard);
216 }
217
218 /***
219 * Reset all instant, empty-stack and triggered abilities. After the call to
220 * this method, there is no event listener able to be activated
221 */
222 public static void reset() {
223 TRIGGRED_ABILITIES.clear();
224 REPLACEMENT_ABILITIES.clear();
225 for (Event event : Event.values()) {
226 TRIGGRED_ABILITIES.put(event, new RevertedArrayList<Ability>(20));
227 Map<Priority, List<ReplacementAbility>> map = new EnumMap<Priority, List<ReplacementAbility>>(
228 Priority.class);
229 for (Priority priority : Priority.values()) {
230 map.put(priority, new RevertedArrayList<ReplacementAbility>(20));
231 }
232 REPLACEMENT_ABILITIES.put(event, map);
233 }
234 CAN_I_CAST_ABILITIES[0].clear();
235 CAN_I_CAST_ABILITIES[1].clear();
236 }
237
238 /***
239 * Create and returns an union of this event and the specified one. Both event
240 * must have the same type. Test(s) and events attributes may be groupped
241 * depending instance of this event. If no possible append is possible
242 * <code>null</code> is returned.
243 *
244 * @param other
245 * the event to append with 'or' operator.
246 * @return a new event reprensenting 'this' or 'other'
247 */
248 public MEventListener appendOr(MEventListener other) {
249
250 return null;
251 }
252
253 /***
254 * Indicates if this event corresponds to an activated ability
255 *
256 * @return true if this event corresponds to an activated ability
257 */
258 public abstract boolean isActivated();
259
260 /***
261 * Indicates if this event corresponds to a triggered ability
262 *
263 * @return true if this event corresponds to a triggered ability
264 */
265 public abstract boolean isTriggered();
266
267 /***
268 * additional code to check.
269 */
270 public Test test = null;
271
272 /***
273 * card owning this event
274 */
275 public MCard card;
276
277 /***
278 * idZone where the card have to be to be activated
279 */
280 protected int idZone;
281
282 /***
283 * Represent all active triggered abilities of games for each event
284 */
285 public static final Map<Event, List<Ability>> TRIGGRED_ABILITIES = new EnumMap<Event, List<Ability>>(
286 Event.class);
287
288 /***
289 * Represent all active replacement abilities of games for each event and each
290 * priority.
291 */
292 public static final Map<Event, Map<Priority, List<ReplacementAbility>>> REPLACEMENT_ABILITIES = new EnumMap<Event, Map<Priority, List<ReplacementAbility>>>(
293 Event.class);
294
295 /***
296 * Returns the replacement abilities associated to this event.
297 *
298 * @param event
299 * the event to use to retrieve the associated replacement abilities.
300 * @return the replacement abilities associated to this event.
301 */
302 protected static final Map<Priority, List<ReplacementAbility>> getReplacementAbilities(
303 Event event) {
304 return REPLACEMENT_ABILITIES.get(event);
305 }
306
307 /***
308 * Represent all activated abilities/spell playable. One index per player.
309 */
310 @SuppressWarnings("unchecked")
311 public static final List<Ability>[] CAN_I_CAST_ABILITIES = new List[2];
312
313 static {
314 CAN_I_CAST_ABILITIES[0] = new ArrayList<Ability>();
315 CAN_I_CAST_ABILITIES[1] = new ArrayList<Ability>();
316 }
317
318 }