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.xml;
20  
21  import java.io.BufferedReader;
22  import java.io.File;
23  import java.io.FileNotFoundException;
24  import java.io.FileOutputStream;
25  import java.io.FileReader;
26  import java.io.IOException;
27  import java.io.PrintWriter;
28  import java.util.ArrayList;
29  import java.util.List;
30  
31  import net.sf.magicproject.token.IdConst;
32  import net.sf.magicproject.tools.MToolKit;
33  
34  import org.apache.commons.io.FileUtils;
35  import org.apache.commons.io.IOUtils;
36  import org.apache.commons.lang.StringUtils;
37  
38  /***
39   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
40   * @since 0.90
41   */
42  public final class Oracle2Xml {
43  
44  	/***
45  	 * May the validated cards (recycled directory) be patched by the new ones?
46  	 */
47  	private static final boolean UPDATE_CARD = false;
48  
49  	/***
50  	 * Bounds
51  	 */
52  	private static final int MAXI = Integer.MAX_VALUE;
53  
54  	private static final String TBS_NAME = IdConst.TBS_DEFAULT;
55  
56  	private boolean isAura = false;
57  
58  	/***
59  	 * Prevent this class to be instanciated.
60  	 */
61  	private Oracle2Xml() {
62  		super();
63  	}
64  
65  	/***
66  	 * @param oracleFile
67  	 *          the oracle format text file.
68  	 * @param destinationDir
69  	 *          the directory where built card will be placed.
70  	 * @param recycledDir
71  	 *          the directory where already built card are placed.
72  	 */
73  	@SuppressWarnings("null")
74  	public void serialize(File oracleFile, File destinationDir, File recycledDir) {
75  		if (!oracleFile.exists() || !oracleFile.isFile()) {
76  			System.err.println("The file '" + oracleFile + "' does not exist");
77  			System.exit(-1);
78  			return;
79  		}
80  
81  		if (!destinationDir.exists() || !destinationDir.isDirectory()) {
82  			System.err.println("The destination directory '" + destinationDir
83  					+ "' does not exist");
84  			System.exit(-1);
85  			return;
86  		}
87  		final StringBuilder cardText = new StringBuilder();
88  		int nbCard = 0;
89  		MToolKit.tbsName = TBS_NAME;
90  		try {
91  			final BufferedReader in = new BufferedReader(new FileReader(oracleFile));
92  			PrintWriter out = null;
93  			while (nbCard < MAXI) {
94  				String line = in.readLine();
95  				if (line == null)
96  					break;
97  				String cardName = line.trim();
98  				if (cardName.length() == 0) {
99  					continue;
100 				}
101 
102 				// a new card starts
103 				String fileName = MToolKit.getExactKeyName(cardName) + ".xml";
104 				if (new File(recycledDir, fileName).exists()) {
105 					if (UPDATE_CARD) {
106 						File patchFile = MToolKit.getFile("tbs/mtg/recycled/" + fileName);
107 						File tempFile = File.createTempFile(fileName, "temp");
108 						FileUtils.copyFile(patchFile, tempFile);
109 						final BufferedReader inExist = new BufferedReader(new FileReader(
110 								tempFile));
111 						final PrintWriter outExist = new PrintWriter(new FileOutputStream(
112 								patchFile));
113 						String lineExist = null;
114 						boolean found = false;
115 						while ((lineExist = inExist.readLine()) != null) {
116 							if (!found && lineExist.contains("name=\"")) {
117 								lineExist = lineExist
118 										.substring(0, lineExist.indexOf("name=\""))
119 										+ "name=\""
120 										+ cardName
121 										+ lineExist.substring(lineExist.indexOf("\"", lineExist
122 												.indexOf("name=\"")
123 												+ "name=\"".length() + 2));
124 								found = true;
125 							}
126 							outExist.println(lineExist);
127 						}
128 						IOUtils.closeQuietly(inExist);
129 						IOUtils.closeQuietly(outExist);
130 
131 						if (!found) {
132 							System.err.println(">> Error patching card '" + cardName + "'");
133 							// } else {
134 							// patching card
135 						}
136 					}
137 					skipCard(in);
138 					continue;
139 				}
140 
141 				out = new PrintWriter(new FileOutputStream(new File(destinationDir,
142 						fileName)));
143 				int[] manaCost = null;
144 
145 				// record the card text
146 				cardText.setLength(0);
147 				cardText.append("<!--\n\t");
148 
149 				List<String> properties = new ArrayList<String>();
150 				String power = null;
151 				String toughness = null;
152 				isNonBasicLand = false;
153 				isLocalEnchantCreature = false;
154 				isLocalEnchantLand = false;
155 				isLocalEnchantArtifact = false;
156 				isEnchantWorld = false;
157 				isLocalEnchantCreatureArtifact = false;
158 				isLocalEnchantPermanent = false;
159 				isLocalEnchantEnchantment = false;
160 				isGlobalEnchant = false;
161 				isInstant = false;
162 				isCreature = false;
163 				isArtifact = false;
164 				isSorcery = false;
165 				isSwamp = false;
166 				isIsland = false;
167 				isForest = false;
168 				isMountain = false;
169 				isPlains = false;
170 
171 				line = in.readLine().trim().replaceAll("//(.*//)", "").toLowerCase();
172 				cardText.append('\t').append(line).append("\n");
173 
174 				isArtifact = line.indexOf("artifact") != -1;
175 				if (line.startsWith("land") || line.endsWith(" land")) {
176 					isNonBasicLand = true;
177 				} else {
178 					manaCost = extractManaCost(line);
179 					line = in.readLine().replaceAll("//(.*//)", "").toLowerCase();
180 					cardText.append('\t').append(line).append("\n");
181 					isLocalEnchantCreature = line.indexOf("enchant creature") != -1;
182 					isEnchantWorld = line.indexOf("world enchantment") != -1;
183 					isAura = line.indexOf("aura") != -1;
184 					if (line.indexOf("enchantment") != -1 && !isAura && !isEnchantWorld)
185 						isGlobalEnchant = true;
186 					if (!isGlobalEnchant && !isAura && !isEnchantWorld
187 							&& !isLocalEnchantCreature) {
188 						isInstant = line.indexOf("instant") != -1;
189 						isCreature = line.indexOf("creature") != -1;
190 						isSorcery = line.indexOf("sorcery") != -1;
191 						isSwamp = line.indexOf("swamp") != -1;
192 						isIsland = line.indexOf("island") != -1;
193 						isForest = line.indexOf("forest") != -1;
194 						isMountain = line.indexOf("mountain") != -1;
195 						isArtifact = isArtifact || line.indexOf("artifact") != -1;
196 						isPlains = line.indexOf("plains") != -1;
197 					}
198 				}
199 				if (line.indexOf("snow") != -1)
200 					properties.add("snow");
201 
202 				if (line.indexOf("legendary") != -1)
203 					properties.add("legend");
204 
205 				if (line.indexOf("-") != -1) {
206 					properties = extractProperties(line.substring(line.indexOf("-") + 1)
207 							.trim(), properties);
208 				}
209 				if (isCreature) {
210 					line = in.readLine();
211 					cardText.append('\t').append(line).append("\n");
212 					if (line.indexOf("/") == -1) {
213 						System.err.println("Error reading card '" + cardName
214 								+ "' : power/toughness, line=" + line);
215 						skipCard(in);
216 						continue;
217 					}
218 					power = line.substring(0, line.indexOf('/')).trim();
219 					toughness = line.substring(line.indexOf('/') + 1).trim();
220 				}
221 				if (isEnchantWorld) {
222 					properties.add("enchant-world");
223 				}
224 
225 				List<String> lineBuffer = new ArrayList<String>();
226 				boolean hasBuyBack = false;
227 				boolean hasFlashBack = false;
228 				boolean hasForecast = false;
229 				boolean hasAffinity = false;
230 				boolean hasRampage = false;
231 				boolean hasTransmute = false;
232 				boolean hasDredge = false;
233 				boolean hasHaunt = false;
234 				boolean hasBloodThirst = false;
235 				boolean hasBushido = false;
236 				String hasTransmuteCost = null;
237 				int hasRampageCount = 1;
238 				int hasDredgeCount = 1;
239 				int hasBloodThirstCount = 1;
240 				int hasBushidoCount = 1;
241 				boolean hasFading = false;
242 				lowerCard = cardName.toLowerCase();
243 				String hasBuyBackLine = null;
244 				String hasFlashBackLine = null;
245 				String hasAffinityLine = null;
246 				String hasForecastLine = null;
247 				String hasFadingLine = null;
248 				boolean hasFlanking = false;
249 				boolean hasHaunting = false;
250 
251 				while (true) {
252 					line = in.readLine();
253 					if (line == null || line.length() == 0)
254 						break;
255 					line = line.replaceAll("T ", "T :").replaceAll("//(.*//)", "")
256 							.toLowerCase();
257 					cardText.append('\t').append(line).append('\n');
258 
259 					if (isAura && !isLocalEnchantCreature && !isLocalEnchantLand
260 							&& !isLocalEnchantCreatureArtifact && !isLocalEnchantArtifact
261 							&& !isLocalEnchantPermanent && !isLocalEnchantEnchantment) {
262 						isLocalEnchantCreature = line.indexOf("enchant creature") != -1;
263 						isLocalEnchantLand = line.indexOf("enchant land") != -1;
264 						isLocalEnchantCreatureArtifact = line
265 								.indexOf("enchant artifact creature") != -1;
266 						isLocalEnchantArtifact = !isLocalEnchantCreatureArtifact
267 								&& line.indexOf("enchant artifact") != -1;
268 						isLocalEnchantPermanent = line.indexOf("enchant permanent") != -1;
269 						isLocalEnchantEnchantment = line.indexOf("enchant enchantment") != -1;
270 					}
271 
272 					if (line.startsWith("buyback")) {
273 						hasBuyBack = true;
274 						hasBuyBackLine = line.substring("buyback".length()).trim();
275 						continue;
276 					} else if (line.startsWith("haunt")) {
277 						hasHaunt = true;
278 						continue;
279 					} else if (line.startsWith("flashback")) {
280 						hasFlashBack = true;
281 						hasFlashBackLine = line.substring("flashback".length()).trim();
282 						continue;
283 					} else if (line.startsWith("affinity for ")) {
284 						hasAffinity = true;
285 						hasAffinityLine = line.substring("affinity for ".length()).trim();
286 						continue;
287 					} else if (line.startsWith("forecast")) {
288 						hasForecast = true;
289 						hasForecastLine = line.substring("forecast - ".length()).trim();
290 						continue;
291 					} else if (line.startsWith("rampage ")) {
292 						hasRampage = true;
293 						hasRampageCount = Integer.parseInt(line.substring(
294 								"rampage ".length(), "rampage ".length() + 1).trim());
295 						continue;
296 					} else if (line.startsWith("transmute ")) {
297 						hasTransmute = true;
298 						hasTransmuteCost = line.substring("transmute ".length()).trim();
299 						continue;
300 					} else if (line.startsWith("dredge ")) {
301 						hasDredge = true;
302 						hasDredgeCount = Integer.parseInt(line.substring(
303 								"dredge ".length(), "dredge ".length() + 1).trim());
304 						continue;
305 					} else if (line.startsWith("bloodthirst ")) {
306 						hasBloodThirst = true;
307 						String bloodThirst = line.substring("bloodthirst ".length(),
308 								"bloodthirst ".length() + 1).trim();
309 						if (bloodThirst.compareTo("x") != 0)
310 							hasBloodThirstCount = Integer.parseInt(bloodThirst);
311 						else
312 							hasBloodThirstCount = 0; // 0 must be changed to a variable that
313 						// counts damage opponent has taken the present turn
314 						continue;
315 					} else if (line.startsWith("bushido ")) {
316 						hasBushido = true;
317 						hasBushidoCount = Integer.parseInt(line.substring(
318 								"bushido ".length(), "bushido ".length() + 1).trim());
319 						continue;
320 					} else if (line.startsWith("fading")) {
321 						hasFading = true;
322 						hasFadingLine = line.substring("fading".length()).trim();
323 						continue;
324 					} else if (line.startsWith("flanking")) {
325 						hasFlanking = true;
326 						continue;
327 					} else if (line.startsWith("haunt")) {
328 						hasHaunting = true;
329 						continue;
330 					}
331 					if (line.indexOf(lowerCard + " doesn't untap during") != -1) {
332 						properties.add("does-not-untap");
333 					}
334 					if (line.indexOf("you may choose not to untap") != -1) {
335 						properties.add("may-not-untap");
336 					}
337 					if (line.startsWith("attacking doesn't cause " + lowerCard
338 							+ " to tap")) {
339 						properties.add("vigilance");
340 					}
341 					if (line.indexOf(lowerCard + " can block as though it had flying") != -1) {
342 						properties.add("block-as-flying");
343 					}
344 					if (line.indexOf(lowerCard + " can't block") != -1) {
345 						properties.add("cannot-block");
346 					}
347 					if (line.indexOf(lowerCard + " can't attack") != -1) {
348 						properties.add("cannot-attack");
349 					}
350 					if (line.indexOf(lowerCard + " is unblockable.") != -1)
351 						properties.add("unblockable");
352 
353 					if (line.indexOf(lowerCard + " is indestructible.") != -1)
354 						properties.add("indestructible");
355 
356 					if (line.indexOf(lowerCard + " can't be countered.") != -1)
357 						properties.add("cannot-be-countered");
358 
359 					if (line.indexOf(lowerCard
360 							+ " can't be the target of spells or abilities.") != -1)
361 						properties.add("untargetable");
362 
363 					if (line.indexOf(lowerCard + " attacks each turn if able.") != -1)
364 						properties.add("attacks-if-able");
365 
366 					if (line.indexOf(lowerCard + " can't be blocked by walls.") != -1)
367 						properties.add("cannot-be-blocked-by-walls");
368 
369 					line = updateProperties(line, properties);
370 					lineBuffer.add(line);
371 				}
372 
373 				cardText.append(" -->");
374 				out.println("<?xml version='1.0'?>");
375 
376 				out.print("<card xmlns='");
377 				out.println(IdConst.NAME_SPACE + "'");
378 				out.print("\txmlns:xsi='");
379 				out.print(XmlParser.W3C_XML_SCHEMA);
380 				out.println("'");
381 				out.print("\txsi:schemaLocation='");
382 				out.println(IdConst.NAME_SPACE + " ../../" + IdConst.TBS_XSD + "'");
383 				out.println("\tname=\"" + cardName + "\">");
384 				out.println("<rules-author-comment>Oracle2Xml generator "
385 						+ IdConst.VERSION + "</rules-author-comment>\n");
386 				out.println(cardText.toString());
387 				out.println("\n\t<!-- COMPLETE THE CODE OF THIS CARD -->\n");
388 				out.println("\t<init>");
389 				out.println("\t\t<registers>");
390 				if (manaCost != null) {
391 					for (int i = 6; i-- > 0;) {
392 						if (manaCost[i] > 0) {
393 							out.println("\t\t\t<register index='" + extractColor(i)
394 									+ "' value='" + manaCost[i] + "'/>");
395 						}
396 					}
397 				}
398 				// power / toughness
399 				if (isCreature) {
400 					if (power.indexOf("*") != -1) {
401 						// power depends on ...
402 						out.println("\t\t\t<register index='power'>");
403 						out.println("\t\t\t\t<!-- REPLACE THIS CODE -->");
404 						out.println("\t\t\t\t<value><counter restriction-zone='play'>");
405 						out.println("\t\t\t\t\t<and>");
406 						out.println("\t\t\t\t\t\t<has-idcard idcard='swamp'/>");
407 						out.println("\t\t\t\t\t\t<controller player='you'/>");
408 						out.println("\t\t\t\t\t</and>");
409 						out.println("\t\t\t\t</counter></value>");
410 						out.println("\t\t\t</register>");
411 					} else {
412 						out
413 								.println("\t\t\t<register index='power' value='" + power
414 										+ "'/>");
415 					}
416 					if (toughness.indexOf("*") != -1) {
417 						// toughness depends on ...
418 						out.println("\t\t\t<register index='toughness'>");
419 						out.println("\t\t\t\t<!-- REPLACE THIS CODE -->");
420 						out.println("\t\t\t\t<value><counter restriction-zone='play'>");
421 						out.println("\t\t\t\t\t<and>");
422 						out.println("\t\t\t\t\t\t<has-idcard idcard='swamp'/>");
423 						out.println("\t\t\t\t\t\t<controller player='you'/>");
424 						out.println("\t\t\t\t\t</and>");
425 						out.println("\t\t\t\t</counter></value>");
426 						out.println("\t\t\t</register>");
427 					} else {
428 						out.println("\t\t\t<register index='toughness' value='" + toughness
429 								+ "'/>");
430 					}
431 				}
432 				out.println("\t\t</registers>");
433 
434 				// colors
435 				if (manaCost != null && manaCost.length > 0) {
436 					out.print("\t\t<colors>");
437 					for (int i = manaCost.length - 1; i-- > 1;) {
438 						if (manaCost[i] > 0) {
439 							out.print(extractColor(i));
440 							if (i > 0) {
441 								out.print(" ");
442 							}
443 						}
444 					}
445 					out.println("</colors>");
446 				}
447 
448 				// idcards
449 				out.print("\t\t<idcards>");
450 				if (isCreature) {
451 					out.print("creature ");
452 				}
453 				if (isNonBasicLand) {
454 					out.print("land ");
455 					if (isArtifact) {
456 						out.print("artifact ");
457 					}
458 				} else if (isAura) {
459 					out.print("local-enchantment ");
460 				} else if (isEnchantWorld) {
461 					out.print("enchant-world ");
462 				} else if (isGlobalEnchant) {
463 					out.print("global-enchantment ");
464 				} else if (isInstant) {
465 					out.print("instant ");
466 				} else if (isArtifact) {
467 					out.print("artifact ");
468 				} else if (isSorcery) {
469 					out.print("sorcery ");
470 				}
471 				if (isSwamp) {
472 					out.print("swamp ");
473 				}
474 				if (isIsland) {
475 					out.print("island ");
476 				}
477 				if (isForest) {
478 					out.print("forest ");
479 				}
480 				if (isMountain) {
481 					out.print("mountain ");
482 				}
483 				if (isPlains) {
484 					out.print("plains ");
485 				}
486 				out.println("</idcards>");
487 
488 				// properties
489 				if (!properties.isEmpty()) {
490 					out.print("\t\t<properties>");
491 					for (String property : properties) {
492 						out.print(property);
493 						out.print(" ");
494 					}
495 					out.println("</properties>");
496 				}
497 				out.println("\t</init>");
498 
499 				if (!lineBuffer.isEmpty()) {
500 					line = lineBuffer.get(0);
501 				}
502 				if (hasFlashBack) {
503 					out.println("\t\t<action reference-name='main-effects'>");
504 					/*
505 					 * if (line.indexOf(':') != -1) { writeActions(out,
506 					 * line.substring(line.indexOf(':') + 1), true); }
507 					 */
508 					writeActions(out, line, true, false);
509 					out
510 							.println("\t\t\t\t<!-- PUT HERE EFFECTS OF THIS SPELL. THIS WILL BE INCLUDED TO FLASHBACK TOO -->");
511 					out.println("\t\t</action>");
512 					out.println("\t</actions>");
513 				}
514 
515 				// abilities
516 				out.println("\t<abilities>");
517 				if (isAura) {
518 					out.println("\t\t<ability ref='cast-enchant'/>");
519 				} else if (isCreature || isGlobalEnchant) {
520 					if (hasAffinity) {
521 						out.println("\t\t<ability ref='cast-spell'>");
522 						out.println("\t\t\t<actions>");
523 						writeAffinity(out, hasAffinityLine);
524 						out.println("\t\t\t</actions>");
525 						out.println("\t\t</ability>");
526 					} else {
527 						out.println("\t\t<ability ref='cast-spell'/>");
528 					}
529 				} else if (isNonBasicLand || isForest || isPlains || isIsland
530 						|| isSwamp || isMountain) {
531 					out.println("\t\t<ability ref='cast-land'/>");
532 				}
533 
534 				if (hasForecast) {
535 					out.println("\t\t<ability ref='reset-forecast' />");
536 					out.println("\t\t<ability ref='forecast'>");
537 					out.println("\t\t\t<actions>");
538 					writeCost(out, hasForecastLine, null);
539 					out.println("\t\t\t</actions>");
540 					out.println("\t\t\t<actions>");
541 					out.println("\t\t\t\t<!-- PUT HERE THE EFFECTS OF FORECAST -->");
542 					out.println("\t\t\t</actions>");
543 					out.println("\t\t</ability>");
544 				}
545 
546 				if (isInstant || isSorcery) {
547 					out.println("\t\t<activated-ability "
548 							+ (hasBuyBack || hasFlashBack ? "reference-name='main-ability' "
549 									: "") + "playable='this' name='' zone='hand'>");
550 					out.println("\t\t\t<cost>");
551 					out.println("\t\t\t\t<pay-mana value='manacost'/>");
552 					if (hasAffinity)
553 						writeAffinity(out, hasAffinityLine);
554 					writeXmanaCost(out, manaCost, false);
555 					if (hasFlashBack) {
556 						out
557 								.println("\t\t\t\t<!-- PUT HERE THE COST OF THIS SPELL. THIS WILL NOT BE INCLUDED TO FLASHBACK COST -->");
558 						out.println("\t\t\t</cost>");
559 						out.println("\t\t\t<effects>");
560 						out.println("\t\t\t\t<action ref='main-effects'/>");
561 						out.println("\t\t\t\t<action ref='finish-spell'/>");
562 
563 					} else {
564 						if (line.indexOf("at the beginning of") != -1) {
565 							out.println("\t\t<create-ability>");
566 							out
567 									.println("\t\t\t<!-- UPDATE PHASE NAME, TYPE and RESOLUTION -->");
568 							out
569 									.println("\t\t\t<triggered-ability resolution='normal' zone='play'>");
570 							out.println("\t\t\t\t<beginning-of-phase phase='upkeep'>");
571 							out.println("\t\t\t\t\t<test ref='during-your-upkeep'/>");
572 							out.println("\t\t\t\t</beginning-of-phase>");
573 							out.println("\t\t\t\t<effects>");
574 							writeActions(out, line, true, false);
575 							out
576 									.println("\t\t\t\t\t<!-- PUT HERE EFFECTS OF THIS DELAYED CARD -->");
577 							out.println("\t\t\t\t\t<unregister-this/>");
578 							out.println("\t\t\t\t</effects>");
579 							out.println("\t\t\t</triggered-ability>");
580 							out.println("\t\t</create-ability>");
581 						}
582 						if (line.indexOf(':') != -1) {
583 							writeActions(out, line.substring(0, line.indexOf(':')), true,
584 									false);
585 						} else {
586 							line = writeCost(out, "", line);
587 						}
588 						if (line.indexOf("as an additional cost to play " + lowerCard) != -1) {
589 							writeActions(out, line
590 									.substring(("as an additional cost to play " + lowerCard)
591 											.length()), true, false);
592 						}
593 						out.println("\t\t\t\t<!-- PUT HERE THE COST OF THIS SPELL -->");
594 						out.println("\t\t\t</cost>");
595 						out.println("\t\t\t<effects>");
596 						for (String subLine : lineBuffer) {
597 							writeActions(out, subLine, false, false);
598 						}
599 						out.println("\t\t\t\t<!-- PUT HERE EFFECTS OF THIS SPELL -->");
600 						out.println("\t\t\t\t<action ref='finish-spell'/>");
601 					}
602 					out.println("\t\t\t</effects>");
603 					out.println("\t\t</activated-ability>");
604 				}
605 
606 				// Rampage
607 				if (hasRampage) {
608 					out.println("\t\t<ability ref='rampage" + hasRampageCount + "'/>");
609 				}
610 
611 				// Transmute
612 				if (hasTransmute) {
613 					out.println("\t\t<ability ref='transmute'>");
614 					out.println("\t\t\t<actions>");
615 					writeCost(out, hasTransmuteCost, null);
616 					out.println("\t\t\t</actions>");
617 					out.println("\t\t</ability>");
618 				}
619 
620 				// Dredge
621 				if (hasDredge) {
622 					out.println("\t\t<ability ref='rampage" + hasDredgeCount + "'/>");
623 				}
624 
625 				// Haunt
626 				if (hasHaunt) {
627 					out.println("\t\t<ability ref='haunt'/>");
628 				}
629 
630 				// BloodThirst
631 				if (hasBloodThirst) {
632 					out.println("\t\t<ability ref='bloodthirst" + hasBloodThirstCount
633 							+ "'/>");
634 				}
635 
636 				// Bushido
637 				if (hasBushido) {
638 					out.println("\t\t<ability ref='bushido" + hasBushidoCount
639 							+ "-blocked'/>");
640 					out.println("\t\t<ability ref='bushido" + hasBushidoCount
641 							+ "-blocking'/>");
642 				}
643 
644 				// Buyback
645 				if (hasBuyBack) {
646 					line = hasBuyBackLine;
647 					out
648 							.println("\t\t<activated-ability playable='this' name='buyback%a' zone='hand'>");
649 					out.println("\t\t\t<cost>");
650 					out.println("\t\t\t\t<action ref='buyback'/>");
651 					writeCost(out, line, null);
652 					out
653 							.println("\t\t\t\t<!-- PUT HERE THE COST OF BUYBACK, AND COMPLETE THE MAIN ABILITY OF THE SPELL -->");
654 					out.println("\t\t\t\t<insert-ability ref='main-ability'/>");
655 					out.println("\t\t\t</cost>");
656 					out.println("\t\t</activated-ability>");
657 				}
658 
659 				// Flashback
660 				if (hasFlashBack) {
661 					line = hasFlashBackLine;
662 					out
663 							.println("\t\t<activated-ability playable='this' name='flashback%a' zone='graveyard'>");
664 					out.println("\t\t\t<cost>");
665 					out.println("\t\t\t\t<action ref='flashback'/>");
666 					writeCost(out, line, null);
667 					out
668 							.println("\t\t\t\t<!-- PUT HERE THE COST OF FLASHBACK, AND COMPLETE THE MAIN ABILITY OF THE SPELL -->");
669 					out.println("\t\t\t\t<insert-ability ref='main-ability'/>");
670 					out.println("\t\t\t</cost>");
671 					out.println("\t\t\t<effects>");
672 					out.println("\t\t\t\t<action ref='main-effects'/>");
673 					out.println("\t\t\t</effects>");
674 					out.println("\t\t</activated-ability>");
675 				}
676 
677 				// Flanking
678 				if (hasFlanking) {
679 					out.println("\t\t<ability ref='flanking'/>");
680 				}
681 
682 				// Haunting
683 				if (hasHaunting) {
684 					out.println("\t\t<ability ref='haunting'/>");
685 				}
686 
687 				// Fading
688 				if (hasFading) {
689 					out.println("\t\t<ability ref='fading'/>");
690 				}
691 
692 				for (int k = 0; k < lineBuffer.size(); k++) {
693 					line = lineBuffer.get(k);
694 
695 					// morph
696 					boolean hasMorph = false;
697 
698 					if (line.indexOf("morph") == 0) {
699 						hasMorph = true;
700 						out.println("\t\t<ability ref=\"cast-morph\"/>");
701 						out
702 								.println("\t\t<activated-ability playable=\"instant\" zone=\"play\" resolution=\"auto\" name=\"morph\">");
703 						out.println("\t\t\t<test>");
704 						out.println("\t\t\t\t<not>");
705 						out.println("\t\t\t\t\t<is-face-up card=\"this\"/>");
706 						out.println("\t\t\t\t</not>");
707 						out.println("\t\t\t</test>");
708 						out.println("\t\t\t<cost>");
709 						writeCost(out, line.substring("morph".length()), null);
710 						out.println("\t\t\t</cost>");
711 						out.println("\t\t\t<effects>");
712 						out.println("\t\t\t\t<action ref=\"morph\"/>");
713 						out.println("\t\t\t</effects>");
714 						out.println("\t\t</activated-ability>");
715 					}
716 
717 					if (line.indexOf(lowerCard + " comes into play tapped") != -1) {
718 						out.println("\t\t<ability ref='come-into-play-tapped'/>");
719 					}
720 
721 					if (!isInstant && !isSorcery && line.length() > 0
722 							&& line.indexOf(':') != -1) {
723 						// activated abilities
724 						out
725 								.println("\t\t<activated-ability playable='instant' name='' zone='play'>");
726 
727 						// test part
728 						if (hasMorph) {
729 							out.println("\t\t\t<test>");
730 							out.println("\t\t\t\t<is-faceup card=\"me\"/>");
731 							out.println("\t\t\t</test>");
732 						}
733 
734 						// 1) cost part
735 						out.println("\t\t\t<cost>");
736 						out.println("\t\t\t\t<!-- PUT HERE THE COST OF THIS ABILITY -->");
737 						writeCost(out, line.substring(0, line.indexOf(':')), line
738 								.substring(line.indexOf(':') + 1));
739 						writeActions(out, line.substring(0, line.indexOf(':')), true, true);
740 
741 						// 2) effect part
742 						out.println("\t\t\t</cost>");
743 						out.println("\t\t\t<effects>");
744 						out.println("\t\t\t\t<!-- PUT HERE EFFECTS OF THIS ABILITY -->");
745 						if (line.indexOf(":") != -1) {
746 							writeActions(out, line.substring(line.indexOf(':') + 1), false,
747 									false);
748 						} else {
749 							writeActions(out, line, false, false);
750 						}
751 						out.println("\t\t\t</effects>");
752 						out.println("\t\t</activated-ability>");
753 					}
754 
755 					if (line.indexOf("when") != -1 || line.indexOf("whenever") != -1) {
756 						if (line.indexOf("comes into play") != -1) {
757 							out.println("\t\t<triggered-ability zone='play'>");
758 							out.println("\t\t\t<moved-card>");
759 							out.println("\t\t\t\t<source-test>");
760 							if (line.indexOf("when " + lowerCard + " comes into play") != -1) {
761 								out.println("\t\t\t\t\t<and>");
762 								out.println("\t\t\t\t\t\t<is-this/>");
763 								out.println("\t\t\t\t\t\t<not>");
764 								out
765 										.println("\t\t\t\t\t\t\t<in-zone zone='play' card='tested'/>");
766 								out.println("\t\t\t\t\t\t</not>");
767 								out
768 										.println("\t\t\t\t\t\t<!-- PUT HERE ADDITIONAL TEST ON CARD BEFORE IT GOES TO PLAY -->");
769 								out.println("\t\t\t\t\t</and>");
770 							} else {
771 								out
772 										.println("\t\t\t\t<!-- PUT HERE ADDITIONAL TEST ON CARD BEFORE IT GOES TO PLAY -->");
773 							}
774 							out.println("\t\t\t\t</source-test>");
775 							out.println("\t\t\t\t<destination-test>");
776 							out
777 									.println("\t\t\t\t\t<!-- PUT HERE ADDITIONAL TEST ON CARD WHEN IT GOES TO PLAY -->");
778 							out.println("\t\t\t\t\t<in-zone zone='play' card='tested'/>");
779 							out.println("\t\t\t\t</destination-test>");
780 							out.println("\t\t\t</moved-card>");
781 						} else if (line.indexOf(" is put into ") < line
782 								.indexOf("graveyard from ")) {
783 							out.println("\t\t<triggered-ability zone='graveyard'>");
784 							out.println("\t\t\t<moved-card>");
785 							out.println("\t\t\t\t<source-test>");
786 							out
787 									.println("\t\t\t\t\t<!-- UPDATE TEST ON CARD BEFORE IT GOES TO GRAVEYARD -->");
788 							out.println("\t\t\t\t\t<and>");
789 							out.println("\t\t\t\t\t\t<is-this/>");
790 							out.println("\t\t\t\t\t\t<in-zone zone='play' card='tested'/>");
791 							out.println("\t\t\t\t\t</and>");
792 							out.println("\t\t\t\t</source-test>");
793 							out.println("\t\t\t\t<destination-test>");
794 							out
795 									.println("\t\t\t\t\t<!-- PUT HERE ADDITIONAL TEST ON CARD WHEN IT GOES TO GRAVEYARD -->");
796 							out
797 									.println("\t\t\t\t\t<in-zone zone='graveyard' card='tested'/>");
798 							out.println("\t\t\t\t</destination-test>");
799 							out.println("\t\t\t</moved-card>");
800 						} else if (line.indexOf(" leaves play") != -1) {
801 							out.println("\t\t<triggered-ability zone='graveyard'>");
802 							out.println("\t\t\t<moved-card>");
803 							out.println("\t\t\t\t<source-test>");
804 							out
805 									.println("\t\t\t\t\t<!-- COMPLETE TEST ON CARD BEFORE IT LEAVE PLAY -->");
806 							out.println("\t\t\t\t\t\t\t<in-zone zone='play' card='tested'/>");
807 							out.println("\t\t\t\t</source-test>");
808 							out.println("\t\t\t</moved-card>");
809 						} else if (line.indexOf("blocks") != -1
810 								|| line.indexOf("becomes blocked") != -1) {
811 							out.println("\t\t<triggered-ability zone='play'>");
812 							out.println("\t\t\t<declared-blocking>");
813 							out.println("\t\t\t\t<blocking-test>");
814 							out
815 									.println("\t\t\t\t\t<!-- COMPLETE THE TEST APPLIED ON BLOCKING CREATURE -->");
816 							out.println("\t\t\t\t</blocking-test>");
817 							out.println("\t\t\t\t<attacking-test>");
818 							out
819 									.println("\t\t\t\t\t<!-- COMPLETE THE TEST APPLIED ON ATTACKING CREATURE -->");
820 							out.println("\t\t\t\t</attacking-test>");
821 							out.println("\t\t\t</declared-blocking>");
822 						} else if (line.indexOf("attacks and isn't blocked") != -1) {
823 							out.println("\t\t<triggered-ability zone='play'>");
824 							out
825 									.println("\t\t\t<modified-register operation='or' register='card' index='state'>");
826 							out.println("\t\t\t\t<source-test>");
827 							out
828 									.println("\t\t\t\t\t<!-- COMPLETE THE TEST APPLIED ON UNBLOCKED CREATURE -->");
829 							out.println("\t\t\t\t\t<is-this/>");
830 							out.println("\t\t\t\t</source-test>");
831 							out.println("\t\t\t</modified-register>");
832 						} else if (line.indexOf("deals combat damage to a player") != -1) {
833 							out.println("\t\t<triggered-ability zone='play'>");
834 							out.println("\t\t\t<assigned-damage type='damage-combat'>");
835 							out.println("\t\t\t\t<source-test>");
836 							out.println("\t\t\t\t\t<is-this/>");
837 							out.println("\t\t\t\t</source-test>");
838 							out.println("\t\t\t\t<destination-test>");
839 							out.println("\t\t\t\t\t<is-player/>");
840 							out.println("\t\t\t\t</destination-test>");
841 							out.println("\t\t\t</assigned-damage>");
842 						} else if (line.indexOf("deals damage to") != -1) {
843 							out.println("\t\t<triggered-ability zone='play'>");
844 							out.println("\t\t\t<assigned-damage type='damage-any'>");
845 							out.println("\t\t\t\t<source-test>");
846 							out.println("\t\t\t\t\t<is-this/>");
847 							out.println("\t\t\t\t</source-test>");
848 							out.println("\t\t\t\t<destination-test>");
849 							out.println("\t\t\t\t\t<and>");
850 							out.println("\t\t\t\t\t\t<not>");
851 							out.println("\t\t\t\t\t\t<is-player/>");
852 							out.println("\t\t\t\t\t\t</not>");
853 							out.println("\t\t\t\t\t\t<has-idcard idcard='creature'/>");
854 							out.println("\t\t\t\t\t</and>");
855 							out.println("\t\t\t\t</destination-test>");
856 							out.println("\t\t\t</assigned-damage>");
857 						} else if (line.indexOf("deals combat damage to") != -1) {
858 							out.println("\t\t<triggered-ability zone='play'>");
859 							out.println("\t\t\t<assigned-damage type='damage-combat'>");
860 							out.println("\t\t\t\t<source-test>");
861 							out.println("\t\t\t\t\t<is-this/>");
862 							out.println("\t\t\t\t</source-test>");
863 							out.println("\t\t\t\t<destination-test>");
864 							out.println("\t\t\t\t\t<and>");
865 							out.println("\t\t\t\t\t\t<not>");
866 							out.println("\t\t\t\t\t\t<is-player/>");
867 							out.println("\t\t\t\t\t\t</not>");
868 							out.println("\t\t\t\t\t\t<has-idcard idcard='creature'/>");
869 							out.println("\t\t\t\t\t</and>");
870 							out.println("\t\t\t\t</destination-test>");
871 							out.println("\t\t\t</assigned-damage>");
872 						} else if (line.indexOf("deals damage to a player") != -1) {
873 							out.println("\t\t<triggered-ability zone='play'>");
874 							out.println("\t\t\t<assigned-damage type='damage-any'>");
875 							out.println("\t\t\t\t<source-test>");
876 							out.println("\t\t\t\t\t<is-this/>");
877 							out.println("\t\t\t\t</source-test>");
878 							out.println("\t\t\t\t<destination-test>");
879 							out.println("\t\t\t\t\t<is-player/>");
880 							out.println("\t\t\t\t</destination-test>");
881 							out.println("\t\t\t</assigned-damage>");
882 						} else if (line.indexOf("becomes unapped") != -1) {
883 							out.println("\t\t<triggered-ability zone='play'>");
884 							out.println("\t\t\t<become-untapped>");
885 							out.println("\t\t\t\t<test>");
886 							out
887 									.println("\t\t\t\t\t<!-- COMPLETE THE TEST APPLIED ON UNTAPPING CARD -->");
888 							out.println("\t\t\t\t\t<is-this card='tested'/>");
889 							out.println("\t\t\t\t</test>");
890 							out.println("\t\t\t</become-untapped>");
891 						} else if (line.indexOf("becomes tapped") != -1) {
892 							out.println("\t\t<triggered-ability zone='play'>");
893 							out.println("\t\t\t<become-tapped>");
894 							out.println("\t\t\t\t<test>");
895 							out
896 									.println("\t\t\t\t\t<!-- COMPLETE THE TEST APPLIED ON TAPPING CARD -->");
897 							out.println("\t\t\t\t\t<is-this card='tested'/>");
898 							out.println("\t\t\t\t</test>");
899 							out.println("\t\t\t</become-tapped>");
900 						} else if (line.indexOf("attacks") != -1) {
901 							out.println("\t\t<triggered-ability zone='play'>");
902 							out.println("\t\t\t<declared-blocking>");
903 							out.println("\t\t\t\t<blocking-test>");
904 							out.println("\t\t\t\t\t<is-this/>");
905 							out
906 									.println("\t\t\t\t\t<!-- COMPLETE THE TEST APPLIED ON BLOCKING CREATURE -->");
907 							out.println("\t\t\t\t</blocking-test>");
908 							out.println("\t\t\t\t<attacking-test>");
909 							out
910 									.println("\t\t\t\t\t<!-- COMPLETE THE TEST APPLIED ON ATTACKING CREATURE -->");
911 							out.println("\t\t\t\t</attacking-test>");
912 							out.println("\t\t\t</declared-blocking>");
913 						} else {
914 							out.println("\t\t<triggered-ability zone='play'>");
915 							out
916 									.println("\t\t\t\t\t<!-- UPDATE THE EVENT OF THIS TRIGGERED ABILITY -->");
917 							out.println("\t\t\t<become-tapped>");
918 							out.println("\t\t\t\t<test>");
919 							out
920 									.println("\t\t\t\t\t<!-- COMPLETE THE TEST APPLIED ON TAPPING CARD -->");
921 							out.println("\t\t\t\t\t<is-this card='tested'/>");
922 							out.println("\t\t\t\t</test>");
923 							out.println("\t\t\t</become-tapped>");
924 						}
925 						if (line.contains("target")) {
926 							out.println("\t\t\t<cost>");
927 							writeTarget(out, line, true);
928 							out.println("\t\t\t</cost>");
929 						}
930 						out.println("\t\t\t<effects>");
931 						writeActions(out, line, false, false);
932 						out
933 								.println("\t\t\t\t<!-- PUT HERE EFFECTS OF THIS TRIGGERED ABILITY -->");
934 						out.println("\t\t\t</effects>");
935 						out.println("\t\t</triggered-ability>");
936 					} else if (line.indexOf("cycling") != -1) {
937 						// Cycling
938 						out.println("\t\t<ability ref='cycling'>");
939 						out.println("\t\t\t<actions>");
940 						writeCost(out, line.substring(
941 								line.indexOf("cycling") + "cycling".length()).trim(), null);
942 						out.println("\t\t\t</actions>");
943 						out.println("\t\t</ability>");
944 					} else if (line.indexOf("echo") != -1) {
945 						// Echo
946 						out.println("\t\t<ability ref='echo'>");
947 						out.println("\t\t\t<actions>");
948 						writeCost(out, line.substring(
949 								line.indexOf("echo") + "echo".length()).trim(), null);
950 						out.println("\t\t\t</actions>");
951 						out.println("\t\t</ability>");
952 					} else if (line.indexOf("at the beginning of") != -1) {
953 						// at the beginning of
954 						if (!isInstant && !isSorcery) {
955 							// a simple triggered ability
956 							out
957 									.println("\t\t\t<!-- UPDATE PHASE NAME, TYPE and RESOLUTION -->");
958 							out
959 									.println("\t\t<triggered-ability resolution='normal' zone='play'>");
960 							out.println("\t\t\t<beginning-of-phase phase='upkeep'>");
961 							out.println("\t\t\t\t<test ref='during-your-upkeep'/>");
962 							out.println("\t\t\t</beginning-of-phase>");
963 							if (line.indexOf("unless") != -1) {
964 								out.println("\t\t\t<cost>");
965 								out.println("\t\t\t\t<choice cancel='false'>");
966 								out.println("\t\t\t\t\t<either>");
967 								out.println("\t\t\t\t\t\t<pay-mana colorless='1'/>");
968 								out.println("\t\t\t\t\t</either>");
969 								out.println("\t\t\t\t\t<either>");
970 								out.println("\t\t\t\t\t\t<action ref='sacrifice-this'/>");
971 								out.println("\t\t\t\t\t</either>");
972 								out.println("\t\t\t\t</choice>");
973 								out.println("\t\t\t</cost>");
974 							} else {
975 								out.println("\t\t\t<effects>");
976 								writeActions(out, line, false, false);
977 								out
978 										.println("\t\t\t\t<!-- PUT HERE EFFECTS OF THIS TRIGGERED ABILITY -->");
979 								out.println("\t\t\t</effects>");
980 							}
981 							out.println("\t\t</triggered-ability>");
982 						}
983 					} else if (line.indexOf("cumulative upkeep") != -1) {
984 						// Cumulative upkeep
985 						out.println("\t\t<ability ref='cumulative-upkeep'/>");
986 						out
987 								.println("\t\t<triggered-ability resolution='normal' zone='play' name='cumulative-upkeep'>");
988 						out.println("\t\t\t<beginning-of-phase phase='upkeep'>");
989 						out.println("\t\t\t\t<test ref='during-your-upkeep'/>");
990 						out.println("\t\t\t</beginning-of-phase>");
991 						out.println("\t\t\t<cost>");
992 						out.println("\t\t\t\t<choice cancel='false'>");
993 						out.println("\t\t\t\t\t<either>");
994 						out.println("\t\t\t\t\t\t<!-- PUT HERE THE ACTION(S) TO PAY -->");
995 						out.println("\t\t\t\t\t\t<action ref='pay-life'/>");
996 						out.println("\t\t\t\t\t\t\t<value>");
997 						out
998 								.println("\t\t\t\t\t\t\t\t<counter object-name='age' card='this'/>");
999 						out.println("\t\t\t\t\t\t\t</value>");
1000 						out.println("\t\t\t\t\t\t</action/>");
1001 						out.println("\t\t\t\t\t</either>");
1002 						out.println("\t\t\t\t\t<either>");
1003 						out.println("\t\t\t\t\t\t<action ref='sacrifice-this'/>");
1004 						out.println("\t\t\t\t\t</either>");
1005 						out.println("\t\t\t\t</choice>");
1006 						out.println("\t\t\t</cost>");
1007 						out.println("\t\t</triggered-ability>");
1008 					}
1009 				}
1010 				out.println("\t</abilities>");
1011 
1012 				// Fading counter
1013 				if (hasFading) {
1014 					out.println("\t<modifiers>");
1015 					int fadingCounter = Integer.parseInt(hasFadingLine);
1016 					if (fadingCounter == Integer.MIN_VALUE) {
1017 						fadingCounter = 1;
1018 					}
1019 					for (int i = fadingCounter; i-- > 0;) {
1020 						out.println("\t\t<object name='fade'/>");
1021 					}
1022 					out.println("\t</modifiers>");
1023 				}
1024 
1025 				// Attachment
1026 				if (isAura) {
1027 					out.println("\t<attachment>");
1028 					out.println("\t\t<modifiers>");
1029 					out.println("\t\t\t<!-- TODO Add the additional modifiers here");
1030 					out
1031 							.println("\t\t\t<register-modifier index='power' value='1' operation='add' linked='true' />");
1032 					out
1033 							.println("\t\t\t<register-modifier index='toughness' value='1' operation='add' linked='true' />");
1034 					out.println("\t\t\t-->");
1035 					out.println("\t</modifiers>");
1036 
1037 					if (isLocalEnchantCreature) {
1038 						out.println("\t\t<valid-target ref='valid-creature-to-enchant' />");
1039 						out
1040 								.println("\t\t<valid-attachment ref='valid-enchant-creature' />");
1041 
1042 					} else if (isLocalEnchantLand) {
1043 						out.println("\t\t<valid-target ref='valid-land-to-enchant' />");
1044 						out.println("\t\t<valid-attachment ref='valid-enchant-land' />");
1045 
1046 					} else if (isLocalEnchantArtifact) {
1047 						out.println("\t\t<valid-target ref='valid-artifact-to-enchant' />");
1048 						out
1049 								.println("\t\t<valid-attachment ref='valid-enchant-artifact' />");
1050 
1051 					} else if (isLocalEnchantEnchantment) {
1052 						out
1053 								.println("\t\t<valid-target ref='valid-enchantment-to-enchant' />");
1054 						out
1055 								.println("\t\t<valid-attachment ref='valid-enchant-enchantment' />");
1056 
1057 					} else if (isLocalEnchantCreatureArtifact) {
1058 						out
1059 								.println("\t\t<valid-target ref='valid-artifact-creature-to-enchant' />");
1060 						out
1061 								.println("\t\t<valid-attachment ref='valid-enchant-artifact-creature' />");
1062 
1063 					} else if (isLocalEnchantPermanent) {
1064 						out.println("\t\t<valid-target ref='valid-to-enchant' />");
1065 						out.println("\t\t<valid-attachment ref='valid-enchant' />");
1066 					}
1067 					out.println("\t</modifiers>");
1068 					out.println("\t</attachment>");
1069 				}
1070 				out.println("</card>");
1071 				IOUtils.closeQuietly(out);
1072 				nbCard++;
1073 			}
1074 		} catch (FileNotFoundException e) {
1075 			System.err.println("Error openning file '" + oracleFile + "' : " + e);
1076 		} catch (IOException e) {
1077 			System.err.println("IOError reading file '" + oracleFile + "' : " + e);
1078 		}
1079 		System.out.println("Success Parsing : " + nbCard + " card(s)");
1080 	}
1081 
1082 	/***
1083 	 * <ul>
1084 	 * Argument are (in this order :
1085 	 * <li>Oracle source file
1086 	 * <li>destination directory
1087 	 * </ul>
1088 	 * 
1089 	 * @param args
1090 	 */
1091 	public static void main(String... args) {
1092 		if (args.length != 2) {
1093 			System.err
1094 					.println("Usage : auto-builber <oracle file> <destination directory>");
1095 			System.exit(-1);
1096 			return;
1097 		}
1098 		String oracle = args[0];
1099 		String destination = args[1];
1100 		// the directory destination end with the file separator
1101 		if (!destination.endsWith(File.separator) && !destination.endsWith("/")
1102 				&& !destination.endsWith("//")) {
1103 			destination += File.separator;
1104 		}
1105 
1106 		try {
1107 			new File(destination).mkdirs();
1108 		} catch (Exception e) {
1109 			// Ignore this error and continue
1110 		}
1111 		new Oracle2Xml().serialize(MToolKit.getFile(oracle), MToolKit
1112 				.getFile(destination), MToolKit.getFile("tbs/" + TBS_NAME
1113 				+ "/recycled/"));
1114 	}
1115 
1116 	/***
1117 	 * Write X expression for pay-mana action
1118 	 * 
1119 	 * @param out
1120 	 *          the output were the pay-mana would be written.
1121 	 * @param manaCost
1122 	 *          the mana cost.
1123 	 * @param writeFixPart
1124 	 *          is the fixed part of mana cost is written or not.
1125 	 * @see net.sf.magicproject.xml.action.PayMana
1126 	 */
1127 	private void writeXmanaCost(PrintWriter out, int[] manaCost,
1128 			boolean writeFixPart) {
1129 
1130 		// The fixed part
1131 		if (writeFixPart) {
1132 			out.print("\t\t\t\t<pay-mana ");
1133 			for (int i = 6; i-- > 0;) {
1134 				if (manaCost[i] > 0) {
1135 					out.print(extractColor(i) + "='" + manaCost[i] + "' ");
1136 				}
1137 			}
1138 			out.println("/>");
1139 		}
1140 
1141 		// The X part
1142 		if (manaCost[6] > 0) {
1143 			out
1144 					.println("\t\t\t\t<!-- UPDATE THE TEXT AND AMOUNT OF MIN/MAXI COLORLESS MANA TO PAY -->");
1145 			out
1146 					.println("\t\t\t\t<input-number min='0' controller='you' operation='set' register='stack' index='0' name='%'>");
1147 			out.println("\t\t\t\t\t<text>%x-value</text>");
1148 			if (manaCost[6] > 1) {
1149 				out.println("\t\t\t\t\t<max register='you' index='manapool'/>");
1150 			} else {
1151 				// XX.. like
1152 				out.println("\t\t\t\t\t<max>");
1153 				out.println("\t\t\t\t\t\t<div right='" + manaCost[6] + "'>");
1154 				out.println("\t\t\t\t\t\t\t<left register='you' index='manapool'>");
1155 				out.println("\t\t\t\t\t\t</div>");
1156 				out.println("\t\t\t\t\t</max>");
1157 			}
1158 			out.println("\t\t\t\t</input-number>");
1159 			out.println("\t\t\t\t<pay-mana>");
1160 			out.println("\t\t\t\t\t<colorless register='stack' index='0'/>");
1161 			out.println("\t\t\t\t</pay-mana>");
1162 		}
1163 	}
1164 
1165 	/***
1166 	 * Write X expression for give-mana action
1167 	 * 
1168 	 * @param out
1169 	 *          the output were the pay-mana would be written.
1170 	 * @param actions
1171 	 *          the mana actions.
1172 	 * @param writeFixPart
1173 	 *          is the fixed part of mana cost is written or not.
1174 	 * @see net.sf.magicproject.xml.action.PayMana
1175 	 */
1176 	private String writeXmanaGive(PrintWriter out, String actions,
1177 			boolean writeFixPart) {
1178 
1179 		final int index = actions.indexOf(' ', "add ".length());
1180 		int[] manaCost = extractManaCost(actions.substring("add ".length(), index));
1181 
1182 		// The fixed part
1183 		if (writeFixPart) {
1184 			out.print("\t\t\t\t<give-mana ");
1185 			for (int i = 6; i-- > 0;) {
1186 				if (manaCost[i] > 0) {
1187 					out.print(extractColor(i) + "='" + manaCost[i] + "' ");
1188 				}
1189 			}
1190 			out.println("/>");
1191 		}
1192 
1193 		// The X part
1194 		if (manaCost[6] > 0) {
1195 			out
1196 					.println("\t\t\t\t<!-- UPDATE THE TEXT AND AMOUNT OF MIN/MAXI COLORLESS MANA TO GIVE -->");
1197 			out
1198 					.println("\t\t\t\t<input-number min='0' controller='you' operation='set' register='stack' index='0' name='%'>");
1199 			out.println("\t\t\t\t\t<text>%x-value</text>");
1200 			if (manaCost[6] > 1) {
1201 				out.println("\t\t\t\t\t<max register='you' index='manapool'/>");
1202 			} else {
1203 				// XX.. like
1204 				out.println("\t\t\t\t\t<max>");
1205 				out.println("\t\t\t\t\t\t<div right='" + manaCost[6] + "'>");
1206 				out.println("\t\t\t\t\t\t\t<left register='you' index='manapool'>");
1207 				out.println("\t\t\t\t\t\t</div>");
1208 				out.println("\t\t\t\t\t</max>");
1209 			}
1210 			out.println("\t\t\t\t</input-number>");
1211 			out.println("\t\t\t\t<give-mana>");
1212 			out.println("\t\t\t\t\t<colorless register='stack' index='0'/>");
1213 			out.println("\t\t\t\t</give-mana>");
1214 		}
1215 
1216 		return actions.substring(index + 1);
1217 	}
1218 
1219 	/***
1220 	 * Expected mana structure is [X]*[0-9]+([U][B][G][R][W])*
1221 	 * 
1222 	 * @param line
1223 	 *          The string containing ONLY the manacost.
1224 	 * @return an integer array {colorless, black, blue, green, red, white, x
1225 	 *         occurences}
1226 	 */
1227 	private int[] extractManaCost(String line) {
1228 		final int[] res = new int[7];
1229 		for (int i = 0; i < line.length(); i++) {
1230 			final char mana = line.charAt(i);
1231 			switch (mana) {
1232 			case 'b':
1233 				res[1]++;
1234 				break;
1235 			case 'u':
1236 				res[2]++;
1237 				break;
1238 			case 'g':
1239 				res[3]++;
1240 				break;
1241 			case 'r':
1242 				res[4]++;
1243 				break;
1244 			case 'w':
1245 				res[5]++;
1246 				break;
1247 			case 'x':
1248 				res[6]++;
1249 				break;
1250 			default:
1251 				// colorless mana
1252 				res[0] *= 10;
1253 				res[0] += Character.getNumericValue(mana);
1254 			}
1255 		}
1256 		return res;
1257 	}
1258 
1259 	private static final String[] SACRIFICE = new String[] { "land", "artifact",
1260 			"permanent", "creature", "enchantment" };
1261 
1262 	private static final String[] SACRIFICE_OTHER = new String[] { "plains",
1263 			"forest", "mountain", "swamp", "island" };
1264 
1265 	/***
1266 	 * @param out
1267 	 * @param action
1268 	 */
1269 	private void writeSacrifice(PrintWriter out, String action) {
1270 		// Sacrifice {this}
1271 		if (action.contains("sacrifice " + lowerCard)) {
1272 			out.println("\t\t\t\t<action ref='sacrifice-this'/>");
1273 			return;
1274 		}
1275 		if (lowerCard.contains(",")
1276 				&& action.contains("sacrifice " + lowerCard.split(",")[0].trim())) {
1277 			out.println("\t\t\t\t<action ref='sacrifice-this'/>");
1278 			return;
1279 		}
1280 		if (action.contains("sacrifice it")) {
1281 			out.println("\t\t\t\t\t<!-- PUT THIS ACTION IN A DELAYED ABILITY -->");
1282 			out.println("\t\t\t\t<action ref='sacrifice-this'/>");
1283 			return;
1284 		}
1285 		for (String thing : SACRIFICE) {
1286 			if (action.contains("sacrifice a " + thing)) {
1287 				// Sacrifice a THING
1288 				out.println("\t\t\t\t<action ref='sacrifice-a-" + thing
1289 						+ "' value='1'/>");
1290 				return;
1291 			}
1292 			if (action.contains("sacrifice an " + thing)) {
1293 				// Sacrifice a THING
1294 				out.println("\t\t\t\t<action ref='sacrifice-an-" + thing
1295 						+ "' value='1'/>");
1296 				return;
1297 			}
1298 			if (action.contains("sacrifice two " + thing + "s")) {
1299 				// Sacrifice 2 THINGS
1300 				out.println("\t\t\t\t<action ref='sacrifice-a-" + thing
1301 						+ "' value='2'/>");
1302 				return;
1303 			}
1304 			if (action.contains("opponent sacrifices a " + thing)) {
1305 				// Opponent sacrifices a THING
1306 				out.println("\t\t\t\t<action ref='opponent-sacrifice-a-" + thing
1307 						+ "' value='1'/>");
1308 				return;
1309 			}
1310 			if (action.contains("opponent sacrifices two " + thing + "s")) {
1311 				// Opponent sacrifices two THINGS
1312 				out.println("\t\t\t\t<action ref='opponent-sacrifice-a-" + thing
1313 						+ "' value='2'/>");
1314 				return;
1315 			}
1316 			if (action.contains("opponent sacrifices ")
1317 					&& action.indexOf(thing, action.indexOf("opponent sacrifices ")) != -1) {
1318 				// Opponent sacrifices many THINGS
1319 				out
1320 						.println("\t\t\t\t<action ref='opponent-sacrifice-a-" + thing
1321 								+ "'>");
1322 				out.println("\t\t\t\t\t<!-- UPDATE THIS VALUE -->");
1323 				out.println("\t\t\t\t\t<value register='stack' value='0'/>");
1324 				out.println("\t\t\t\t</action>");
1325 				return;
1326 			}
1327 			if (action.contains(thing)) {
1328 				// Player sacrifice n THINGS
1329 				out
1330 						.println("\t\t\t\t<action ref='opponent-sacrifice-a-" + thing
1331 								+ "'>");
1332 				out.println("\t\t\t\t\t<value>");
1333 				out.println("\t\t\t\t\t<!-- COMPLETE THE AMOUNT OF SACRIFICE -->");
1334 				out.println("\t\t\t\t\t</value>");
1335 				out.println("\t\t\t\t</action>");
1336 				return;
1337 			}
1338 		}
1339 
1340 		for (String sac : SACRIFICE_OTHER) {
1341 			if (action.contains("sacrifice a " + sac)
1342 					|| action.contains("sacrifice an " + sac)) {
1343 				out.println("\t\t\t\t<action ref='sacrifice-a-permanent' value='1'/>");
1344 				out.println("\t\t\t\t\t<test>");
1345 				out.println("\t\t\t\t\t\t<has-idcard idcard='" + sac + "'/>");
1346 				out.println("\t\t\t\t\t</test>");
1347 				out.println("\t\t\t\t</action>");
1348 				return;
1349 			}
1350 		}
1351 
1352 		if (action.contains("sacrifice a")) {
1353 			// Sacrifice a THING
1354 			out.println("\t\t\t\t<action ref='sacrifice-a-permanent' value='1'>");
1355 		} else if (action.contains("sacrifice two ")) {
1356 			// Sacrifice 2 THINGS
1357 			out.println("\t\t\t\t<action ref='sacrifice-a-permanent' value='2'>");
1358 		} else {
1359 			// Sacrifice X THINGS
1360 			out.println("\t\t\t\t<action ref='sacrifice-a-permanent'>");
1361 			out.println("\t\t\t\t\t<!-- UPDATE THIS VALUE -->");
1362 			out.println("\t\t\t\t\t<value register='stack' value='0'/>");
1363 		}
1364 		out.println("\t\t\t\t\t<test>");
1365 		String property = action.substring(action.indexOf("sacrifice ")).split(" ")[2];
1366 		out.println("\t\t\t\t\t\t<has-property property='" + property + "'/>");
1367 		out.println("\t\t\t\t\t</test>");
1368 		out.println("\t\t\t\t</action>");
1369 	}
1370 
1371 	private String writeTarget(PrintWriter out, String action, boolean writeTarget) {
1372 		String tmpString = action;
1373 		if (tmpString.contains("target")) {
1374 
1375 			while (tmpString.indexOf("target ") != -1) {
1376 				if (tmpString.contains("target creature or player")) {
1377 					if (writeTarget) {
1378 						out.println("\t\t\t\t<action ref='target-dealtable'>");
1379 						out.println("\t\t\t\t\t<test>");
1380 						out
1381 								.println("\t\t\t\t\t<!-- COMPLETE THIS TEST ON PLAYER/CREATURE TO TARGET -->");
1382 						out.println("\t\t\t\t\t</test>");
1383 						out.println("\t\t\t\t</action>");
1384 					}
1385 					tmpString = StringUtils.replaceOnce(tmpString,
1386 							"target creature or player", "");
1387 				} else if (tmpString.contains("target player")) {
1388 					if (writeTarget) {
1389 						out.println("\t\t\t\t<action ref='target-player'/>");
1390 					}
1391 					tmpString = StringUtils.replaceOnce(tmpString, "target player", "");
1392 				} else if (tmpString.contains("target opponent")) {
1393 					if (writeTarget) {
1394 						out.println("\t\t\t\t<action ref='target-opponent'/>");
1395 					}
1396 					tmpString = StringUtils.replaceOnce(tmpString, "target opponent", "");
1397 				} else {
1398 					boolean found = false;
1399 					for (int sacrificeI = SACRIFICE.length; sacrificeI-- > 0;) {
1400 						final String thing = SACRIFICE[sacrificeI];
1401 						if (tmpString.contains("target " + thing)) {
1402 							if (writeTarget) {
1403 								out.println("\t\t\t\t<action ref='target-" + thing + "'>");
1404 								out.println("\t\t\t\t\t<test>");
1405 								out.println("\t\t\t\t\t<!-- COMPLETE THIS TEST ON " + thing
1406 										+ " TO TARGET -->");
1407 								out.println("\t\t\t\t\t</test>");
1408 								out.println("\t\t\t\t</action>");
1409 							}
1410 							tmpString = StringUtils.replaceOnce(tmpString, "target " + thing,
1411 									"");
1412 							found = true;
1413 							break;
1414 						}
1415 					}
1416 					if (!found) {
1417 						if (writeTarget) {
1418 							out.println("\t\t\t\t<action ref='target-card'>");
1419 							out.println("\t\t\t\t\t<test>");
1420 							out.println("\t\t\t\t\t<!-- COMPLETE THIS TEST ON TARGET -->");
1421 							out.println("\t\t\t\t\t</test>");
1422 							out.println("\t\t\t\t</action>");
1423 						}
1424 						tmpString = StringUtils.replaceOnce(tmpString, "target ", "");
1425 					}
1426 				}
1427 			}
1428 		}
1429 		return tmpString;
1430 	}
1431 
1432 	/***
1433 	 * Write the given actions comma separated, in the specified output.
1434 	 * 
1435 	 * @param out
1436 	 *          the output were the pay-mana would be written.
1437 	 * @param actionString
1438 	 *          the string containg actions.
1439 	 * @param targetString
1440 	 *          the effects containing any target action.
1441 	 */
1442 	private String writeCost(PrintWriter out, String actionString,
1443 			String targetString) {
1444 		String res = "";
1445 		String[] actions = actionString.replaceAll("--", "").trim().split(", ");
1446 
1447 		for (String action : actions) {
1448 			if (action.matches("[x]*[0-9]+[ubgrw]*")
1449 					|| action.matches("[x]*[0-9]*[ubgrw]+")) {
1450 				// pay-mana
1451 				writeXmanaCost(out, extractManaCost(action), true);
1452 			} else if ("t".equals(action.trim())) {
1453 				// {T}
1454 				out.println("\t\t\t\t<action ref='T'/>");
1455 			} else if (action.contains("sacrifice")) {
1456 				writeSacrifice(out, action);
1457 			} else if (res.length() == 0) {
1458 				res = action;
1459 			} else {
1460 				res += " " + action;
1461 			}
1462 		}
1463 
1464 		if (targetString != null && targetString.contains("target")) {
1465 			// Target actions
1466 			return res + ":" + writeTarget(out, targetString, true);
1467 		} else if (targetString != null) {
1468 			return res + ":" + targetString;
1469 		}
1470 		return res + ":";
1471 	}
1472 
1473 	private void writeActions(PrintWriter out, String pActions,
1474 			boolean writeTarget, boolean ignoreCost) {
1475 		String actions = pActions.replaceAll("--", "");
1476 		boolean startWithSpc = actions.startsWith(" ");
1477 		actions = actions.trim();
1478 
1479 		if (actions.matches("add [x]*[0-9]+[ubgrw]* .*")
1480 				|| actions.matches("add [x]*[0-9]*[ubgrw]+ .*")) {
1481 			// Give mana
1482 			actions = writeXmanaGive(out, actions, true);
1483 		}
1484 
1485 		// return to your hand
1486 		if (actions.indexOf(lowerCard + " to your hand") != -1) {
1487 			out.println("\t\t\t\t<target type='this' />");
1488 			out.println("\t\t\t\t<action ref='return-to-hand'/>");
1489 			actions = StringUtils.replaceOnce(actions, lowerCard + " to your hand",
1490 					"");
1491 		} else if (actions.indexOf("to your hand") != -1) {
1492 			out.println("\t\t\t\t<action ref='return-to-hand'/>");
1493 			actions = StringUtils.replaceOnce(actions, "to your hand", "");
1494 		} else if (actions.indexOf(lowerCard + " to its owner's hand") != -1) {
1495 			out.println("\t\t\t\t<target type='this' />");
1496 			out.println("\t\t\t\t<action ref='return-to-hand'/>");
1497 			actions = StringUtils.replaceOnce(actions, lowerCard
1498 					+ " to its owner's hand", "");
1499 		} else if (actions.indexOf("to its owner's hand") != -1) {
1500 			out.println("\t\t\t\t<action ref='return-to-hand'/>");
1501 			actions = StringUtils.replaceOnce(actions, "to its owner's hand", "");
1502 		}
1503 
1504 		if (actions.indexOf("regenerate " + lowerCard) != -1)
1505 			out.println("\t\t\t\t<action ref='regenerate'/>");
1506 
1507 		// First perform Target action
1508 		writeTarget(out, actions, writeTarget);
1509 
1510 		if (actions.indexOf("enchanted creature gets ") != -1) {
1511 			out.println("\t\t\t\t<target type='attachedto'/>");
1512 			actions = StringUtils.replaceOnce(actions, "enchanted creature", "");
1513 		} else if (actions.indexOf(lowerCard + " gets") != -1) {
1514 			out.println("\t\t\t\t<target type='this'/>");
1515 			actions = StringUtils.replaceOnce(actions, lowerCard, "");
1516 		}
1517 
1518 		if (actions.indexOf("put") != -1 && actions.indexOf("puts") == -1
1519 				&& actions.indexOf("creature token") != -1) {
1520 			if (actions.lastIndexOf("put") < actions.indexOf("creature token")) {
1521 				final int endIndex = actions.indexOf("creature token");
1522 				String tokenAction = actions.substring(actions.lastIndexOf("put") + 4,
1523 						endIndex - 1);
1524 				String[] words = tokenAction.split(" ");
1525 
1526 				if (words.length > 3) {
1527 					out.print("\t\t\t\t<repeat value='");
1528 					if (words[0].compareTo("a") == 0)
1529 						out.println("1'/>");
1530 					else if (words[0].compareTo("two") == 0)
1531 						out.println("2'/>");
1532 					else if (words[0].compareTo("x") == 0)
1533 						out.println("x'/> <!-- NEEDS CODE FOR X TOKENS -->");
1534 					else if (words[0].compareTo("three") == 0)
1535 						out.println("3'/>");
1536 					else if (words[0].compareTo("four") == 0)
1537 						out.println("4'/>");
1538 					else if (words[0].compareTo("five") == 0)
1539 						out.println("5'/>");
1540 					else if (words[0].compareTo("six") == 0)
1541 						out.println("6'/>");
1542 					else if (words[0].compareTo("seven") == 0)
1543 						out.println("7'/>");
1544 					out.println("\t\t\t\t<create-card>");
1545 					if (words.length == 6)
1546 						out.println("\t\t\t\t\t<card name='"
1547 								+ StringUtils.capitalize(words[5]) + "'>");
1548 					else
1549 						out.println("\t\t\t\t\t<card name='"
1550 								+ StringUtils.capitalize(words[3]) + "'>");
1551 					out
1552 							.println("\t\t\t\t\t\t<rules-author-comment></rules-author-comment>");
1553 					out.println("\t\t\t\t\t\t<init>");
1554 					out.println("\t\t\t\t\t\t\t<registers>");
1555 					out.println("\t\t\t\t\t\t\t\t<register index='power' value='"
1556 							+ words[1].charAt(0) + "'/>");
1557 					out.println("\t\t\t\t\t\t\t\t<register index='toughness' value='"
1558 							+ words[1].charAt(2) + "'/>");
1559 					out.println("\t\t\t\t\t\t\t</registers>");
1560 					out.println("\t\t\t\t\t\t\t<colors>" + words[2] + "</colors>");
1561 					List<String> tokenProperties = new ArrayList<String>();
1562 					tokenProperties.add("token");
1563 					if (words.length == 6) {
1564 						out.println("\t\t\t\t\t\t\t<colors>" + words[4] + "</colors>");
1565 						tokenProperties.add(words[5]);
1566 					} else {
1567 						tokenProperties.add(words[3]);
1568 					}
1569 					out.println("\t\t\t\t\t\t\t<idcards>creature</idcards>");
1570 					if (actions.indexOf("with", endIndex) != -1
1571 							&& actions.indexOf("into", endIndex) > actions.indexOf("with",
1572 									endIndex)) {
1573 						updateProperties(actions.substring(actions
1574 								.indexOf("with", endIndex)
1575 								+ "with".length() + 1, actions.indexOf("into", endIndex)),
1576 								tokenProperties);
1577 					}
1578 					out.print("\t\t\t\t\t\t\t<properties>");
1579 					for (String property : tokenProperties) {
1580 						out.print(property);
1581 						out.print(' ');
1582 					}
1583 					out.println("</properties>");
1584 					out.println("\t\t\t\t\t\t</init>");
1585 					out.println("\t\t\t\t\t</card>");
1586 					out.println("\t\t\t\t</create-card>");
1587 					String zone = actions.substring(actions.lastIndexOf("put") + 4);
1588 					zone = zone.substring(zone.indexOf("into") + "into".length()).trim();
1589 					int zoneIndex = zone.indexOf('.');
1590 					if (zoneIndex > zone.indexOf(' ') && zone.indexOf(' ') >= 0) {
1591 						zoneIndex = zone.indexOf(' ');
1592 					}
1593 					if (actions.indexOf("target opponent") != -1
1594 							&& actions.indexOf("target opponent") < actions.indexOf('.')) {
1595 						out
1596 								.print("\t\t\t\t<move-card controller='target-list.first' destination='");
1597 					} else {
1598 						out.print("\t\t\t\t<move-card controller='you' destination='");
1599 					}
1600 					out.print(zone.substring(0, zoneIndex).trim());
1601 					out.println("'/>");
1602 				}
1603 			}
1604 		}
1605 		if (startWithSpc) {
1606 			actions = " " + actions;
1607 		}
1608 
1609 		while (actions.length() > 0) {
1610 			if (actions.startsWith("add [x]*[0-9]+[ubgrw] ")
1611 					|| actions.startsWith("add [x]*[0-9]*[ubgrw]+ ")) {
1612 				// Give mana
1613 				actions = writeXmanaGive(out, actions, true);
1614 			} else if (actions.startsWith("add one mana of any color")) {
1615 				out.println("\t\t\t\t<give-mana black='1'/>");
1616 				out
1617 						.println("\t\t\t\t<!-- DUPLICATE THIS ABILITY WITH THE FOLLOWING ACTIONS OR USE <action ref='tap-add-B'/> REF-ABILITY");
1618 				out.println("\t\t\t\t<give-mana blue='1'/>");
1619 				out.println("\t\t\t\t<give-mana green='1'/>");
1620 				out.println("\t\t\t\t<give-mana red='1'/>");
1621 				out.println("\t\t\t\t<give-mana white='1'/>");
1622 				out.println("\t\t\t\t  -->");
1623 				actions = actions.substring("add one mana of any color".length());
1624 			} else if (actions.startsWith("add two mana of any ")) {
1625 				out.println("\t\t\t\t<give-mana black='2'/>");
1626 				out
1627 						.println("\t\t\t\t<!-- DUPLICATE THIS ABILITY WITH THE FOLLOWING ACTIONS");
1628 				out.println("\t\t\t\t<give-mana blue='2'/>");
1629 				out.println("\t\t\t\t<give-mana green='2'/>");
1630 				out.println("\t\t\t\t<give-mana red='2'/>");
1631 				out.println("\t\t\t\t<give-mana white='2'/>");
1632 				out.println("\t\t\t\t  -->");
1633 				actions = actions.substring("add two mana of any ".length());
1634 			} else if (actions.startsWith("add three mana of any ")) {
1635 				out.println("\t\t\t\t<give-mana black='3'/>");
1636 				out
1637 						.println("\t\t\t\t<!-- DUPLICATE THIS ABILITY WITH THE FOLLOWING ACTIONS");
1638 				out.println("\t\t\t\t<give-mana blue='3'/>");
1639 				out.println("\t\t\t\t<give-mana green='3'/>");
1640 				out.println("\t\t\t\t<give-mana red='3'/>");
1641 				out.println("\t\t\t\t<give-mana white='3'/>");
1642 				out.println("\t\t\t\t  -->");
1643 				actions = actions.substring("add three mana of any ".length());
1644 			} else if (actions.startsWith("remove it from the game at end of turn")) {
1645 				out.println("\t\t\t\t<action ref-'remove-from-game-target-eot'/>");
1646 				actions = actions.substring("remove it from the game at end of turn"
1647 						.length());
1648 			} else if (actions.startsWith("destroy it at end of turn")) {
1649 				out.println("\t\t\t\t<action ref-'destroy-target-eot'/>");
1650 				actions = actions.substring("destroy it at end of turn".length());
1651 			} else if (actions
1652 					.startsWith("can attack this turn as though it didn't have defender")) {
1653 				out.println("\t\t\t\t<action ref='wall-can-attack-until-eot'/>");
1654 				actions = actions
1655 						.substring("can attack this turn as though it didn't have defender"
1656 								.length());
1657 			} else if (actions.startsWith("look at ")
1658 					&& actions.indexOf("hand") != -1) {
1659 				// Look at target opponent's hand
1660 				out.println("\t\t\t\t<show-zone zone='hand' for='you'/>");
1661 				out
1662 						.println("\t\t\t\t<!-- INSERT HERE ACTIONS PERFORMED WHILE HAND IS VISIBLE -->");
1663 				out.println("\t\t\t\t<action ref='restore-hand-visibility'/>");
1664 				actions = actions.substring(actions.indexOf("hand") + "hand".length());
1665 				continue;
1666 			} else if (actions.startsWith("choose a creature type")) {
1667 				// Choose a creature type
1668 				out
1669 						.println("\t\t\t\t<input-property operation='set' index='free0' register='this' values='FIRST_SUB_TYPE..LAST_SUB_TYPE' />");
1670 				actions = actions.substring("choose a creature type".length());
1671 				continue;
1672 			} else if (actions.startsWith("choose a color")) {
1673 				// Choose a color
1674 				out
1675 						.println("\t\t\t\t<input-color operation='set' index='free0' register='this'/>");
1676 				actions = actions.substring("choose a color".length());
1677 				continue;
1678 			} else if (actions.startsWith("search ")) {
1679 				// Search in your library for...
1680 				List<String> idCard = new ArrayList<String>();
1681 				List<String> inIdCard = new ArrayList<String>();
1682 				List<String> color = new ArrayList<String>();
1683 				List<String> property = new ArrayList<String>();
1684 				boolean upTo = actions.indexOf("up to ") != -1;
1685 				if (actions.indexOf("any number of ") != -1) {
1686 					out.println("\t\t\t\t<target-list operation='clear' name='%'/>");
1687 					out.println("\t\t\t\t<target type='you' name='%'/> ");
1688 					out.println("\t\t\t\t<show-zone zone='library' for='you' name='%'/>");
1689 					out
1690 							.println("\t\t\t\t<target mode='choose' type='card' raise-event='false' restriction-zone='library' hop='2' cancel='false' name='search-any'>");
1691 					out.println("\t\t\t\t\t<test>");
1692 					out.println("\t\t\t\t\t\t<controller player='target-list.first'/>");
1693 					out.println("\t\t\t\t\t</test>");
1694 					out.println("\t\t\t\t</target>");
1695 					out.println("\t\t\t\t<hop value='-1' name='%'/>");
1696 					out.println("\t\t\t\t<action ref='restore-library-visibility'/>");
1697 					out.println("\t\t\t\t<shuffle zone='library'/>");
1698 					out
1699 							.println("\t\t\t\t<target-list operation='remove-first' name='%'/> ");
1700 					actions = actions.substring("search ".length());
1701 				}
1702 				boolean isYou = actions.startsWith("search your ");
1703 				if (actions.indexOf("white") != -1) {
1704 					color.add("white");
1705 				}
1706 				if (actions.indexOf("black") != -1) {
1707 					color.add("black");
1708 				}
1709 				if (actions.indexOf("blue") != -1) {
1710 					color.add("blue");
1711 				}
1712 				if (actions.indexOf("green") != -1) {
1713 					color.add("green");
1714 				}
1715 				if (actions.indexOf("red") != -1) {
1716 					color.add("red");
1717 				}
1718 				if (actions.indexOf("artifact") != -1) {
1719 					idCard.add("artifact");
1720 				} else if (actions.indexOf("creature") != -1) {
1721 					idCard.add("creature");
1722 				}
1723 				if (actions.indexOf("enchantment") != -1) {
1724 					idCard.add("enchantment");
1725 				}
1726 				if (actions.indexOf("sorcery") != -1) {
1727 					idCard.add("sorcery");
1728 				}
1729 				if (actions.indexOf("instant") != -1) {
1730 					idCard.add("instant");
1731 				}
1732 				if (actions.indexOf("island") != -1) {
1733 					idCard.add("island");
1734 				}
1735 				if (actions.indexOf("swamp") != -1) {
1736 					idCard.add("swamp");
1737 				}
1738 				if (actions.indexOf("forest") != -1) {
1739 					idCard.add("forest");
1740 				}
1741 				if (actions.indexOf("mountain") != -1) {
1742 					idCard.add("mountain");
1743 				}
1744 				if (actions.indexOf("plains") != -1) {
1745 					idCard.add("plains");
1746 				}
1747 				if (actions.indexOf("mercenary") != -1) {
1748 					property.add("mercenary");
1749 				}
1750 				if (actions.indexOf("nonbasic land") != -1) {
1751 					inIdCard.add("nonbasic-land");
1752 				}
1753 				if (actions.indexOf("basic land") != -1) {
1754 					inIdCard.add("basic-land");
1755 				} else if (actions.indexOf("land") != -1) {
1756 					inIdCard.add("land");
1757 				}
1758 				if (actions.indexOf("legend") != -1) {
1759 					property.add("legend");
1760 				}
1761 				if (actions.indexOf("zombie") != -1) {
1762 					property.add("zombie");
1763 				}
1764 				if (actions.indexOf("rebel") != -1) {
1765 					property.add("rebel");
1766 				}
1767 				if (actions.indexOf("dragon") != -1) {
1768 					property.add("dragon");
1769 				}
1770 				if (actions.indexOf("goblin") != -1) {
1771 					property.add("goblin");
1772 				}
1773 				if (actions.indexOf("dwarf") != -1) {
1774 					property.add("dwarf");
1775 				}
1776 				if (isYou && upTo) {
1777 					out.println("\t\t\t\t<action ref='search-lib-up-to' value='3'>");
1778 				} else if (isYou) {
1779 					out.println("\t\t\t\t<action ref='search' value='3'>");
1780 				} else {
1781 					out.println("\t\t\t\t<action ref='target-player'/>");
1782 					if (upTo) {
1783 						out
1784 								.println("\t\t\t\t<action ref='search-lib-up-to-player' value='3'>");
1785 					} else {
1786 						out.println("\t\t\t\t<action ref='search-lib-player' value='3'>");
1787 					}
1788 				}
1789 				out.println("\t\t\t\t\t<test>");
1790 				out.println("\t\t\t\t\t\t<and>");
1791 				out.println("\t\t\t\t\t\t\t<controller player='target-list.first'/>");
1792 				if (idCard.size() + inIdCard.size() > 1) {
1793 					out.println("\t\t\t\t\t\t\t<or>");
1794 				}
1795 				for (String id : idCard) {
1796 					out.println("\t\t\t\t\t\t\t<has-idcard idcard='" + id + "'/>");
1797 				}
1798 				for (String id : inIdCard) {
1799 					out.println("\t\t\t\t\t\t\t<in-idcard idcard='" + id + "'/>");
1800 				}
1801 				if (idCard.size() + inIdCard.size() > 1) {
1802 					out.println("\t\t\t\t\t\t\t</or>");
1803 				}
1804 				if (property.size() > 1) {
1805 					out.println("\t\t\t\t\t\t\t<or>");
1806 				}
1807 				for (String id : property) {
1808 					out.println("\t\t\t\t\t\t\t<has-property property='" + id + "'/>");
1809 				}
1810 				if (property.size() > 1) {
1811 					out.println("\t\t\t\t\t\t\t</or>");
1812 				}
1813 				if (color.size() > 1) {
1814 					out.println("\t\t\t\t\t\t\t<or>");
1815 				}
1816 				for (String id : color) {
1817 					out.println("\t\t\t\t\t\t\t<has-color color='" + id + "'/>");
1818 				}
1819 				if (color.size() > 1) {
1820 					out.println("\t\t\t\t\t\t\t</or>");
1821 				}
1822 				out.println("\t\t\t\t\t\t</and>");
1823 				out.println("\t\t\t\t\t</test>");
1824 				out.println("\t\t\t\t</action>");
1825 				out
1826 						.println("\t\t\t\t\t<!-- INSERT HERE ACTIONS PERFORMED WHEN CARDS HAVE BEEN CHOOSEN -->");
1827 				actions = actions.substring("search ".length());
1828 			} else if (actions.startsWith("sacrifice ")) {
1829 				// Sacrifice
1830 				if (!ignoreCost)
1831 					writeSacrifice(out, actions);
1832 				actions = actions.substring("sacrifice ".length());
1833 			} else
1834 
1835 			if (actions.startsWith("untap ")) {
1836 				// Tap
1837 				actions = writeActionOnTarget(out, "untap ", actions);
1838 				out.println("\t\t\t\t<untap/>");
1839 			} else if (actions.startsWith("tap ")) {
1840 				actions = writeActionOnTarget(out, "tap ", actions);
1841 				out.println("\t\t\t\t<tap/>");
1842 			} else
1843 
1844 			if (actions.startsWith("discards")) {
1845 				// Discard a card from your hand
1846 				out
1847 						.println("\t\t\t\t<!-- UPDATE THE NUMBER OF CARD PLAYER HAVE TO DISCARD, OR REMOVE REPEAT ACTION IF IS ONE -->");
1848 				if (actions.startsWith("discards two"))
1849 					out.println("\t\t\t\t<repeat value='2'/>");
1850 				else
1851 					out.println("\t\t\t\t<repeat value='1'/>");
1852 				out
1853 						.println("\t\t\t\t<!-- UPDATE TARGET MODE (PLAYER THAT CHOOSE THE CARD, ALL, RANDOM,...) -->");
1854 				out
1855 						.println("\t\t\t\t<target type='card' mode='choose' raise-event='false' restriction-zone='hand'>");
1856 				out.println("\t\t\t\t\t<test>");
1857 				out
1858 						.println("\t\t\t\t\t\t<!-- UPDATE THE PLAYER THAT CHOOSE HAVe TO DISCARD IT'S CARD -->");
1859 				out.println("\t\t\t\t\t\t<controller player='you'/>");
1860 				out
1861 						.println("\t\t\t\t\t\t<!-- COMPLETE THE TEST TO DETERMINE CARD TO DISCARD -->");
1862 				out.println("\t\t\t\t\t</test>");
1863 				out.println("\t\t\t\t</target>");
1864 				out.println("\t\t\t\t<action ref='discard'/>");
1865 				actions = actions.substring("discards ".length());
1866 			} else if (actions.startsWith("discard ")) {
1867 				// Discard a card from your hand
1868 				out
1869 						.println("\t\t\t\t<!-- UPDATE THE NUMBER OF CARD PLAYER HAVE TO DISCARD, OR REMOVE REPEAT ACTION IF IS ONE -->");
1870 				if (actions.startsWith("discard two"))
1871 					out.println("\t\t\t\t<repeat value='2'/>");
1872 				else
1873 					out.println("\t\t\t\t<repeat value='1'/>");
1874 				out.println("\t\t\t\t\t<!-- UPDATE TARGET MODE (ALL, RANDOM) -->");
1875 				out
1876 						.println("\t\t\t\t<target type='card' mode='choose' raise-event='false' restriction-zone='hand'>");
1877 				out.println("\t\t\t\t\t<test>");
1878 				out
1879 						.println("\t\t\t\t\t\t\t<!-- COMPLETE THE TEST TO DETERMINE CARD TO DISCARD -->");
1880 				out.println("\t\t\t\t\t</test>");
1881 				out.println("\t\t\t\t</target>");
1882 				out.println("\t\t\t\t<action ref='discard'/>");
1883 				actions = actions.substring("discard ".length());
1884 			} else if (actions.startsWith(" draws")) {
1885 				// Draw cards
1886 				if (!actions.startsWith(" draws a card")) {
1887 					if (actions.startsWith(" draws two cards")) {
1888 						out.println("\t\t\t\t<repeat value='2'/>");
1889 					} else if (actions.startsWith(" draws three card")) {
1890 						out.println("\t\t\t\t<repeat value='3'/>");
1891 					} else if (actions.startsWith(" draws ")
1892 							&& actions.indexOf("cards") != -1) {
1893 						out
1894 								.println("\t\t\t\t<!-- UPDATE THE NUMBER OF CARD PLAYER HAVE TO DRAW -->");
1895 						out.println("\t\t\t\t<repeat value='1'/>");
1896 					}
1897 				}
1898 				out.println("\t\t\t\t<action ref='draw-a-card'/>");
1899 				actions = actions.substring(" draws".length());
1900 			} else if (actions.startsWith("draw ")) {
1901 				out.println("\t\t\t\t<target type='you'/>");
1902 				if (!actions.startsWith("draw a card")) {
1903 					if (actions.startsWith("draw two cards")) {
1904 						out.println("\t\t\t\t<repeat value='2'/>");
1905 					} else if (actions.startsWith("draw three card")) {
1906 						out.println("\t\t\t\t<repeat value='3'/>");
1907 					} else if (actions.startsWith("draw ")
1908 							&& actions.indexOf("cards") != -1) {
1909 						out
1910 								.println("\t\t\t\t<!-- UPDATE THE NUMBER OF CARD YOU HAVE TO DRAW -->");
1911 						out.println("\t\t\t\t<repeat value='1'/>");
1912 					}
1913 				}
1914 				out.println("\t\t\t\t<action ref='draw-a-card'/>");
1915 				actions = actions.substring("draw ".length());
1916 			} else if (actions.startsWith("destroy ")) {
1917 				// Destroy
1918 				actions = writeActionOnTarget(out, "destroy ", actions);
1919 				out.println("\t\t\t\t<action ref='destroy'/>");
1920 			} else if (actions.startsWith("deals ")
1921 					&& actions.indexOf("damage") != -1) {
1922 				// Damage
1923 				String toReplace = actions.substring(0, actions.indexOf("damage")
1924 						+ "damage".length())
1925 						+ " to ";
1926 				String type = toReplace.indexOf("combat") != -1 ? "damage-combat"
1927 						: "damage-normal";
1928 				String amount = actions.substring(
1929 						actions.indexOf("deals ") + "deals ".length(),
1930 						actions.indexOf("damage")).trim();
1931 				actions = writeActionOnTarget(out, toReplace, actions);
1932 				try {
1933 					out.println("\t\t\t\t<assign-damage value='"
1934 							+ Integer.parseInt(amount) + "' type='" + type + "'/>");
1935 				} catch (NumberFormatException e) {
1936 					out.println("\t\t\t\t<assign-damage type='" + type + "'>");
1937 					out.println("\t\t\t\t\t<value register='this' index='power'/>");
1938 					out.println("\t\t\t\t</assign-damage>");
1939 				}
1940 			} else if (actions.startsWith("put ")
1941 					&& actions.matches("put [^ ]+ [^ ]+ counter.*")) {
1942 				// Add objects
1943 				int counterIndex = actions.indexOf("counter");
1944 				String[] counters = actions.substring(0, counterIndex).split(" ");
1945 				String objectCount = counters[1].trim();
1946 				String objectName = counters[2].trim();
1947 				if (actions.matches("put [^ ]+ [^ ]+ counter? on " + lowerCard + ".*")) {
1948 					out.println("\t\t\t\t<target-list operation='clear''/>");
1949 					out.println("\t\t\t\t<target type='this'/>");
1950 				}
1951 				try {
1952 					final int objectCountInt;
1953 					if ("a".equals(objectCount)) {
1954 						objectCountInt = 1;
1955 					} else if ("two".equals(objectCount)) {
1956 						objectCountInt = 2;
1957 					} else if ("tree".equals(objectCount)) {
1958 						objectCountInt = 3;
1959 					} else if ("four".equals(objectCount)) {
1960 						objectCountInt = 4;
1961 					} else if ("five".equals(objectCount)) {
1962 						objectCountInt = 5;
1963 					} else {
1964 						objectCountInt = Integer.parseInt(objectCount);
1965 					}
1966 					if (objectCountInt > 1) {
1967 						out.print("\t\t\t\t<repeat value='");
1968 						out.print(objectCountInt);
1969 						out.println("/>");
1970 					}
1971 				} catch (NumberFormatException e) {
1972 					out.println("\t\t\t\t<repeat>");
1973 					out.println("\t\t\t\t\t<value register='stack' index='0'/>");
1974 					out.println("\t\t\t\t</repeat>");
1975 				}
1976 				out.print("\t\t\t\t<add-object object-name='");
1977 				out.print(objectName);
1978 				out.println("'/>");
1979 				actions = actions.substring(counterIndex + "counter".length() + 1);
1980 			} else if (actions.startsWith("counter ")) {
1981 				// counter a spell
1982 				out.println("\t\t\t\t<action ref='counter'/>");
1983 				actions = actions.substring("counter ".length());
1984 			} else if (actions.startsWith("prevent the next ")) {
1985 				int amount = 1;
1986 				try {
1987 					amount = Integer.valueOf(actions.substring("prevent the next "
1988 							.length(), "prevent the next ".length() + 1));
1989 				} catch (NumberFormatException e) {
1990 					out.println("\t\t\t\t<!-- UPDATE THE DAMAGE PREVENTION NUMBER -->");
1991 				}
1992 				out.println("\t\t\t\t<!-- UPDATE THE DAMAGE PREVENTION OBJECTS -->");
1993 				out.println("\t\t\t\t<action ref='prevent-" + amount + "'/>");
1994 				actions = actions.substring("prevent the next ".length() + 1);
1995 			} else if (actions.startsWith("prevent all")) {
1996 				// Prevent all damage that would be dealt to ...
1997 				out.println("\t\t\t\t<action ref='prevent-all'/>");
1998 				actions = actions.substring("prevent all".length());
1999 			} else if (actions.startsWith("redirect the next ")) {
2000 				int amount = 1;
2001 				try {
2002 					amount = Integer.valueOf(actions.substring("redirect the next "
2003 							.length(), "redirect the next ".length() + 1));
2004 				} catch (NumberFormatException e) {
2005 					out.println("\t\t\t\t<!-- UPDATE THE DAMAGE REDIRECTION NUMBER -->");
2006 				}
2007 				out.println("\t\t\t\t<!-- UPDATE THE DAMAGE REDIRECTION OBJECTS -->");
2008 				out.println("\t\t\t\t<action ref='redirect-" + amount + "'/>");
2009 				actions = actions.substring("redirect the next ".length() + 1);
2010 			} else if (actions.startsWith("redirect all")) {
2011 				// Redirect all damage that would be dealt to ...
2012 				out.println("\t\t\t\t<action ref='redirect-all'/>");
2013 				actions = actions.substring("redirect all".length());
2014 			} else if (actions.startsWith("pay ") && actions.indexOf(" life") != -1) {
2015 				// Pay 2 life
2016 				try {
2017 					int value = Integer.parseInt(actions.substring("pay ".length(),
2018 							"pay ".length() + 2).trim());
2019 					out.println("\t\t\t\t<action ref='pay-life' value='" + value + "'/>");
2020 				} catch (NumberFormatException e) {
2021 					out.println("\t\t\t\t<action ref='pay-life'>");
2022 					out.println("\t\t\t\t\t<!-- UPDATE THE X VALUE OF LIFE TO PAY -->");
2023 					out.println("\t\t\t\t\t<value register='stack' index='0'/>");
2024 					out.println("\t\t\t\t</action>");
2025 				}
2026 				actions = actions
2027 						.substring(actions.indexOf(" life") + " life".length());
2028 			} else if (actions.startsWith(" gain ") && actions.indexOf(" life") != -1) {
2029 				// You gain 2 life
2030 				try {
2031 					int value = Integer.parseInt(actions.substring(" gain ".length(),
2032 							" gain ".length() + 2).trim());
2033 					out
2034 							.println("\t\t\t\t<action ref='gain-life' value='" + value
2035 									+ "'/>");
2036 				} catch (NumberFormatException e) {
2037 					out.println("\t\t\t\t<action ref='gain-life'>");
2038 					out.println("\t\t\t\t\t<!-- UPDATE THE X VALUE OF LIFE TO ADD -->");
2039 					out.println("\t\t\t\t\t<value register='stack' index='0'/>");
2040 					out.println("\t\t\t\t</action>");
2041 				}
2042 				actions = actions
2043 						.substring(actions.indexOf(" life") + " life".length());
2044 			} else if (actions.startsWith(" lose ") && actions.indexOf(" life") != -1) {
2045 				// You lose 2 life
2046 				try {
2047 					int value = Integer.parseInt(actions.substring(" lose ".length(),
2048 							" lose ".length() + 2).trim());
2049 					out
2050 							.println("\t\t\t\t<action ref='lose-life' value='" + value
2051 									+ "'/>");
2052 				} catch (NumberFormatException e) {
2053 					out.println("\t\t\t\t<action ref='lose-life'>");
2054 					out.println("\t\t\t\t\t<!-- UPDATE THE X VALUE OF LIFE TO LOSE -->");
2055 					out.println("\t\t\t\t\t<value register='stack' index='0'/>");
2056 					out.println("\t\t\t\t</action>");
2057 				}
2058 				actions = actions
2059 						.substring(actions.indexOf(" life") + " life".length());
2060 			} else if (actions.startsWith(" gains ")
2061 					&& actions.indexOf(" life") != -1) {
2062 				// Player gains 2 life
2063 				try {
2064 					int value = Integer.parseInt(actions.substring(" gains ".length(),
2065 							" gains ".length() + 2).trim());
2066 					out.println("\t\t\t\t<action ref='gain-life-target' value='" + value
2067 							+ "'/>");
2068 				} catch (NumberFormatException e) {
2069 					out.println("\t\t\t\t<action ref='gain-life-target'>");
2070 					out.println("\t\t\t\t\t<!-- UPDATE THE X VALUE OF LIFE TO ADD -->");
2071 					out.println("\t\t\t\t\t<value register='stack' index='0'/>");
2072 					out.println("\t\t\t\t</action>");
2073 				}
2074 				actions = actions
2075 						.substring(actions.indexOf(" life") + " life".length());
2076 			} else if (actions.startsWith(" loses ")
2077 					&& actions.indexOf(" life") != -1) {
2078 				// Player loses 2 life
2079 				try {
2080 					int value = Integer.parseInt(actions.substring(" loses ".length(),
2081 							" loses ".length() + 2).trim());
2082 					out.println("\t\t\t\t<action ref='lose-life-target' value='" + value
2083 							+ "'/>");
2084 				} catch (NumberFormatException e) {
2085 					out.println("\t\t\t\t<action ref='lose-life-target'>");
2086 					out.println("\t\t\t\t\t<!-- UPDATE THE X VALUE OF LIFE TO LOSE -->");
2087 					out.println("\t\t\t\t\t<value register='stack' index='0'/>");
2088 					out.println("\t\t\t\t</action>");
2089 				}
2090 				actions = actions
2091 						.substring(actions.indexOf(" life") + " life".length());
2092 			} else if (actions.startsWith(" gets ") || actions.startsWith(" gains ")) {
2093 				// Gets ...
2094 				if (actions.indexOf(" poison counter") != -1) {
2095 					// poison counter
2096 					out.println("\t\t\t\t<!-- UPDATE THE NB OF POISON TO ADD -->");
2097 					out
2098 							.println("\t\t\t\t<modify-register register='opponent' index='poison' operation='add' value=''/>");
2099 					actions = actions.substring(actions.indexOf(" poison counter")
2100 							+ " poison counter".length() + 1);
2101 				} else {
2102 					// Gets
2103 					String power = null;
2104 					boolean endOfTurn = actions.indexOf(" until end of turn") != -1;
2105 					if (actions.indexOf("/") == -1) {
2106 						out
2107 								.println("\t\t\t\t\t<!-- UPDATE THE MODIFIER TYPE AND THE LINKED ATTRIBUTE -->");
2108 						out
2109 								.println("\t\t\t\t\t<property-modifier property='flying' linked='false'/>");
2110 						if (endOfTurn) {
2111 							out.println("\t\t\t\t\t\t<until>");
2112 							out.println("\t\t\t\t\t\t\t<end-of-phase phase='cleanup'/>");
2113 							out.println("\t\t\t\t\t\t</until>");
2114 						}
2115 						out.println("\t\t\t\t\t</property-modifier>");
2116 					} else {
2117 						if (actions.startsWith(" gets ")) {
2118 							power = actions
2119 									.substring(" gets ".length(), actions.indexOf("/")).trim();
2120 						} else {
2121 							power = actions.substring(" gains ".length(),
2122 									actions.indexOf("/")).trim();
2123 						}
2124 						String tmpStr = actions.substring(actions.indexOf("/") + 1);
2125 						int dot = tmpStr.indexOf(".");
2126 						int space = tmpStr.indexOf(" ");
2127 						String toughness = tmpStr.substring(0,
2128 								(space < dot || dot == -1) && space != -1 ? space : dot)
2129 								.replaceAll(",", "").trim();
2130 						out.println("\t\t\t\t<add-modifier>");
2131 						if (!power.startsWith("+0")) {
2132 							out.println("\t\t\t\t\t<!-- CHECK THE LINKED ATTRIBUTE -->");
2133 							if (power.indexOf("x") != -1) {
2134 								out
2135 										.println("\t\t\t\t\t<register-modifier index='power' operation='"
2136 												+ (power.startsWith("-") ? "minus" : "add")
2137 												+ "' linked='false'>");
2138 								if (endOfTurn) {
2139 									out.println("\t\t\t\t\t\t<until>");
2140 									out.println("\t\t\t\t\t\t\t<end-of-phase phase='cleanup'/>");
2141 									out.println("\t\t\t\t\t\t</until>");
2142 								}
2143 								out.println("\t\t\t\t\t\t<!-- UPDATE THE POWER X VALUE -->");
2144 								out.println("\t\t\t\t\t\t<value register='stack' index='0'/>");
2145 							} else {
2146 								out
2147 										.println("\t\t\t\t\t<register-modifier index='power' value='"
2148 												+ power.substring(1)
2149 												+ "' operation='"
2150 												+ (power.startsWith("-") ? "minus" : "add")
2151 												+ "' linked='false'>");
2152 								if (endOfTurn) {
2153 									out.println("\t\t\t\t\t\t<until>");
2154 									out.println("\t\t\t\t\t\t\t<end-of-phase phase='cleanup'/>");
2155 									out.println("\t\t\t\t\t\t</until>");
2156 								}
2157 							}
2158 							out.println("\t\t\t\t\t</register-modifier>");
2159 						}
2160 						if (!toughness.startsWith("+0")) {
2161 							out.println("\t\t\t\t\t<!-- CHECK THE LINKED ATTRIBUTE -->");
2162 							if (toughness.indexOf("x") != -1) {
2163 								out
2164 										.println("\t\t\t\t\t<register-modifier index='toughness' operation='"
2165 												+ (power.startsWith("-") ? "minus" : "add")
2166 												+ "' linked='false'>");
2167 								if (endOfTurn) {
2168 									out.println("\t\t\t\t\t\t<until>");
2169 									out.println("\t\t\t\t\t\t\t<end-of-phase phase='cleanup'/>");
2170 									out.println("\t\t\t\t\t\t</until>");
2171 								}
2172 								out
2173 										.println("\t\t\t\t\t\t<!-- UPDATE THE TOUGHNESS X VALUE -->");
2174 								out.println("\t\t\t\t\t\t<value register='stack' index='0'/>");
2175 
2176 							} else {
2177 								out
2178 										.println("\t\t\t\t\t<register-modifier index='toughness' value='"
2179 												+ toughness.substring(1)
2180 												+ "' operation='"
2181 												+ (toughness.startsWith("-") ? "minus" : "add")
2182 												+ "' linked='false'>");
2183 								if (endOfTurn) {
2184 									out.println("\t\t\t\t\t\t<until>");
2185 									out.println("\t\t\t\t\t\t\t<end-of-phase phase='cleanup'/>");
2186 									out.println("\t\t\t\t\t\t</until>");
2187 								}
2188 							}
2189 							out.println("\t\t\t\t\t</register-modifier>");
2190 						}
2191 					}
2192 					out.println("\t\t\t\t</add-modifier>");
2193 
2194 					if (isAura) {
2195 						out.println("\t\t\t\t<target type='this'/>");
2196 						out.println("\t\t\t\t<attachlist>");
2197 						out.println("\t\t\t\t\t\t<!-- UPDATE ATTACHMENT CONDITION -->");
2198 						out
2199 								.println("\t\t\t\t<valid-attachment ref='valid-enchant-creature'/>");
2200 						out.println("\t\t\t\t</attachlist>");
2201 
2202 					}
2203 					actions = actions.substring(" gets ".length());
2204 				}
2205 			} else if (actions
2206 					.matches("^remove .{1,5} cards? in your graveyard from the game")) {
2207 				if (actions.startsWith("remove two"))
2208 					out.println("\t\t\t\t<repeat value='2'/>");
2209 				else if (actions.startsWith("remove three"))
2210 					out.println("\t\t\t\t<repeat value='3'/>");
2211 				else if (actions.startsWith("remove four"))
2212 					out.println("\t\t\t\t<repeat value='4'/>");
2213 				out.println("\t\t\t\t<action ref='remove-a-card-from-graveyard'/>");
2214 			}
2215 			if (actions.length() > 0) {
2216 				actions = actions.substring(1);
2217 			}
2218 		}
2219 
2220 		// TODO Enchanted creature has first strike and trample.
2221 		// At the end of its controller's turn,
2222 
2223 		// TODO Choose one -- You gain 5 life; or prevent the next 5 damage that
2224 		// would be dealt to target creature this turn.
2225 
2226 		// TODO Entwine {2} (Choose both if you pay the entwine cost.)
2227 
2228 	}
2229 
2230 	/***
2231 	 * @param out
2232 	 * @param actions
2233 	 */
2234 	private String writeActionOnTarget(PrintWriter out, String firstAction,
2235 			String actions) {
2236 		if (actions.startsWith(firstAction + "you")) {
2237 			out.println("\t\t\t\t<target type='you'/>");
2238 			return actions.substring((firstAction + "you").length());
2239 		} else if (actions.startsWith(firstAction + "enchanted")) {
2240 			out.println("\t\t\t\t<target type='attachedto'/>");
2241 			return actions.substring((firstAction + "enchanted").length());
2242 		} else if (actions.startsWith(firstAction + lowerCard)) {
2243 			out.println("\t\t\t\t<target type='this'/>");
2244 			return actions.substring((firstAction + lowerCard).length());
2245 		} else if (actions.startsWith(firstAction + "all")) {
2246 			out.println("\t\t\t\t<target-list operation='clear' name='%'/>");
2247 			out.println("\t\t\t\t<!-- UPDATE TYPE, ZONE OF THIS TEST -->");
2248 			out
2249 					.println("\t\t\t\t<target type='card' mode='all' restriction-zone='play'>");
2250 			out.println("\t\t\t\t\t<test>");
2251 			out
2252 					.println("\t\t\t\t<!-- COMPLETE THE TEST TO DETERMINE OBJECTS USED BY THE NEXT ACTION -->");
2253 			out.println("\t\t\t\t\t</test>");
2254 			out.println("\t\t\t\t</target>");
2255 			return actions.substring((firstAction + "a").length());
2256 		} else if (actions.startsWith(firstAction + "a")) {
2257 			out.println("\t\t\t\t<target-list operation='clear' name='%'/>");
2258 			out
2259 					.println("\t\t\t\t<!-- UPDATE TYPE, ZONE, CONTROLLER, MODE OF THIS TEST -->");
2260 			out
2261 					.println("\t\t\t\t<target type='card' mode='choose' raise-event='false' restriction-zone='play'>");
2262 			out.println("\t\t\t\t\t<test>");
2263 			out
2264 					.println("\t\t\t\t<!-- COMPLETE THE TEST TO DETERMINE OBJECT USED BY THE NEXT ACTION -->");
2265 			out.println("\t\t\t\t\t</test>");
2266 			out.println("\t\t\t\t</target>");
2267 			return actions.substring((firstAction + "a").length());
2268 		} else if (actions.length() <= firstAction.length()) {
2269 			return "";
2270 		} else {
2271 			return actions.substring(firstAction.length());
2272 		}
2273 	}
2274 
2275 	private List<String> extractProperties(String line, List<String> properties) {
2276 		String[] propertiesSTR = line.split(" ");
2277 		for (String property : propertiesSTR) {
2278 			properties.add(property);
2279 		}
2280 		return properties;
2281 	}
2282 
2283 	/***
2284 	 * @param line
2285 	 * @param properties
2286 	 */
2287 	private String updateProperties(String pLine, List<String> properties) {
2288 		String[] propertiesSTR = pLine.split(", ");
2289 
2290 		// first : validation
2291 		for (int i = propertiesSTR.length; i-- > 0;) {
2292 			propertiesSTR[i] = propertiesSTR[i].trim();
2293 			if (propertiesSTR[i].length() > 30 || propertiesSTR[i].indexOf(" ") != -1
2294 					&& propertiesSTR[i].indexOf("strike") == -1
2295 					&& !propertiesSTR[i].startsWith("protection from")) {
2296 				return pLine;
2297 			}
2298 		}
2299 
2300 		// then : update list
2301 		String line = pLine;
2302 		for (String property : propertiesSTR) {
2303 			if (property.indexOf("cycling") == -1
2304 					&& property.indexOf("buyback") == -1
2305 					&& property.indexOf("flashback") == -1
2306 					&& property.indexOf("echo") == -1) {
2307 				properties.add(property.trim().replaceAll(" ", "-")); // modificado
2308 				// replaceFirst
2309 				line = MToolKit.replaceAll(
2310 						StringUtils.replaceOnce(line, property + ",", ""), property, "")
2311 						.trim();
2312 			}
2313 		}
2314 		return line;
2315 	}
2316 
2317 	private String extractColor(int idcolors) {
2318 		switch (idcolors) {
2319 		case 0:
2320 			return "colorless";
2321 		case 1:
2322 			return "black";
2323 		case 2:
2324 			return "blue";
2325 		case 3:
2326 			return "green";
2327 		case 4:
2328 			return "red";
2329 		case 5:
2330 			return "white";
2331 		default:
2332 			return "x";
2333 		}
2334 	}
2335 
2336 	/***
2337 	 * @param in
2338 	 */
2339 	private void skipCard(BufferedReader in) throws IOException {
2340 		String line = in.readLine();
2341 		while (line != null && line.length() > 0) {
2342 			line = in.readLine();
2343 		}
2344 	}
2345 
2346 	/***
2347 	 * Write the affinity XML code for a given idCard
2348 	 * 
2349 	 * @param out
2350 	 * @param hasAffinityLine
2351 	 */
2352 	private void writeAffinity(PrintWriter out, String idCard) {
2353 		assert idCard != null && idCard.length() > 0;
2354 		out.println("\t\t\t\t<action ref='affinity'>");
2355 		out.println("\t\t\t\t\t<counter-test>");
2356 		out.print("\t\t\t\t\t\t<has-idcard idcard='");
2357 		out.print(idCard.split(" ")[0].trim());
2358 		out.println("'/>");
2359 		out.println("\t\t\t\t\t</counter-test>");
2360 		out.println("\t\t\t\t</action>");
2361 
2362 	}
2363 
2364 	private String lowerCard = null;
2365 
2366 	private boolean isNonBasicLand = false;
2367 
2368 	private boolean isLocalEnchantCreature = false;
2369 
2370 	private boolean isLocalEnchantLand = false;
2371 
2372 	private boolean isLocalEnchantArtifact = false;
2373 
2374 	private boolean isEnchantWorld = false;
2375 
2376 	private boolean isLocalEnchantCreatureArtifact = false;
2377 
2378 	private boolean isLocalEnchantPermanent = false;
2379 
2380 	private boolean isLocalEnchantEnchantment = false;
2381 
2382 	private boolean isGlobalEnchant = false;
2383 
2384 	private boolean isInstant = false;
2385 
2386 	private boolean isCreature = false;
2387 
2388 	private boolean isArtifact = false;
2389 
2390 	private boolean isSorcery = false;
2391 
2392 	private boolean isSwamp = false;
2393 
2394 	private boolean isIsland = false;
2395 
2396 	private boolean isForest = false;
2397 
2398 	private boolean isMountain = false;
2399 
2400 	private boolean isPlains = false;
2401 }