View Javadoc

1   /*
2    * Created on 19 octobre 2001, 21:31
3    * 
4    *   Magic-Project is a turn based strategy simulator
5    *   Copyright (C) 2003-2007 Fabrice Daugan
6    *
7    *   This program is free software; you can redistribute it and/or modify it 
8    * under the terms of the GNU General Public License as published by the Free 
9    * Software Foundation; either version 2 of the License, or (at your option) any
10   * later version.
11   *
12   *   This program is distributed in the hope that it will be useful, but WITHOUT 
13   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14   * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
15   * details.
16   *
17   *   You should have received a copy of the GNU General Public License along  
18   * with this program; if not, write to the Free Software Foundation, Inc., 
19   * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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  		// Log.debug("EVENT " + this.getClass());
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 		// TODO implements the OR appender to all child classes
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 }