View Javadoc

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