View Javadoc

1   /*
2    *   Firemox is a turn based strategy simulator
3    *   Copyright (C) 2003-2007 Fabrice Daugan
4    *
5    *   This program is free software; you can redistribute it and/or modify it 
6    * under the terms of the GNU General Public License as published by the Free 
7    * Software Foundation; either version 2 of the License, or (at your option) any
8    * later version.
9    *
10   *   This program is distributed in the hope that it will be useful, but WITHOUT 
11   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12   * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
13   * details.
14   *
15   *   You should have received a copy of the GNU General Public License along  
16   * with this program; if not, write to the Free Software Foundation, Inc., 
17   * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  package net.sf.firemox.action;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.net.URL;
24  import java.util.Arrays;
25  import java.util.HashMap;
26  import java.util.Map;
27  
28  import net.sf.firemox.action.intlist.IntList;
29  import net.sf.firemox.action.objectmap.ObjectMapFactory;
30  import net.sf.firemox.action.target.TargetFactory;
31  import net.sf.firemox.action.targetlist.TargetListFactory;
32  import net.sf.firemox.modifier.Modifier;
33  import net.sf.firemox.operation.IdOperation;
34  import net.sf.firemox.test.And;
35  import net.sf.firemox.test.Or;
36  import net.sf.firemox.test.Test;
37  import net.sf.firemox.test.TestFactory;
38  import net.sf.firemox.tools.Log;
39  import net.sf.firemox.tools.MToolKit;
40  import net.sf.firemox.tools.Picture;
41  
42  /***
43   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
44   * @since 0.85
45   */
46  public final class ActionFactory {
47  
48  	/***
49  	 * Create a new instance of this class.
50  	 */
51  	private ActionFactory() {
52  		super();
53  	}
54  
55  	/***
56  	 * Initialize pictures and constraints associted to actions.
57  	 * <ul>
58  	 * Structure of InputStream : Data[size]
59  	 * <li>baseUrl of action pictures [String]
60  	 * <li>nb associated pictures [int]</li>
61  	 * <li>action i [MAction]</li>
62  	 * <li>picture i [String]</li>
63  	 * <li>nb associated constraints [1]</li>
64  	 * <li>action i [MAction]</li>
65  	 * <li>operation for test i [Operation]</li>
66  	 * <li>constraint i [Test]</li>
67  	 * </ul>
68  	 * 
69  	 * @param inputFile
70  	 *          file containing this action
71  	 * @throws IOException
72  	 *           If some other I/O error occurs
73  	 */
74  	public static void init(InputStream inputFile) throws IOException {
75  		// action pictures
76  		final String picturesBaseUrl = MToolKit.readString(inputFile);
77  		PICTURES.clear();
78  		for (int i = inputFile.read(); i-- > 0;) {
79  			final String actionName = MToolKit.readString(inputFile);
80  			final String pictureName = MToolKit.readString(inputFile);
81  			try {
82  				Picture.download(MToolKit
83  						.getTbsPicture("actions/" + pictureName, false), new URL(
84  						picturesBaseUrl + pictureName));
85  				PICTURES
86  						.put(actionName, "<img src='file:///"
87  								+ MToolKit.getTbsHtmlPicture("actions/" + pictureName)
88  								+ "'>&nbsp;");
89  			} catch (Exception e) {
90  				Log.info(e.getMessage());
91  			}
92  		}
93  
94  		// action constraints
95  		CONSTRAINTS.clear();
96  		for (int i = inputFile.read(); i-- > 0;) {
97  			final Object[] constraint = new Object[3];
98  
99  			// read action
100 			final MAction action = ActionFactory.readAction(inputFile, null);
101 			constraint[0] = action;
102 
103 			// read operation id
104 			constraint[1] = IdOperation.deserialize(inputFile);
105 
106 			// read constraint test
107 			constraint[2] = TestFactory.readNextTest(inputFile);
108 
109 			// associate action to the constraint
110 			CONSTRAINTS.put(action.getIdAction(), constraint);
111 		}
112 	}
113 
114 	/***
115 	 * Read a list a actions from the given input stream.
116 	 * 
117 	 * @param inputFile
118 	 *          the stream used to create list of actions.
119 	 * @param modifier
120 	 *          the optional modifier containing the action list.
121 	 * @return list of actions read from the given stream.
122 	 * @throws IOException
123 	 *           If some other I/O error occurs
124 	 */
125 	public static MAction[] readActionList(InputStream inputFile,
126 			Modifier modifier) throws IOException {
127 		final MAction[] res = new MAction[inputFile.read()];
128 		try {
129 			for (int index = 0; index < res.length; index++) {
130 				res[index] = ActionFactory.readAction(inputFile, null);
131 			}
132 			return res;
133 		} catch (Throwable e) {
134 			throw new RuntimeException(
135 					">> TBS ERROR reading action. Last known action is : "
136 							+ currentAction + ", context : " + Arrays.toString(res), e);
137 		}
138 	}
139 
140 	/***
141 	 * Return the constraints to make usable the specified actions list.
142 	 * 
143 	 * @param cost
144 	 *          is the actions list
145 	 * @param constraintTest
146 	 *          is the existing constrains
147 	 * @return the constraints to make usable the specified actions list.
148 	 */
149 	public static Test getConstraints(MAction[] cost, Test constraintTest) {
150 		Test res = constraintTest;
151 		for (int index = 0; index < cost.length; index++) {
152 			// constraints of action
153 			final Object[] constraint = CONSTRAINTS.get(cost[index].getIdAction());
154 			if (constraint != null && cost[index].equal((MAction) constraint[0])) {
155 				// there is a constraint with this action
156 				switch ((IdOperation) constraint[1]) {
157 				case AND:
158 					res = And.append(constraintTest, cost[index]
159 							.parseTest((Test) constraint[2]));
160 					break;
161 				case OR:
162 					res = Or.append(constraintTest, (Test) constraint[2]);
163 					break;
164 				default:
165 					throw new InternalError("Unknown constraint operation : "
166 							+ ((Integer) constraint[1]).intValue());
167 				}
168 			}
169 		}
170 		return res;
171 	}
172 
173 	/***
174 	 * Read and return the next action from specified inputFile
175 	 * 
176 	 * @param inputFile
177 	 *          the input stream where action will be read.
178 	 * @param modifier
179 	 *          the modifier that would be used with actions that need it. Can be
180 	 *          null.
181 	 * @return the next action read into of specified inputFile
182 	 * @throws IOException
183 	 *           If some other I/O error occurs
184 	 */
185 	public static MAction readAction(InputStream inputFile, Modifier modifier)
186 			throws IOException {
187 		Actiontype idAction = Actiontype.valueOf(inputFile);
188 		switch (idAction) {
189 		case ABORT:
190 			return Abort.instance;
191 		case ADD_ABILITY:
192 			return new AddAbility(inputFile);
193 		case ADD_MODIFIER:
194 			return new AddModifier(inputFile);
195 		case ADD_OBJECT:
196 			return new AddObject(inputFile);
197 		case ATTACH_LIST:
198 			return new AttachList(inputFile);
199 		case CHOICE:
200 			return new InputChoice(inputFile);
201 		case CREATE_ABILITY:
202 			return new CreateAbility(inputFile);
203 		case CREATE_CARD:
204 			return new CreateCard(inputFile);
205 		case CREATE_MODIFIER:
206 			return new CreateModifier(inputFile);
207 		case REMOVE_OBJECT:
208 			return new RemoveObject(inputFile);
209 		case ASSIGN_DAMAGE_FROM_TO:
210 			return new AssignDamageFromTo(inputFile);
211 		case ASSIGN_DAMAGE_TARGET:
212 			return new AssignDamageTarget(inputFile);
213 		case ASSIGN_DAMAGE_SOURCE_DEST:
214 			return new AssignDamageSourceDest(inputFile);
215 		case DETACH_ME:
216 			return DetachMe.getInstance();
217 		case GENERATE_EVENT:
218 			return new GenerateEvent(inputFile);
219 		case GIVE_MANA_BASIC:
220 			return new GiveManaBasic(inputFile);
221 		case GIVE_MANA_MULTI:
222 			return new GiveManaMulti(inputFile);
223 		case HOP:
224 			return new Hop(inputFile);
225 		case IF_THEN_ELSE:
226 			return new IfThenHop(inputFile);
227 		case INPUT_COLOR:
228 			return new InputColor(inputFile);
229 		case INPUT_NUMBER:
230 			return new InputNumber(inputFile);
231 		case INPUT_ZONE:
232 			return new InputZone(inputFile);
233 		case INPUT_PROPERTY:
234 			return new InputProperty(inputFile);
235 		case INT_LIST:
236 			return IntList.readNextIntList(inputFile);
237 		case LETHAL_DAMAGE:
238 			return LethalDamage.instance;
239 		case LOSE_GAME:
240 			return new LoseGame(inputFile);
241 		case MODIFY_ABILITY_REGISTER:
242 			return new ModifyAbilityRegister(inputFile);
243 		case MODIFY_STACK_REGISTER:
244 			return new ModifyStackRegister(inputFile);
245 		case MODIFY_TARGET_LIST_REGISTER:
246 			return new ModifyTargetListRegister(inputFile);
247 		case MODIFY_TARGETABLE_REGISTER:
248 			return new ModifyTargetableRegister(inputFile);
249 		case MODIFY_STATIC_REGISTER:
250 			return new ModifyStaticRegister(inputFile);
251 		case MODIFY_REQUIRED_MANA:
252 			return new ModifyRequiredMana(inputFile);
253 		case MOVE_CARD:
254 			return new MoveCard(inputFile);
255 		case MOVE_OBJECT:
256 			return new MoveObject(inputFile);
257 		case MOVE_PLAYER_CARD:
258 			return new MovePlayerCard(inputFile);
259 		case MSG:
260 			return new Input(inputFile);
261 		case NEXT_CURRENT_PLAYER:
262 			return new NextCurrentPlayer(inputFile);
263 		case NEXT_PHASE:
264 			return new NextPhase(inputFile);
265 		case OBJECT_MAP:
266 			return ObjectMapFactory.readNextObjectMap(inputFile);
267 		case PAY_MANA:
268 			return new PayMana(inputFile);
269 		case UNREGISTER_THIS:
270 			return UnregisterThis.instance;
271 		case REPEAT_ACTION:
272 			return new Repeat(inputFile);
273 		case RESOLVE_HIDDEN:
274 			return ResolveHidden.instance;
275 		case SET_ID_CARD:
276 			return new SetIdCard(inputFile);
277 		case SHUFFLE:
278 			return new Shuffle(inputFile);
279 		case SKIP_PHASE:
280 			return new SkipPhase(inputFile);
281 		case SOUND:
282 			return new Sound(inputFile);
283 		case TAP:
284 			return new Tap(inputFile);
285 		case TARGET:
286 			return TargetFactory.readNextTarget(inputFile);
287 		case TARGET_LIST:
288 			return TargetListFactory.readNextTargetList(inputFile);
289 		case UPDATE_TOUGHNESS:
290 			return UpdateToughness.getInstance();
291 		case UPDATE_LIFE:
292 			return UpdateLife.getInstance();
293 		case ZONE_VISIBILITY:
294 			return new ZoneVisibility(inputFile);
295 		case FORCE_PLAY:
296 			return new ForcePlay(inputFile);
297 		case TARGET_ALL:
298 			return new TargetAllNoEvent(inputFile);
299 		case TARGET_RANDOM:
300 			return new TargetRandomNoEvent(inputFile);
301 		case ATTACH:
302 			return new Attach(inputFile);
303 		case FACE:
304 			return new Face(inputFile);
305 		case COPY_CARD:
306 			return new CopyCard(inputFile);
307 		case RESTORE_CARD:
308 			return new RestoreCard(inputFile);
309 		default:
310 			throw new InternalError("Unknow action: " + idAction);
311 		}
312 	}
313 
314 	/***
315 	 * Associated pictures
316 	 */
317 	protected static final Map<String, String> PICTURES = new HashMap<String, String>();
318 
319 	/***
320 	 * Available action constraints.
321 	 */
322 	private static final Map<Actiontype, Object[]> CONSTRAINTS = new HashMap<Actiontype, Object[]>();
323 
324 	/***
325 	 * Is the current action is being to be parsed. Used only while parsing.
326 	 */
327 	static UserAction currentAction;
328 
329 }