1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
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
134
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
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;
313
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
399 if (isCreature) {
400 if (power.indexOf("*") != -1) {
401
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
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
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
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
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
506
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
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
607 if (hasRampage) {
608 out.println("\t\t<ability ref='rampage" + hasRampageCount + "'/>");
609 }
610
611
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
621 if (hasDredge) {
622 out.println("\t\t<ability ref='rampage" + hasDredgeCount + "'/>");
623 }
624
625
626 if (hasHaunt) {
627 out.println("\t\t<ability ref='haunt'/>");
628 }
629
630
631 if (hasBloodThirst) {
632 out.println("\t\t<ability ref='bloodthirst" + hasBloodThirstCount
633 + "'/>");
634 }
635
636
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
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
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
678 if (hasFlanking) {
679 out.println("\t\t<ability ref='flanking'/>");
680 }
681
682
683 if (hasHaunting) {
684 out.println("\t\t<ability ref='haunting'/>");
685 }
686
687
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
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
724 out
725 .println("\t\t<activated-ability playable='instant' name='' zone='play'>");
726
727
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
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
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
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
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
954 if (!isInstant && !isSorcery) {
955
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1354 out.println("\t\t\t\t<action ref='sacrifice-a-permanent' value='1'>");
1355 } else if (action.contains("sacrifice two ")) {
1356
1357 out.println("\t\t\t\t<action ref='sacrifice-a-permanent' value='2'>");
1358 } else {
1359
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
1451 writeXmanaCost(out, extractManaCost(action), true);
1452 } else if ("t".equals(action.trim())) {
1453
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
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
1482 actions = writeXmanaGive(out, actions, true);
1483 }
1484
1485
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
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
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
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
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
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
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
1830 if (!ignoreCost)
1831 writeSacrifice(out, actions);
1832 actions = actions.substring("sacrifice ".length());
1833 } else
1834
1835 if (actions.startsWith("untap ")) {
1836
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2094 if (actions.indexOf(" poison counter") != -1) {
2095
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
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
2221
2222
2223
2224
2225
2226
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
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
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(" ", "-"));
2308
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 }