View Javadoc

1   /*
2    * CanICast.java 
3    * Created on 27 janv. 2004
4    * 
5    *   Magic-Project is a turn based strategy simulator
6    *   Copyright (C) 2003-2007 Fabrice Daugan
7    *
8    *   This program is free software; you can redistribute it and/or modify it 
9    * under the terms of the GNU General Public License as published by the Free 
10   * Software Foundation; either version 2 of the License, or (at your option) any
11   * later version.
12   *
13   *   This program is distributed in the hope that it will be useful, but WITHOUT 
14   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15   * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
16   * details.
17   *
18   *   You should have received a copy of the GNU General Public License along  
19   * with this program; if not, write to the Free Software Foundation, Inc., 
20   * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21   */
22  package net.sf.magicproject.event;
23  
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.util.List;
27  
28  import net.sf.magicproject.action.GiveMana;
29  import net.sf.magicproject.action.MAction;
30  import net.sf.magicproject.clickable.ability.Ability;
31  import net.sf.magicproject.clickable.targetable.card.MCard;
32  import net.sf.magicproject.expression.ExpressionFactory;
33  import net.sf.magicproject.test.Test;
34  import net.sf.magicproject.token.IdTokens;
35  
36  /***
37   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
38   * @since 0.54
39   * @since 0.93 recheck the card position during ability matching to avoid
40   *        playable spell from stack.
41   */
42  public class CanICast extends MEventListener {
43  
44  	/***
45  	 * Create an instance of CanICast by reading a file Offset's file must
46  	 * pointing on the first byte of this event <br>
47  	 * <ul>
48  	 * Structure of InputStream : Data[size]
49  	 * <li>[super]</li>
50  	 * <li>idCard [Expression]</li>
51  	 * </ul>
52  	 * 
53  	 * @param inputFile
54  	 *          is the file containing this event
55  	 * @param card
56  	 *          is the card owning this event
57  	 * @throws IOException
58  	 *           if error occurred during the reading process from the specified
59  	 *           input stream
60  	 */
61  	public CanICast(InputStream inputFile, MCard card) throws IOException {
62  		super(inputFile, card);
63  		// TODO extend the idCard to a real Expression for activated abilities
64  		idCard = ExpressionFactory.readNextExpression(inputFile).getValue(null,
65  				null, null);
66  	}
67  
68  	/***
69  	 * Creates a new instance of CanICast specifying all attributes of this class.
70  	 * All parameters are copied, not cloned. So this new object shares the card
71  	 * and the specified codes
72  	 * 
73  	 * @param idZone
74  	 *          the place constraint to activate this event
75  	 * @param test
76  	 *          the test of this event
77  	 * @param card
78  	 *          is the card owning this card
79  	 * @param idCard
80  	 *          is the id of card we want to play
81  	 */
82  	protected CanICast(int idZone, Test test, MCard card, int idCard) {
83  		super(idZone, test, card);
84  		this.idCard = idCard;
85  	}
86  
87  	@Override
88  	public MEventListener clone(MCard card) {
89  		return new CanICast(idZone, test, card, idCard);
90  	}
91  
92  	@Override
93  	public final boolean isActivated() {
94  		return true;
95  	}
96  
97  	@Override
98  	public final boolean isTriggered() {
99  		return false;
100 	}
101 
102 	@Override
103 	public final void registerToManager(Ability ability) {
104 		// add this event listener
105 		if (!MEventListener.CAN_I_CAST_ABILITIES[ability.getController().idPlayer]
106 				.contains(ability)) {
107 			CAN_I_CAST_ABILITIES[ability.getController().idPlayer].add(ability);
108 		}
109 	}
110 
111 	@Override
112 	public final void removeFromManager(Ability ability) {
113 		CAN_I_CAST_ABILITIES[0].remove(ability);
114 		CAN_I_CAST_ABILITIES[1].remove(ability);
115 	}
116 
117 	/***
118 	 * Tell if the current event matches with this event. If there is an
119 	 * additional code to check, it'would be checked if the main event matches
120 	 * with the main event
121 	 * 
122 	 * @param ability
123 	 *          is the ability owning this test. The card component of this
124 	 *          ability should correspond to the card owning this test too.
125 	 * @param idActivePlayer
126 	 *          id of active player
127 	 * @return true if the current event match with this event
128 	 */
129 	public boolean isMatching(Ability ability, int idActivePlayer) {
130 		return isWellPlaced() && canIcastCondition(idActivePlayer, idCard)
131 				&& test(ability, card);
132 	}
133 
134 	/***
135 	 * Tell if the current event matches with this event. If there is an
136 	 * additional code to check, it'would be checked if the main event matches
137 	 * with the main event
138 	 * 
139 	 * @param ability
140 	 *          is the ability owning this test. The card component of this
141 	 *          ability should correspond to the card owning this test too.
142 	 * @param idActivePlayer
143 	 *          id of active player
144 	 * @return true if the current event match with this event
145 	 */
146 	public boolean isMatchingManaAbility(Ability ability, int idActivePlayer) {
147 		return idCard == IdTokens.MANA_ABILITY && test(ability, card);
148 	}
149 
150 	@Override
151 	public boolean isWellPlaced() {
152 		return card.playableZone(card.getIdZone(), this.idZone);
153 	}
154 
155 	@Override
156 	public boolean isWellPlaced(int idZone) {
157 		return card.playableZone(idZone, this.idZone);
158 	}
159 
160 	/***
161 	 * Dispatch this event to all active event listener able to understand this
162 	 * event. The listening events able to understand this event are <code>this
163 	 * </code>
164 	 * and other multiple event listeners
165 	 * 
166 	 * @param idActivePlayer
167 	 *          id of active player
168 	 * @param res
169 	 *          list in which playable abilities would be added
170 	 * @param advRes
171 	 *          list in which advanced playable abilities would be added
172 	 * @see #isMatching(Ability, int)
173 	 */
174 	public static void dispatchEvent(int idActivePlayer, List<Ability> res,
175 			List<Ability> advRes) {
176 		for (Ability ability : CAN_I_CAST_ABILITIES[idActivePlayer]) {
177 			if (((CanICast) ability.eventComing())
178 					.isMatching(ability, idActivePlayer)
179 					&& ability.checkTargetActions() && ability.checkObjectActions()) {
180 				if (ability.isMatching()) {
181 					res.add(ability);
182 				} else {
183 					advRes.add(ability);
184 				}
185 			}
186 		}
187 	}
188 
189 	/***
190 	 * Dispatch this event to all active event listener able to understand this
191 	 * event.
192 	 * 
193 	 * @param idActivePlayer
194 	 *          id of active player
195 	 * @param res
196 	 *          list in which playable abilities would be added
197 	 * @see #isMatching(Ability, int)
198 	 */
199 	public static void dispatchManaAbilityEvent(int idActivePlayer,
200 			List<Ability> res) {
201 		for (Ability ability : CAN_I_CAST_ABILITIES[idActivePlayer]) {
202 			if (((CanICast) ability.eventComing()).isMatchingManaAbility(ability,
203 					idActivePlayer)
204 					&& ability.isMatching()) {
205 				res.add(ability);
206 			}
207 		}
208 	}
209 
210 	/***
211 	 * Iterate on given actions looking for a 'give mana' action. If one or
212 	 * several are found, the playable <code>idCard</code> of this event will be
213 	 * replaced by <code>IdTokens.MANA_ABILITY</code>
214 	 * 
215 	 * @param actionList
216 	 *          list of actions
217 	 * @return true if at least one 'give mana' action has been found in the
218 	 *         specified list.
219 	 */
220 	public boolean updateManaAbilityTag(MAction... actionList) {
221 		for (MAction action : actionList) {
222 			if (action instanceof GiveMana) {
223 				idCard = IdTokens.MANA_ABILITY;
224 				return true;
225 			}
226 		}
227 		return false;
228 	}
229 
230 	/***
231 	 * Return set of playable idCard
232 	 * 
233 	 * @return set of playable idCard
234 	 */
235 	public int getPlayableIdCard() {
236 		return idCard;
237 	}
238 
239 	@Override
240 	public final Event getIdEvent() {
241 		return Event.CAN_CAST_CARD;
242 	}
243 
244 	/***
245 	 * set of playable idCard
246 	 */
247 	private int idCard;
248 
249 }