mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 03:08:02 +00:00
Compare commits
441 Commits
forge-1.5.
...
forge-1.5.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
312c15d824 | ||
|
|
3f0cdc9b19 | ||
|
|
5d5c42c843 | ||
|
|
1a8fe19c88 | ||
|
|
7e37495b49 | ||
|
|
3210f06931 | ||
|
|
a457ff539d | ||
|
|
afbcd90ffc | ||
|
|
8acdc6c458 | ||
|
|
4ed8f69da1 | ||
|
|
90fe657da6 | ||
|
|
91fe7b516c | ||
|
|
e3851e3f1d | ||
|
|
301014285f | ||
|
|
e467f44bf2 | ||
|
|
e8e5ac2ca7 | ||
|
|
ebb0a4b2bc | ||
|
|
d21e2666ec | ||
|
|
43140b2db3 | ||
|
|
c898e1321f | ||
|
|
4f04cbbcc8 | ||
|
|
f17e857710 | ||
|
|
2401b9b1ff | ||
|
|
e646ff1d1f | ||
|
|
9bb800ce43 | ||
|
|
6859ad2ad9 | ||
|
|
19152790b2 | ||
|
|
05751dbe1b | ||
|
|
f35f6b3edd | ||
|
|
8af7fadbf6 | ||
|
|
9190ce038f | ||
|
|
bda47748f2 | ||
|
|
96084d7b26 | ||
|
|
e96ff73b50 | ||
|
|
fcb8c4bdd6 | ||
|
|
c7c1d2d302 | ||
|
|
21ea8e377c | ||
|
|
e9409d01a6 | ||
|
|
a8c70a903f | ||
|
|
c66ca97dfc | ||
|
|
5b5517ad29 | ||
|
|
c8de886967 | ||
|
|
2ef19583a6 | ||
|
|
9e0ff5e635 | ||
|
|
427cef758f | ||
|
|
1cc1516feb | ||
|
|
daafa3f5c2 | ||
|
|
9e20af7603 | ||
|
|
306a160df0 | ||
|
|
b5686bcd2f | ||
|
|
33dd245131 | ||
|
|
25334c27f1 | ||
|
|
3f20ebb15b | ||
|
|
37849b88e2 | ||
|
|
800b3f8272 | ||
|
|
b2ecb3cb52 | ||
|
|
8a794f2e02 | ||
|
|
3c05e1674f | ||
|
|
a15b3c2a69 | ||
|
|
10c138d64e | ||
|
|
99d1718498 | ||
|
|
515985dead | ||
|
|
e30c4532b8 | ||
|
|
2ab5f19f79 | ||
|
|
f5054558c2 | ||
|
|
b726053164 | ||
|
|
cc433b6708 | ||
|
|
e95e251161 | ||
|
|
75edc751f3 | ||
|
|
b4ba84a0d1 | ||
|
|
38074a1660 | ||
|
|
ca5e20b1a9 | ||
|
|
c4db463338 | ||
|
|
34c2cb604f | ||
|
|
f058e38004 | ||
|
|
b38a8b5830 | ||
|
|
8e76829a27 | ||
|
|
f3bf092898 | ||
|
|
4dd2b87538 | ||
|
|
4d6930e903 | ||
|
|
3fecd16efd | ||
|
|
29a535c71a | ||
|
|
3fd72f35df | ||
|
|
bb3d637738 | ||
|
|
02fe620360 | ||
|
|
ebe0e350ff | ||
|
|
6dbe638a59 | ||
|
|
31b5f4181a | ||
|
|
72d0cfdbbc | ||
|
|
f934764290 | ||
|
|
e28f809a58 | ||
|
|
a88dd00a0d | ||
|
|
5d9de47fd5 | ||
|
|
7add28ad7d | ||
|
|
17b97aca28 | ||
|
|
86b422230e | ||
|
|
0193671453 | ||
|
|
c4be1b8697 | ||
|
|
52f8880627 | ||
|
|
f537e8cf78 | ||
|
|
482af12b67 | ||
|
|
2f85d50778 | ||
|
|
b51663c130 | ||
|
|
7ebc54352e | ||
|
|
6703e62823 | ||
|
|
e860e9e1af | ||
|
|
de3303abc9 | ||
|
|
a0695c08cc | ||
|
|
c5aeb0785e | ||
|
|
21b376848f | ||
|
|
f8fe7e41b4 | ||
|
|
22caa0a408 | ||
|
|
4d3945f5a4 | ||
|
|
0786012ed8 | ||
|
|
6e9a316460 | ||
|
|
fd7d0e1d99 | ||
|
|
65199c7a81 | ||
|
|
851094c523 | ||
|
|
9b31032016 | ||
|
|
a7fa173e52 | ||
|
|
de4d83372c | ||
|
|
c7f24490f3 | ||
|
|
fabc7a3a27 | ||
|
|
e830527f74 | ||
|
|
5fc5feb636 | ||
|
|
384af0001c | ||
|
|
2abc9b3f7c | ||
|
|
9242f3439c | ||
|
|
b1ba8f0aa2 | ||
|
|
20b3775280 | ||
|
|
c2bb321e17 | ||
|
|
b0160287ba | ||
|
|
284e2257f3 | ||
|
|
ec06d07f35 | ||
|
|
5eca8807d8 | ||
|
|
5b3ee63299 | ||
|
|
a6ffa3ae36 | ||
|
|
e021e66387 | ||
|
|
eb70985551 | ||
|
|
cd6dc5158e | ||
|
|
942f30557c | ||
|
|
1486d61e65 | ||
|
|
eb082d2f49 | ||
|
|
7e6e691771 | ||
|
|
8e4962ceb1 | ||
|
|
414d82bd37 | ||
|
|
4091f1d1d9 | ||
|
|
fe0f4ddf99 | ||
|
|
b0845c5795 | ||
|
|
aeddb37d9d | ||
|
|
1ff1c35486 | ||
|
|
6e585a7afa | ||
|
|
e0df16ee17 | ||
|
|
ae5cb7a17a | ||
|
|
8d79ed527f | ||
|
|
d4bc84c6bd | ||
|
|
9743a7d1b7 | ||
|
|
e5cffc623a | ||
|
|
9c0a559bce | ||
|
|
b794bc5ee0 | ||
|
|
55c71d77e1 | ||
|
|
6914e30443 | ||
|
|
1c52e8e38a | ||
|
|
c38f169d1d | ||
|
|
8f4b8dbf88 | ||
|
|
b68f28b621 | ||
|
|
a23eb2f869 | ||
|
|
8dfbf2b3b6 | ||
|
|
70b0fab66a | ||
|
|
082e2ff2cd | ||
|
|
12af50d473 | ||
|
|
b1cde02dd4 | ||
|
|
2d737ab092 | ||
|
|
8cd9220f36 | ||
|
|
838d4a98aa | ||
|
|
d32bfea94e | ||
|
|
181a7f5b9c | ||
|
|
ee00b544f7 | ||
|
|
5548c71bda | ||
|
|
ae7a6b79b7 | ||
|
|
96d2338bea | ||
|
|
21217e030b | ||
|
|
1d63f4b4a1 | ||
|
|
8843e5bfe7 | ||
|
|
48b97f8632 | ||
|
|
20184fb4c0 | ||
|
|
76000a90fb | ||
|
|
4aebd350ee | ||
|
|
13f4a0abb4 | ||
|
|
35ea297090 | ||
|
|
f11909d6da | ||
|
|
5df82652b6 | ||
|
|
8fde8ebe5f | ||
|
|
6bc20a8830 | ||
|
|
0bbd9c103a | ||
|
|
0b68e2ade6 | ||
|
|
1ca79539b6 | ||
|
|
1c2c3d6d51 | ||
|
|
bdb1243409 | ||
|
|
812d4ca519 | ||
|
|
4e7e14cbf3 | ||
|
|
2064b6517e | ||
|
|
c9f491a483 | ||
|
|
be2ec80f0c | ||
|
|
1c13e8dc10 | ||
|
|
4748aa2262 | ||
|
|
a3376b0502 | ||
|
|
c073d39cd6 | ||
|
|
b508f78f04 | ||
|
|
8424da8311 | ||
|
|
cfd9d55668 | ||
|
|
417e3bb104 | ||
|
|
320d4f62d9 | ||
|
|
6c712d86fb | ||
|
|
a0479f9610 | ||
|
|
374a744a44 | ||
|
|
81416d49de | ||
|
|
31ebd62c83 | ||
|
|
93dd4af6ed | ||
|
|
9f0308dd66 | ||
|
|
f9298703d4 | ||
|
|
3992032e8e | ||
|
|
58dacc0789 | ||
|
|
b3280923d9 | ||
|
|
e83da9ff9c | ||
|
|
8b1d0fc759 | ||
|
|
ff869933be | ||
|
|
fb0af4dc18 | ||
|
|
6f5551d78d | ||
|
|
a90efe4939 | ||
|
|
46c37b9d82 | ||
|
|
3e23eb517b | ||
|
|
9cf75ea844 | ||
|
|
5565b4a4d0 | ||
|
|
bde5967ef4 | ||
|
|
f3560238fe | ||
|
|
f97f489aba | ||
|
|
454b7715c0 | ||
|
|
ac1e279235 | ||
|
|
5950162663 | ||
|
|
6a52b46192 | ||
|
|
f5558eec7f | ||
|
|
0c39f596a3 | ||
|
|
ba3c544484 | ||
|
|
e0063727a9 | ||
|
|
7b68821a8c | ||
|
|
4a84b408d4 | ||
|
|
b9aec4ffb8 | ||
|
|
1a958e758f | ||
|
|
74527319aa | ||
|
|
a66e7ad14f | ||
|
|
e4b91416dd | ||
|
|
7735c705c0 | ||
|
|
31ab48d0d4 | ||
|
|
e5cf9da31d | ||
|
|
9eac64ab7b | ||
|
|
7131cebf7d | ||
|
|
bfb4a5ee57 | ||
|
|
21e250bf36 | ||
|
|
f5b1ac970b | ||
|
|
c85f14f27c | ||
|
|
c0cf6198a4 | ||
|
|
4d3012fee7 | ||
|
|
75726dc272 | ||
|
|
260724af80 | ||
|
|
2b37cf217f | ||
|
|
669ff579c5 | ||
|
|
d0e65fe1bc | ||
|
|
4485e46801 | ||
|
|
2265687c75 | ||
|
|
f70523bf14 | ||
|
|
48013b9339 | ||
|
|
e9e1caf9d1 | ||
|
|
5b17e2beda | ||
|
|
19bc74f88d | ||
|
|
ae0069652a | ||
|
|
5ec7f01b7a | ||
|
|
691f798f90 | ||
|
|
d5bef0861b | ||
|
|
87dd938cde | ||
|
|
c4e0d3e7ce | ||
|
|
c705722bdc | ||
|
|
6424fa151a | ||
|
|
0646e49359 | ||
|
|
6ddae9e9da | ||
|
|
efc7be1637 | ||
|
|
1de80be872 | ||
|
|
f8740f1268 | ||
|
|
d6f30c9220 | ||
|
|
f2d7004b02 | ||
|
|
6ecf800bab | ||
|
|
6f92a834da | ||
|
|
a7a85d22d5 | ||
|
|
178024e248 | ||
|
|
798e93af46 | ||
|
|
3cb125ae4a | ||
|
|
30aed49e87 | ||
|
|
d0173a2341 | ||
|
|
fb7a61ab30 | ||
|
|
13e09c73bc | ||
|
|
6fdaf4fda4 | ||
|
|
ba79089bed | ||
|
|
a8670467be | ||
|
|
4dd84cdb2e | ||
|
|
028d6c0a1f | ||
|
|
ca2584f598 | ||
|
|
17e96250f7 | ||
|
|
79fdd21817 | ||
|
|
a0daa7c4be | ||
|
|
000d0d3119 | ||
|
|
3b01b4f3dd | ||
|
|
f0613e9660 | ||
|
|
1c51ed37c2 | ||
|
|
2bfcd92da9 | ||
|
|
0bf676448b | ||
|
|
5bceff414e | ||
|
|
1b65231e30 | ||
|
|
8b39b69bb7 | ||
|
|
4dfab45544 | ||
|
|
f046dbf3cc | ||
|
|
2e5f9350eb | ||
|
|
938784d6e8 | ||
|
|
02c582a695 | ||
|
|
2851d49c3b | ||
|
|
e88af1f6ba | ||
|
|
da3b6bf19e | ||
|
|
da28e10ac7 | ||
|
|
e6b260cc60 | ||
|
|
2cea9debcf | ||
|
|
768a26a5d4 | ||
|
|
0e251ffb6a | ||
|
|
74c04ea561 | ||
|
|
e92cc2735b | ||
|
|
6a94535b78 | ||
|
|
17ad490f97 | ||
|
|
704e4c4ef7 | ||
|
|
36a301275e | ||
|
|
bb2a01512e | ||
|
|
ad73c9391d | ||
|
|
ce33d146d0 | ||
|
|
055695890e | ||
|
|
028579eed4 | ||
|
|
5c836228f7 | ||
|
|
0663eee49a | ||
|
|
4d9205699b | ||
|
|
d8a5993a28 | ||
|
|
6e7e19fd34 | ||
|
|
9e55ee9be1 | ||
|
|
ae93665645 | ||
|
|
7eb84bb6a3 | ||
|
|
3006cc9431 | ||
|
|
480629953b | ||
|
|
c54ed09d38 | ||
|
|
a098b56339 | ||
|
|
7a9f8d9788 | ||
|
|
7bd822b96a | ||
|
|
d20e9d5629 | ||
|
|
9b61a99dc3 | ||
|
|
4c1f670147 | ||
|
|
c05d299fe4 | ||
|
|
0ba8b530fe | ||
|
|
0a6f7afeff | ||
|
|
483f274bac | ||
|
|
1fd36a4623 | ||
|
|
3b1ab80c1c | ||
|
|
abe0cec346 | ||
|
|
6e1e22d6cb | ||
|
|
7650ec9323 | ||
|
|
fe3fedaf64 | ||
|
|
f21f187890 | ||
|
|
41e164d131 | ||
|
|
adb6a0b7f0 | ||
|
|
31618c1611 | ||
|
|
6eba60638b | ||
|
|
e4040d4a47 | ||
|
|
c53cd32291 | ||
|
|
172ca340ae | ||
|
|
a8451abea4 | ||
|
|
cdf67a3865 | ||
|
|
e2f2fc4804 | ||
|
|
db9a451e32 | ||
|
|
a8cf682f71 | ||
|
|
0c721f1776 | ||
|
|
f8194aac7a | ||
|
|
15dd60ff3e | ||
|
|
d54441a9b2 | ||
|
|
4e75bfb4d0 | ||
|
|
3e350d03c6 | ||
|
|
2fa44e1ae2 | ||
|
|
1e5244cee0 | ||
|
|
6043c2738d | ||
|
|
013cf5eb13 | ||
|
|
a413fe2dc1 | ||
|
|
a2bf02eb82 | ||
|
|
229485494a | ||
|
|
4ea3439667 | ||
|
|
4154d31143 | ||
|
|
30b660f802 | ||
|
|
b79cf45778 | ||
|
|
c6e9cbd69b | ||
|
|
7e493ed129 | ||
|
|
c3ed6ebe79 | ||
|
|
27e33ec1b1 | ||
|
|
7601d5a2bd | ||
|
|
a9fb42eb15 | ||
|
|
cd9cdbf1be | ||
|
|
e68a716587 | ||
|
|
bab5672669 | ||
|
|
80f083e141 | ||
|
|
91d37b38cc | ||
|
|
9349fa9217 | ||
|
|
748523f9cf | ||
|
|
e64336abe9 | ||
|
|
15450a7fba | ||
|
|
ad2f63cd8f | ||
|
|
dbd3d956fb | ||
|
|
aabb4399ed | ||
|
|
a99386ac1d | ||
|
|
b400f22d15 | ||
|
|
8843054b89 | ||
|
|
8c8bde0799 | ||
|
|
109a990b28 | ||
|
|
8e9ac2e3e7 | ||
|
|
c0ad9b1b71 | ||
|
|
01609a1f29 | ||
|
|
2f5219615d | ||
|
|
91cd93783f | ||
|
|
2d8e4e9053 | ||
|
|
9500b3a5ae | ||
|
|
84e124bbf5 | ||
|
|
0d0377ae4a | ||
|
|
9e1ec67253 | ||
|
|
4f8ee5ea52 | ||
|
|
56654ffcb1 | ||
|
|
ac48d3634b | ||
|
|
934e4cbb2c | ||
|
|
53e631d65f | ||
|
|
1483d7c969 | ||
|
|
71ddee1033 | ||
|
|
480bba7a8c | ||
|
|
9c4c529c62 |
@@ -1,8 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
|
||||
|
||||
31237
.gitattributes
vendored
31237
.gitattributes
vendored
File diff suppressed because it is too large
Load Diff
26
.gitignore
vendored
26
.gitignore
vendored
@@ -2,20 +2,28 @@
|
||||
/*.iml
|
||||
/*.tmp
|
||||
/.metadata
|
||||
forge-ai/forge-ai.iml
|
||||
forge-ai/target
|
||||
forge-core/forge-core.iml
|
||||
forge-core/target
|
||||
forge-game/target
|
||||
forge-gui/forge-gui.iml
|
||||
forge-gui/forge.profile.properties
|
||||
forge-gui/res/*.log
|
||||
forge-gui/res/PerSetTrackingResults
|
||||
forge-gui/res/cardsfolder/*.bat
|
||||
forge-gui/res/decks
|
||||
forge-gui/res/layouts
|
||||
forge-gui/res/pics*
|
||||
forge-gui/res/pics_product
|
||||
forge-gui/target
|
||||
forge-gui/tools/PerSetTrackingResults
|
||||
forge-gui/tools/oracleScript.log
|
||||
/forge.profile.properties
|
||||
/nbactions.xml
|
||||
/pom.xml.next
|
||||
/pom.xml.releaseBackup
|
||||
/pom.xml.tag
|
||||
/release.properties
|
||||
res/*.log
|
||||
res/PerSetTrackingResults
|
||||
res/cardsfolder/*.bat
|
||||
res/decks
|
||||
res/layouts
|
||||
res/pics*
|
||||
res/pics_product
|
||||
/target
|
||||
/test-output
|
||||
tools/PerSetTrackingResults
|
||||
tools/oracleScript.log
|
||||
|
||||
29
.project
29
.project
@@ -4,36 +4,7 @@
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
|
||||
9
forge-ai/.classpath
Normal file
9
forge-ai/.classpath
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
23
forge-ai/.project
Normal file
23
forge-ai/.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>forge-ai</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
4
forge-ai/.settings/org.eclipse.core.resources.prefs
Normal file
4
forge-ai/.settings/org.eclipse.core.resources.prefs
Normal file
@@ -0,0 +1,4 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=ISO-8859-1
|
||||
encoding//src/test/java=ISO-8859-1
|
||||
encoding/<project>=ISO-8859-1
|
||||
5
forge-ai/.settings/org.eclipse.jdt.core.prefs
Normal file
5
forge-ai/.settings/org.eclipse.jdt.core.prefs
Normal file
@@ -0,0 +1,5 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.7
|
||||
4
forge-ai/.settings/org.eclipse.m2e.core.prefs
Normal file
4
forge-ai/.settings/org.eclipse.m2e.core.prefs
Normal file
@@ -0,0 +1,4 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
||||
28
forge-ai/pom.xml
Normal file
28
forge-ai/pom.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.5.6</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-ai</artifactId>
|
||||
<name>Forge AI</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>forge</groupId>
|
||||
<artifactId>forge-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>forge</groupId>
|
||||
<artifactId>forge-game</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
9
forge-core/.classpath
Normal file
9
forge-core/.classpath
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
23
forge-core/.project
Normal file
23
forge-core/.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>forge-core</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
4
forge-core/.settings/org.eclipse.core.resources.prefs
Normal file
4
forge-core/.settings/org.eclipse.core.resources.prefs
Normal file
@@ -0,0 +1,4 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=ISO-8859-1
|
||||
encoding//src/test/java=ISO-8859-1
|
||||
encoding/<project>=ISO-8859-1
|
||||
5
forge-core/.settings/org.eclipse.jdt.core.prefs
Normal file
5
forge-core/.settings/org.eclipse.jdt.core.prefs
Normal file
@@ -0,0 +1,5 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.7
|
||||
4
forge-core/.settings/org.eclipse.m2e.core.prefs
Normal file
4
forge-core/.settings/org.eclipse.m2e.core.prefs
Normal file
@@ -0,0 +1,4 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
||||
27
forge-core/pom.xml
Normal file
27
forge-core/pom.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>forge</artifactId>
|
||||
<groupId>forge</groupId>
|
||||
<version>1.5.6</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>forge-core</artifactId>
|
||||
<name>Forge Core</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>14.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,375 +1,375 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.card.cardfactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import org.apache.commons.lang.time.StopWatch;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.CardRulesReader;
|
||||
import forge.error.BugReporter;
|
||||
import forge.gui.toolbox.FProgressBar;
|
||||
import forge.util.FileUtil;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* CardReader class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public class CardStorageReader {
|
||||
|
||||
private static final String CARD_FILE_DOT_EXTENSION = ".txt";
|
||||
|
||||
/** Default charset when loading from files. */
|
||||
public static final String DEFAULT_CHARSET_NAME = "US-ASCII";
|
||||
|
||||
final private boolean useThreadPool = FThreads.isMultiCoreSystem();
|
||||
final private int NUMBER_OF_PARTS = 25;
|
||||
|
||||
final private CountDownLatch cdl = new CountDownLatch(NUMBER_OF_PARTS);
|
||||
final private FProgressBar barProgress;
|
||||
|
||||
private transient File cardsfolder;
|
||||
|
||||
private transient ZipFile zip;
|
||||
private transient Charset charset;
|
||||
|
||||
|
||||
// 8/18/11 10:56 PM
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for CardReader.
|
||||
* </p>
|
||||
*
|
||||
* @param theCardsFolder
|
||||
* indicates location of the cardsFolder
|
||||
* @param useZip
|
||||
* if true, attempts to load cards from a zip file, if one
|
||||
* exists.
|
||||
*/
|
||||
public CardStorageReader(String cardDataDir, final boolean useZip, FProgressBar barProgress) {
|
||||
this.barProgress = barProgress;
|
||||
|
||||
// These read data for lightweight classes.
|
||||
File theCardsFolder = new File(cardDataDir);
|
||||
|
||||
if (!theCardsFolder.exists()) {
|
||||
throw new RuntimeException("CardReader : constructor error -- file not found -- filename is "
|
||||
+ theCardsFolder.getAbsolutePath());
|
||||
}
|
||||
|
||||
if (!theCardsFolder.isDirectory()) {
|
||||
throw new RuntimeException("CardReader : constructor error -- not a directory -- "
|
||||
+ theCardsFolder.getAbsolutePath());
|
||||
}
|
||||
|
||||
this.cardsfolder = theCardsFolder;
|
||||
|
||||
final File zipFile = new File(theCardsFolder, "cardsfolder.zip");
|
||||
|
||||
if (useZip && zipFile.exists()) {
|
||||
try {
|
||||
this.zip = new ZipFile(zipFile);
|
||||
} catch (final Exception exn) {
|
||||
System.err.printf("Error reading zip file \"%s\": %s. Defaulting to txt files in \"%s\".%n", zipFile.getAbsolutePath(), exn, theCardsFolder.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
this.charset = Charset.forName(CardStorageReader.DEFAULT_CHARSET_NAME);
|
||||
|
||||
} // CardReader()
|
||||
|
||||
private final List<CardRules> loadCardsInRange(final List<File> files, int from, int to) {
|
||||
|
||||
CardRulesReader rulesReader = new CardRulesReader();
|
||||
|
||||
List<CardRules> result = new ArrayList<CardRules>();
|
||||
for(int i = from; i < to; i++) {
|
||||
File cardTxtFile = files.get(i);
|
||||
result.add(this.loadCard(rulesReader, cardTxtFile));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private final List<CardRules> loadCardsInRangeFromZip(final List<ZipEntry> files, int from, int to) {
|
||||
|
||||
CardRulesReader rulesReader = new CardRulesReader();
|
||||
|
||||
List<CardRules> result = new ArrayList<CardRules>();
|
||||
for(int i = from; i < to; i++) {
|
||||
ZipEntry ze = files.get(i);
|
||||
// if (ze.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION)) // already filtered!
|
||||
result.add(this.loadCard(rulesReader, ze));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Starts reading cards into memory until the given card is found.
|
||||
*
|
||||
* After that, we save our place in the list of cards (on disk) in case we
|
||||
* need to load more.
|
||||
*
|
||||
* @return the Card or null if it was not found.
|
||||
*/
|
||||
public final List<CardRules> loadCards() {
|
||||
if (barProgress != null) {
|
||||
barProgress.setMaximum(NUMBER_OF_PARTS);
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
barProgress.setPercentMode(true);
|
||||
barProgress.setDescription("Loading card data: ");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final List<Callable<List<CardRules>>> tasks;
|
||||
long estimatedFilesRemaining;
|
||||
|
||||
// Iterate through txt files or zip archive.
|
||||
// Report relevant numbers to progress monitor model.
|
||||
if (this.zip == null) {
|
||||
final List<File> allFiles = new ArrayList<File>();
|
||||
fillFilesArray(allFiles, this.cardsfolder);
|
||||
estimatedFilesRemaining = allFiles.size();
|
||||
tasks = makeTaskListForFiles(allFiles);
|
||||
} else {
|
||||
|
||||
estimatedFilesRemaining = this.zip.size();
|
||||
ZipEntry entry;
|
||||
List<ZipEntry> entries = new ArrayList<ZipEntry>();
|
||||
// zipEnum was initialized in the constructor.
|
||||
Enumeration<? extends ZipEntry> zipEnum = this.zip.entries();
|
||||
while (zipEnum.hasMoreElements()) {
|
||||
entry = zipEnum.nextElement();
|
||||
if (entry.isDirectory() || !entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION))
|
||||
continue;
|
||||
entries.add(entry);
|
||||
}
|
||||
|
||||
tasks = makeTaskListForZip(entries);
|
||||
} // endif
|
||||
|
||||
StopWatch sw = new StopWatch();
|
||||
sw.start();
|
||||
|
||||
List<CardRules> res = executeLoadTask(tasks);
|
||||
|
||||
sw.stop();
|
||||
final long timeOnParse = sw.getTime();
|
||||
System.out.printf("Read cards: %s %s in %d ms (%d parts) %s%n", estimatedFilesRemaining, zip == null? "files" : "archived files", timeOnParse, NUMBER_OF_PARTS, useThreadPool ? "using thread pool" : "in same thread");
|
||||
if ( null != barProgress )
|
||||
barProgress.setPercentMode(false);
|
||||
return res;
|
||||
} // loadCardsUntilYouFind(String)
|
||||
|
||||
private List<CardRules> executeLoadTask(final List<Callable<List<CardRules>>> tasks) {
|
||||
List<CardRules> result = new ArrayList<CardRules>();
|
||||
|
||||
try {
|
||||
if ( useThreadPool ) {
|
||||
final ExecutorService executor = FThreads.getComputingPool(0.5f);
|
||||
final List<Future<List<CardRules>>> parts = executor.invokeAll(tasks);
|
||||
executor.shutdown();
|
||||
cdl.await();
|
||||
for(Future<List<CardRules>> pp : parts) {
|
||||
result.addAll(pp.get());
|
||||
}
|
||||
} else {
|
||||
for(Callable<List<CardRules>> c : tasks) {
|
||||
result.addAll(c.call());
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) { // this clause comes from non-threaded branch
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Callable<List<CardRules>>> makeTaskListForZip(final List<ZipEntry> entries) {
|
||||
int totalFiles = entries.size();
|
||||
int filesPerPart = totalFiles / NUMBER_OF_PARTS;
|
||||
final List<Callable<List<CardRules>>> tasks = new ArrayList<Callable<List<CardRules>>>();
|
||||
for (int iPart = 0; iPart < NUMBER_OF_PARTS; iPart++) {
|
||||
final int from = iPart * filesPerPart;
|
||||
final int till = iPart == NUMBER_OF_PARTS - 1 ? totalFiles : from + filesPerPart;
|
||||
tasks.add(new Callable<List<CardRules>>() {
|
||||
@Override
|
||||
public List<CardRules> call() throws Exception{
|
||||
List<CardRules> res = loadCardsInRangeFromZip(entries, from, till);
|
||||
if ( null != barProgress )
|
||||
barProgress.increment();
|
||||
cdl.countDown();
|
||||
return res;
|
||||
}
|
||||
});
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
|
||||
private List<Callable<List<CardRules>>> makeTaskListForFiles(final List<File> allFiles) {
|
||||
int totalFiles = allFiles.size();
|
||||
int filesPerPart = totalFiles / NUMBER_OF_PARTS;
|
||||
final List<Callable<List<CardRules>>> tasks = new ArrayList<Callable<List<CardRules>>>();
|
||||
for (int iPart = 0; iPart < NUMBER_OF_PARTS; iPart++) {
|
||||
final int from = iPart * filesPerPart;
|
||||
final int till = iPart == NUMBER_OF_PARTS - 1 ? totalFiles : from + filesPerPart;
|
||||
tasks.add(new Callable<List<CardRules>>() {
|
||||
@Override
|
||||
public List<CardRules> call() throws Exception{
|
||||
List<CardRules> res = loadCardsInRange(allFiles, from, till);
|
||||
if ( null != barProgress )
|
||||
barProgress.increment();
|
||||
cdl.countDown();
|
||||
return res;
|
||||
}
|
||||
});
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
* @param allFiles
|
||||
* @param cardsfolder2
|
||||
*/
|
||||
private void fillFilesArray(List<File> allFiles, File startDir) {
|
||||
String[] list = startDir.list();
|
||||
for (String filename : list) {
|
||||
File entry = new File(startDir, filename);
|
||||
|
||||
if (!entry.isDirectory()) {
|
||||
if (entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION))
|
||||
allFiles.add(entry);
|
||||
continue;
|
||||
}
|
||||
if (filename.startsWith(".")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fillFilesArray(allFiles, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* load a card.
|
||||
* </p>
|
||||
*
|
||||
* @param inputStream
|
||||
* the stream from which to load the card's information
|
||||
*
|
||||
* @return the card loaded from the stream
|
||||
*/
|
||||
protected final CardRules loadCard(CardRulesReader reader, final InputStream inputStream) {
|
||||
reader.reset();
|
||||
|
||||
InputStreamReader isr = new InputStreamReader(inputStream, this.charset);
|
||||
List<String> allLines = FileUtil.readAllLines(isr, true);
|
||||
|
||||
return reader.readCard(allLines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a card from a txt file.
|
||||
*
|
||||
* @param pathToTxtFile
|
||||
* the full or relative path to the file to load
|
||||
*
|
||||
* @return a new Card instance
|
||||
*/
|
||||
protected final CardRules loadCard(final CardRulesReader reader, final File pathToTxtFile) {
|
||||
FileInputStream fileInputStream = null;
|
||||
try {
|
||||
fileInputStream = new FileInputStream(pathToTxtFile);
|
||||
return this.loadCard(reader, fileInputStream);
|
||||
} catch (final FileNotFoundException ex) {
|
||||
BugReporter.reportException(ex, "File \"%s\" exception", pathToTxtFile.getAbsolutePath());
|
||||
throw new RuntimeException("CardReader : run error -- file exception -- filename is "
|
||||
+ pathToTxtFile.getPath(), ex);
|
||||
} finally {
|
||||
try {
|
||||
fileInputStream.close();
|
||||
} catch (final IOException ignored) {
|
||||
// 11:08
|
||||
// PM
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a card from an entry in a zip file.
|
||||
*
|
||||
* @param entry
|
||||
* to load from
|
||||
*
|
||||
* @return a new Card instance
|
||||
*/
|
||||
protected final CardRules loadCard(final CardRulesReader rulesReader, final ZipEntry entry) {
|
||||
InputStream zipInputStream = null;
|
||||
try {
|
||||
zipInputStream = this.zip.getInputStream(entry);
|
||||
return this.loadCard(rulesReader, zipInputStream);
|
||||
} catch (final IOException exn) {
|
||||
throw new RuntimeException(exn);
|
||||
// PM
|
||||
} finally {
|
||||
try {
|
||||
if (zipInputStream != null) {
|
||||
zipInputStream.close();
|
||||
}
|
||||
} catch (final IOException ignored) {
|
||||
// 11:08
|
||||
// PM
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.apache.commons.lang3.time.StopWatch;
|
||||
|
||||
import forge.card.CardRules;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.ThreadUtil;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* CardReader class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: CardStorageReader.java 23742 2013-11-22 16:32:56Z Max mtg $
|
||||
*/
|
||||
|
||||
public class CardStorageReader {
|
||||
public interface Observer {
|
||||
public void cardLoaded(CardRules rules, List<String> lines, File fileOnDisk);
|
||||
}
|
||||
|
||||
public interface ProgressObserver{
|
||||
void setOperationName(String name, boolean usePercents);
|
||||
void report(int current, int total);
|
||||
|
||||
// does nothing, used when they pass null instead of an instance
|
||||
public final static ProgressObserver emptyObserver = new ProgressObserver() {
|
||||
@Override public void setOperationName(String name, boolean usePercents) {}
|
||||
@Override public void report(int current, int total) {}
|
||||
};
|
||||
}
|
||||
|
||||
private static final String CARD_FILE_DOT_EXTENSION = ".txt";
|
||||
|
||||
/** Default charset when loading from files. */
|
||||
public static final String DEFAULT_CHARSET_NAME = "US-ASCII";
|
||||
|
||||
private final boolean useThreadPool = ThreadUtil.isMultiCoreSystem();
|
||||
private final static int NUMBER_OF_PARTS = 25;
|
||||
|
||||
private final ProgressObserver progressObserver;
|
||||
|
||||
private transient File cardsfolder;
|
||||
|
||||
private transient ZipFile zip;
|
||||
private final transient Charset charset;
|
||||
|
||||
private final Observer observer;
|
||||
|
||||
|
||||
// 8/18/11 10:56 PM
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for CardReader.
|
||||
* </p>
|
||||
*
|
||||
* @param theCardsFolder
|
||||
* indicates location of the cardsFolder
|
||||
* @param useZip
|
||||
* if true, attempts to load cards from a zip file, if one
|
||||
* exists.
|
||||
*/
|
||||
public CardStorageReader(String cardDataDir, CardStorageReader.ProgressObserver progressObserver, Observer observer) {
|
||||
this.progressObserver = progressObserver != null ? progressObserver : CardStorageReader.ProgressObserver.emptyObserver;
|
||||
this.cardsfolder = new File(cardDataDir);
|
||||
this.observer = observer;
|
||||
|
||||
// These read data for lightweight classes.
|
||||
if (!cardsfolder.exists()) {
|
||||
throw new RuntimeException("CardReader : constructor error -- " + cardsfolder.getAbsolutePath() + " file/folder not found.");
|
||||
}
|
||||
|
||||
if (!cardsfolder.isDirectory()) {
|
||||
throw new RuntimeException("CardReader : constructor error -- not a directory -- " + cardsfolder.getAbsolutePath());
|
||||
}
|
||||
|
||||
final File zipFile = new File(cardsfolder, "cardsfolder.zip");
|
||||
|
||||
if (zipFile.exists()) {
|
||||
try {
|
||||
this.zip = new ZipFile(zipFile);
|
||||
} catch (final Exception exn) {
|
||||
System.err.printf("Error reading zip file \"%s\": %s. Defaulting to txt files in \"%s\".%n", zipFile.getAbsolutePath(), exn, cardsfolder.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
this.charset = Charset.forName(CardStorageReader.DEFAULT_CHARSET_NAME);
|
||||
|
||||
} // CardReader()
|
||||
|
||||
private final List<CardRules> loadCardsInRange(final List<File> files, int from, int to) {
|
||||
CardRules.Reader rulesReader = new CardRules.Reader();
|
||||
|
||||
List<CardRules> result = new ArrayList<CardRules>();
|
||||
for(int i = from; i < to; i++) {
|
||||
File cardTxtFile = files.get(i);
|
||||
result.add(this.loadCard(rulesReader, cardTxtFile));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private final List<CardRules> loadCardsInRangeFromZip(final List<ZipEntry> files, int from, int to) {
|
||||
CardRules.Reader rulesReader = new CardRules.Reader();
|
||||
|
||||
List<CardRules> result = new ArrayList<CardRules>();
|
||||
for(int i = from; i < to; i++) {
|
||||
ZipEntry ze = files.get(i);
|
||||
// if (ze.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION)) // already filtered!
|
||||
result.add(this.loadCard(rulesReader, ze));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts reading cards into memory until the given card is found.
|
||||
*
|
||||
* After that, we save our place in the list of cards (on disk) in case we
|
||||
* need to load more.
|
||||
*
|
||||
* @return the Card or null if it was not found.
|
||||
*/
|
||||
public final Iterable<CardRules> loadCards() {
|
||||
progressObserver.setOperationName("Loading cards, examining folder", true);
|
||||
|
||||
// Iterate through txt files or zip archive.
|
||||
// Report relevant numbers to progress monitor model.
|
||||
|
||||
|
||||
Set<CardRules> result = new TreeSet<CardRules>(new Comparator<CardRules>() {
|
||||
@Override
|
||||
public int compare(CardRules o1, CardRules o2) {
|
||||
return String.CASE_INSENSITIVE_ORDER.compare(o1.getName(), o2.getName());
|
||||
}
|
||||
});
|
||||
|
||||
final List<File> allFiles = collectCardFiles(new ArrayList<File>(), this.cardsfolder);
|
||||
if(!allFiles.isEmpty()) {
|
||||
int fileParts = zip == null ? NUMBER_OF_PARTS : 1 + NUMBER_OF_PARTS / 3;
|
||||
if( allFiles.size() < fileParts * 100)
|
||||
fileParts = allFiles.size() / 100; // to avoid creation of many threads for a dozen of files
|
||||
final CountDownLatch cdlFiles = new CountDownLatch(fileParts);
|
||||
List<Callable<List<CardRules>>> taskFiles = makeTaskListForFiles(allFiles, cdlFiles);
|
||||
progressObserver.setOperationName("Loading cards from folders", true);
|
||||
progressObserver.report(0, taskFiles.size());
|
||||
StopWatch sw = new StopWatch();
|
||||
sw.start();
|
||||
executeLoadTask(result, taskFiles, cdlFiles);
|
||||
sw.stop();
|
||||
final long timeOnParse = sw.getTime();
|
||||
System.out.printf("Read cards: %s files in %d ms (%d parts) %s%n", allFiles.size(), timeOnParse, taskFiles.size(), useThreadPool ? "using thread pool" : "in same thread");
|
||||
}
|
||||
|
||||
if( this.zip != null ) {
|
||||
final CountDownLatch cdlZip = new CountDownLatch(NUMBER_OF_PARTS);
|
||||
List<Callable<List<CardRules>>> taskZip = new ArrayList<>();
|
||||
|
||||
ZipEntry entry;
|
||||
List<ZipEntry> entries = new ArrayList<ZipEntry>();
|
||||
// zipEnum was initialized in the constructor.
|
||||
Enumeration<? extends ZipEntry> zipEnum = this.zip.entries();
|
||||
while (zipEnum.hasMoreElements()) {
|
||||
entry = zipEnum.nextElement();
|
||||
if (entry.isDirectory() || !entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION))
|
||||
continue;
|
||||
entries.add(entry);
|
||||
}
|
||||
|
||||
taskZip = makeTaskListForZip(entries, cdlZip);
|
||||
progressObserver.setOperationName("Loading cards from archive", true);
|
||||
progressObserver.report(0, taskZip.size());
|
||||
StopWatch sw = new StopWatch();
|
||||
sw.start();
|
||||
executeLoadTask(result, taskZip, cdlZip);
|
||||
sw.stop();
|
||||
final long timeOnParse = sw.getTime();
|
||||
System.out.printf("Read cards: %s archived files in %d ms (%d parts) %s%n", this.zip.size(), timeOnParse, taskZip.size(), useThreadPool ? "using thread pool" : "in same thread");
|
||||
}
|
||||
|
||||
return result;
|
||||
} // loadCardsUntilYouFind(String)
|
||||
|
||||
private void executeLoadTask(Collection<CardRules> result, final List<Callable<List<CardRules>>> tasks, CountDownLatch cdl) {
|
||||
try {
|
||||
if ( useThreadPool ) {
|
||||
final ExecutorService executor = ThreadUtil.getComputingPool(0.5f);
|
||||
final List<Future<List<CardRules>>> parts = executor.invokeAll(tasks);
|
||||
executor.shutdown();
|
||||
cdl.await();
|
||||
for(Future<List<CardRules>> pp : parts) {
|
||||
result.addAll(pp.get());
|
||||
}
|
||||
} else {
|
||||
for(Callable<List<CardRules>> c : tasks) {
|
||||
result.addAll(c.call());
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) { // this clause comes from non-threaded branch
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Callable<List<CardRules>>> makeTaskListForZip(final List<ZipEntry> entries, final CountDownLatch cdl) {
|
||||
int totalFiles = entries.size();
|
||||
final int maxParts = (int) cdl.getCount();
|
||||
int filesPerPart = totalFiles / maxParts;
|
||||
final List<Callable<List<CardRules>>> tasks = new ArrayList<Callable<List<CardRules>>>();
|
||||
for (int iPart = 0; iPart < maxParts; iPart++) {
|
||||
final int from = iPart * filesPerPart;
|
||||
final int till = iPart == maxParts - 1 ? totalFiles : from + filesPerPart;
|
||||
tasks.add(new Callable<List<CardRules>>() {
|
||||
@Override
|
||||
public List<CardRules> call() throws Exception{
|
||||
List<CardRules> res = loadCardsInRangeFromZip(entries, from, till);
|
||||
cdl.countDown();
|
||||
progressObserver.report(maxParts - (int)cdl.getCount(), maxParts);
|
||||
return res;
|
||||
}
|
||||
});
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
|
||||
private List<Callable<List<CardRules>>> makeTaskListForFiles(final List<File> allFiles, final CountDownLatch cdl) {
|
||||
int totalFiles = allFiles.size();
|
||||
final int maxParts = (int) cdl.getCount();
|
||||
int filesPerPart = totalFiles / maxParts;
|
||||
final List<Callable<List<CardRules>>> tasks = new ArrayList<Callable<List<CardRules>>>();
|
||||
for (int iPart = 0; iPart < maxParts; iPart++) {
|
||||
final int from = iPart * filesPerPart;
|
||||
final int till = iPart == maxParts - 1 ? totalFiles : from + filesPerPart;
|
||||
tasks.add(new Callable<List<CardRules>>() {
|
||||
@Override
|
||||
public List<CardRules> call() throws Exception{
|
||||
List<CardRules> res = loadCardsInRange(allFiles, from, till);
|
||||
cdl.countDown();
|
||||
progressObserver.report(maxParts - (int)cdl.getCount(), maxParts);
|
||||
return res;
|
||||
}
|
||||
});
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
|
||||
public static List<File> collectCardFiles(List<File> accumulator, File startDir) {
|
||||
String[] list = startDir.list();
|
||||
for (String filename : list) {
|
||||
File entry = new File(startDir, filename);
|
||||
|
||||
if (!entry.isDirectory()) {
|
||||
if (entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION))
|
||||
accumulator.add(entry);
|
||||
continue;
|
||||
}
|
||||
if (filename.startsWith(".")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
collectCardFiles(accumulator, entry);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
|
||||
private List<String> readScript(final InputStream inputStream) {
|
||||
return FileUtil.readAllLines(new InputStreamReader(inputStream, this.charset), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a card from a txt file.
|
||||
*
|
||||
* @param pathToTxtFile
|
||||
* the full or relative path to the file to load
|
||||
*
|
||||
* @return a new Card instance
|
||||
*/
|
||||
protected final CardRules loadCard(final CardRules.Reader reader, final File file) {
|
||||
FileInputStream fileInputStream = null;
|
||||
try {
|
||||
fileInputStream = new FileInputStream(file);
|
||||
reader.reset();
|
||||
List<String> lines = readScript(fileInputStream);
|
||||
CardRules rules = reader.readCard(lines);
|
||||
if ( null != observer )
|
||||
observer.cardLoaded(rules, lines, file);
|
||||
return rules;
|
||||
} catch (final FileNotFoundException ex) {
|
||||
throw new RuntimeException("CardReader : run error -- file not found: " + file.getPath(), ex);
|
||||
} finally {
|
||||
try {
|
||||
fileInputStream.close();
|
||||
} catch (final IOException ignored) {
|
||||
// 11:08
|
||||
// PM
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a card from an entry in a zip file.
|
||||
*
|
||||
* @param entry
|
||||
* to load from
|
||||
*
|
||||
* @return a new Card instance
|
||||
*/
|
||||
protected final CardRules loadCard(final CardRules.Reader rulesReader, final ZipEntry entry) {
|
||||
InputStream zipInputStream = null;
|
||||
try {
|
||||
zipInputStream = this.zip.getInputStream(entry);
|
||||
rulesReader.reset();
|
||||
CardRules rules = rulesReader.readCard(readScript(zipInputStream));
|
||||
|
||||
return rules;
|
||||
} catch (final IOException exn) {
|
||||
throw new RuntimeException(exn);
|
||||
// PM
|
||||
} finally {
|
||||
try {
|
||||
if (zipInputStream != null) {
|
||||
zipInputStream.close();
|
||||
}
|
||||
} catch (final IOException ignored) {
|
||||
// 11:08
|
||||
// PM
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
102
forge-core/src/main/java/forge/StaticData.java
Normal file
102
forge-core/src/main/java/forge/StaticData.java
Normal file
@@ -0,0 +1,102 @@
|
||||
package forge;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import forge.card.CardDb;
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.PrintSheet;
|
||||
import forge.item.FatPack;
|
||||
import forge.item.SealedProduct;
|
||||
import forge.util.storage.IStorage;
|
||||
import forge.util.storage.StorageBase;
|
||||
|
||||
|
||||
/**
|
||||
* The class holding game invariants, such as cards, editions, game formats. All that data, which is not supposed to be changed by player
|
||||
*
|
||||
* @author Max
|
||||
*/
|
||||
public class StaticData {
|
||||
private final CardDb commonCards;
|
||||
private final CardDb variantCards;
|
||||
private final CardEdition.Collection editions;
|
||||
private final IStorage<SealedProduct.Template> boosters;
|
||||
private final IStorage<SealedProduct.Template> specialBoosters;
|
||||
private final IStorage<SealedProduct.Template> tournaments;
|
||||
private final IStorage<FatPack.Template> fatPacks;
|
||||
private final IStorage<PrintSheet> printSheets;
|
||||
|
||||
private static StaticData lastInstance = null;
|
||||
|
||||
public StaticData(CardStorageReader reader, String editionFolder, String blockDataFolder) {
|
||||
this.editions = new CardEdition.Collection(new CardEdition.Reader(new File(editionFolder)));
|
||||
lastInstance = this;
|
||||
|
||||
final Map<String, CardRules> regularCards = new TreeMap<String, CardRules>(String.CASE_INSENSITIVE_ORDER);
|
||||
final Map<String, CardRules> variantsCards = new TreeMap<String, CardRules>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
for (CardRules card : reader.loadCards()) {
|
||||
if (null == card) continue;
|
||||
|
||||
final String cardName = card.getName();
|
||||
if ( card.isVariant() ) {
|
||||
variantsCards.put(cardName, card);
|
||||
}
|
||||
else {
|
||||
regularCards.put(cardName, card);
|
||||
}
|
||||
}
|
||||
|
||||
commonCards = new CardDb(regularCards, editions, false);
|
||||
variantCards = new CardDb(variantsCards, editions, false);
|
||||
|
||||
this.boosters = new StorageBase<SealedProduct.Template>("Boosters", editions.getBoosterGenerator());
|
||||
this.specialBoosters = new StorageBase<SealedProduct.Template>("Special boosters", new SealedProduct.Template.Reader(new File(blockDataFolder, "boosters-special.txt")));
|
||||
this.tournaments = new StorageBase<SealedProduct.Template>("Starter sets", new SealedProduct.Template.Reader(new File(blockDataFolder, "starters.txt")));
|
||||
this.fatPacks = new StorageBase<FatPack.Template>("Fat packs", new FatPack.Template.Reader("res/blockdata/fatpacks.txt"));
|
||||
this.printSheets = new StorageBase<PrintSheet>("Special print runs", new PrintSheet.Reader(new File(blockDataFolder, "printsheets.txt")));
|
||||
}
|
||||
|
||||
public final static StaticData instance() {
|
||||
return lastInstance;
|
||||
}
|
||||
|
||||
public final CardEdition.Collection getEditions() {
|
||||
return this.editions;
|
||||
}
|
||||
|
||||
/** @return {@link forge.util.storage.IStorageView}<{@link forge.item.FatPackTemplate}> */
|
||||
public IStorage<FatPack.Template> getFatPacks() {
|
||||
return fatPacks;
|
||||
}
|
||||
|
||||
/** @return {@link forge.util.storage.IStorageView}<{@link forge.card.BoosterTemplate}> */
|
||||
public final IStorage<SealedProduct.Template> getTournamentPacks() {
|
||||
return tournaments;
|
||||
}
|
||||
|
||||
/** @return {@link forge.util.storage.IStorageView}<{@link forge.card.BoosterTemplate}> */
|
||||
public final IStorage<SealedProduct.Template> getBoosters() {
|
||||
return boosters;
|
||||
}
|
||||
|
||||
public final IStorage<SealedProduct.Template> getSpecialBoosters() {
|
||||
return specialBoosters;
|
||||
}
|
||||
|
||||
public IStorage<PrintSheet> getPrintSheets() {
|
||||
return printSheets;
|
||||
}
|
||||
|
||||
public CardDb getCommonCards() {
|
||||
return commonCards;
|
||||
}
|
||||
|
||||
public CardDb getVariantCards() {
|
||||
return variantCards;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,10 +34,10 @@ import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.Singletons;
|
||||
import forge.StaticData;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.item.PrintSheet;
|
||||
import forge.item.SealedProduct;
|
||||
import forge.util.TextUtil;
|
||||
|
||||
/**
|
||||
@@ -50,26 +50,15 @@ import forge.util.TextUtil;
|
||||
*/
|
||||
public class BoosterGenerator {
|
||||
|
||||
private static final String LAND = "Land";
|
||||
public static final String ANY = "Any";
|
||||
public static final String COMMON = "Common";
|
||||
public static final String UNCOMMON = "Uncommon";
|
||||
public static final String UNCOMMON_RARE = "UncommonRare";
|
||||
public static final String RARE = "Rare";
|
||||
public static final String RARE_MYTHIC = "RareMythic";
|
||||
public static final String MYTHIC = "Mythic";
|
||||
public static final String BASIC_LAND = "BasicLand";
|
||||
public static final String TIME_SHIFTED = "TimeShifted";
|
||||
|
||||
|
||||
private final static Map<String, PrintSheet> cachedSheets = new TreeMap<String, PrintSheet>(String.CASE_INSENSITIVE_ORDER);
|
||||
private static final synchronized PrintSheet getPrintSheet(String key) {
|
||||
if( !cachedSheets.containsKey(key) )
|
||||
cachedSheets.put(key, makeSheet(key, CardDb.instance().getAllCards()));
|
||||
cachedSheets.put(key, makeSheet(key, StaticData.instance().getCommonCards().getAllCards()));
|
||||
return cachedSheets.get(key);
|
||||
}
|
||||
|
||||
public static final List<PaperCard> getBoosterPack(SealedProductTemplate booster) {
|
||||
public static final List<PaperCard> getBoosterPack(SealedProduct.Template booster) {
|
||||
List<PaperCard> result = new ArrayList<PaperCard>();
|
||||
for(Pair<String, Integer> slot : booster.getSlots()) {
|
||||
String slotType = slot.getLeft(); // add expansion symbol here?
|
||||
@@ -77,7 +66,7 @@ public class BoosterGenerator {
|
||||
|
||||
String[] sType = TextUtil.splitWithParenthesis(slotType, ' ');
|
||||
String setCode = sType.length == 1 && booster.getEdition() != null ? booster.getEdition() : null;
|
||||
String sheetKey = Singletons.getModel().getEditions().contains(setCode) ? slotType.trim() + " " + setCode: slotType.trim();
|
||||
String sheetKey = StaticData.instance().getEditions().contains(setCode) ? slotType.trim() + " " + setCode: slotType.trim();
|
||||
|
||||
PrintSheet ps = getPrintSheet(sheetKey);
|
||||
result.addAll(ps.random(numCards, true));
|
||||
@@ -100,7 +89,7 @@ public class BoosterGenerator {
|
||||
String mainCode = itMod.next();
|
||||
if ( mainCode.regionMatches(true, 0, "fromSheet", 0, 9)) { // custom print sheet
|
||||
String sheetName = StringUtils.strip(mainCode.substring(9), "()\" ");
|
||||
src = Singletons.getModel().getPrintSheets().get(sheetName).toFlatList();
|
||||
src = StaticData.instance().getPrintSheets().get(sheetName).toFlatList();
|
||||
setPred = Predicates.alwaysTrue();
|
||||
|
||||
} else if (mainCode.startsWith("promo")) { // get exactly the named cards, that's a tiny inlined print sheet
|
||||
@@ -108,7 +97,7 @@ public class BoosterGenerator {
|
||||
String[] cardNames = TextUtil.splitWithParenthesis(list, ',', '"', '"');
|
||||
List<PaperCard> srcList = new ArrayList<PaperCard>();
|
||||
for(String cardName: cardNames)
|
||||
srcList.add(CardDb.instance().getCard(cardName));
|
||||
srcList.add(StaticData.instance().getCommonCards().getCard(cardName));
|
||||
src = srcList;
|
||||
setPred = Predicates.alwaysTrue();
|
||||
|
||||
@@ -121,18 +110,18 @@ public class BoosterGenerator {
|
||||
// only special operators should remain by now - the ones that could not be turned into one predicate
|
||||
String mainCode = operators.isEmpty() ? null : operators.get(0).trim();
|
||||
|
||||
if( null == mainCode || mainCode.equalsIgnoreCase(ANY) ) { // no restriction on rarity
|
||||
if( null == mainCode || mainCode.equalsIgnoreCase(BoosterSlots.ANY) ) { // no restriction on rarity
|
||||
Predicate<PaperCard> predicate = Predicates.and(setPred, extraPred);
|
||||
ps.addAll(Iterables.filter(src, predicate));
|
||||
|
||||
} else if ( mainCode.equalsIgnoreCase(UNCOMMON_RARE) ) { // for sets like ARN, where U1 cards are considered rare and U3 are uncommon
|
||||
} else if ( mainCode.equalsIgnoreCase(BoosterSlots.UNCOMMON_RARE) ) { // for sets like ARN, where U1 cards are considered rare and U3 are uncommon
|
||||
Predicate<PaperCard> predicateRares = Predicates.and(setPred, IPaperCard.Predicates.Presets.IS_RARE, extraPred);
|
||||
ps.addAll(Iterables.filter(src, predicateRares));
|
||||
|
||||
Predicate<PaperCard> predicateUncommon = Predicates.and( setPred, IPaperCard.Predicates.Presets.IS_UNCOMMON, extraPred);
|
||||
ps.addAll(Iterables.filter(src, predicateUncommon), 3);
|
||||
|
||||
} else if ( mainCode.equalsIgnoreCase(RARE_MYTHIC) ) {
|
||||
} else if ( mainCode.equalsIgnoreCase(BoosterSlots.RARE_MYTHIC) ) {
|
||||
// Typical ratio of rares to mythics is 53:15, changing to 35:10 in smaller sets.
|
||||
// To achieve the desired 1:8 are all mythics are added once, and all rares added twice per print sheet.
|
||||
|
||||
@@ -168,13 +157,13 @@ public class BoosterGenerator {
|
||||
|
||||
Predicate<PaperCard> toAdd = null;
|
||||
if( operator.equalsIgnoreCase("dfc") ) { toAdd = Predicates.compose(CardRulesPredicates.splitType(CardSplitType.Transform), PaperCard.FN_GET_RULES);
|
||||
} else if ( operator.equalsIgnoreCase(LAND) ) { toAdd = Predicates.compose(CardRulesPredicates.Presets.IS_LAND, PaperCard.FN_GET_RULES);
|
||||
} else if ( operator.equalsIgnoreCase(BASIC_LAND)) { toAdd = IPaperCard.Predicates.Presets.IS_BASIC_LAND;
|
||||
} else if ( operator.equalsIgnoreCase(TIME_SHIFTED)) { toAdd = IPaperCard.Predicates.Presets.IS_SPECIAL;
|
||||
} else if ( operator.equalsIgnoreCase(MYTHIC)) { toAdd = IPaperCard.Predicates.Presets.IS_MYTHIC_RARE;
|
||||
} else if ( operator.equalsIgnoreCase(RARE)) { toAdd = IPaperCard.Predicates.Presets.IS_RARE;
|
||||
} else if ( operator.equalsIgnoreCase(UNCOMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_UNCOMMON;
|
||||
} else if ( operator.equalsIgnoreCase(COMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_COMMON;
|
||||
} else if ( operator.equalsIgnoreCase(BoosterSlots.LAND) ) { toAdd = Predicates.compose(CardRulesPredicates.Presets.IS_LAND, PaperCard.FN_GET_RULES);
|
||||
} else if ( operator.equalsIgnoreCase(BoosterSlots.BASIC_LAND)) { toAdd = IPaperCard.Predicates.Presets.IS_BASIC_LAND;
|
||||
} else if ( operator.equalsIgnoreCase(BoosterSlots.TIME_SHIFTED)) { toAdd = IPaperCard.Predicates.Presets.IS_SPECIAL;
|
||||
} else if ( operator.equalsIgnoreCase(BoosterSlots.MYTHIC)) { toAdd = IPaperCard.Predicates.Presets.IS_MYTHIC_RARE;
|
||||
} else if ( operator.equalsIgnoreCase(BoosterSlots.RARE)) { toAdd = IPaperCard.Predicates.Presets.IS_RARE;
|
||||
} else if ( operator.equalsIgnoreCase(BoosterSlots.UNCOMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_UNCOMMON;
|
||||
} else if ( operator.equalsIgnoreCase(BoosterSlots.COMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_COMMON;
|
||||
} else if ( operator.startsWith("name(") ) {
|
||||
operator = StringUtils.strip(operator.substring(4), "() ");
|
||||
String[] cardNames = TextUtil.splitWithParenthesis(operator, ',', '"', '"');
|
||||
14
forge-core/src/main/java/forge/card/BoosterSlots.java
Normal file
14
forge-core/src/main/java/forge/card/BoosterSlots.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package forge.card;
|
||||
|
||||
public class BoosterSlots {
|
||||
public static final String LAND = "Land";
|
||||
public static final String ANY = "Any";
|
||||
public static final String COMMON = "Common";
|
||||
public static final String UNCOMMON = "Uncommon";
|
||||
public static final String UNCOMMON_RARE = "UncommonRare";
|
||||
public static final String RARE = "Rare";
|
||||
public static final String RARE_MYTHIC = "RareMythic";
|
||||
public static final String MYTHIC = "Mythic";
|
||||
public static final String BASIC_LAND = "BasicLand";
|
||||
public static final String TIME_SHIFTED = "TimeShifted";
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package forge;
|
||||
package forge.card;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
@@ -21,6 +21,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -29,6 +30,7 @@ import java.util.TreeMap;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
@@ -36,77 +38,46 @@ import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.CardEdition.Type;
|
||||
import forge.card.CardEdition.CardInSet;
|
||||
import forge.item.PaperCard;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.CollectionSuppliers;
|
||||
import forge.util.Lang;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.maps.CollectionSuppliers;
|
||||
|
||||
public final class CardDb implements ICardDatabase {
|
||||
private static volatile CardDb commonCards = null; // 'volatile' keyword makes this working
|
||||
private static volatile CardDb variantCards = null; // 'volatile' keyword makes this working
|
||||
public final static String foilSuffix = "+";
|
||||
private final static int foilSuffixLength = foilSuffix.length();
|
||||
|
||||
public static ICardDatabase instance() {
|
||||
if (CardDb.commonCards == null) {
|
||||
throw new NullPointerException("CardDb has not yet been initialized, run setup() first");
|
||||
}
|
||||
return CardDb.commonCards;
|
||||
}
|
||||
|
||||
public static ICardDatabase variants() {
|
||||
if (CardDb.variantCards == null) {
|
||||
throw new NullPointerException("CardDb has not yet been initialized, run setup() first");
|
||||
}
|
||||
return CardDb.variantCards;
|
||||
}
|
||||
|
||||
public static void setup(final Iterable<CardRules> rules, EditionCollection editions) {
|
||||
if (CardDb.commonCards != null) {
|
||||
throw new RuntimeException("CardDb has already been initialized, don't do it twice please");
|
||||
}
|
||||
synchronized (CardDb.class) {
|
||||
if (CardDb.commonCards == null) { // It's broken under 1.4 and below, on 1.5+ works again!
|
||||
CardSorter cs = new CardSorter(rules);
|
||||
commonCards = new CardDb(cs.regularCards, editions, false);
|
||||
variantCards = new CardDb(cs.variantsCards, editions, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// need this to obtain cardReference by name+set+artindex
|
||||
private final Multimap<String, PaperCard> allCardsByName = Multimaps.newListMultimap(new TreeMap<String,Collection<PaperCard>>(String.CASE_INSENSITIVE_ORDER), CollectionSuppliers.<PaperCard>arrayLists());
|
||||
private final Multimap<String, PaperCard> allCardsByName = Multimaps.newListMultimap(new TreeMap<String,Collection<PaperCard>>(String.CASE_INSENSITIVE_ORDER), CollectionSuppliers.<PaperCard>arrayLists());
|
||||
private final Map<String, PaperCard> uniqueCardsByName = new TreeMap<String, PaperCard>(String.CASE_INSENSITIVE_ORDER);
|
||||
private final Map<String, CardRules> rulesByName;
|
||||
|
||||
private final List<PaperCard> allCards = new ArrayList<PaperCard>();
|
||||
private final List<PaperCard> roAllCards = Collections.unmodifiableList(allCards);
|
||||
private final Collection<PaperCard> roUniqueCards = Collections.unmodifiableCollection(uniqueCardsByName.values());
|
||||
private final EditionCollection editions;
|
||||
|
||||
|
||||
private CardDb(Map<String, CardRules> rules, EditionCollection editions0, boolean logMissingCards) {
|
||||
private final List<PaperCard> allCards = new ArrayList<PaperCard>();
|
||||
private final List<PaperCard> roAllCards = Collections.unmodifiableList(allCards);
|
||||
private final Collection<PaperCard> roUniqueCards = Collections.unmodifiableCollection(uniqueCardsByName.values());
|
||||
private final CardEdition.Collection editions;
|
||||
|
||||
public CardDb(Map<String, CardRules> rules, CardEdition.Collection editions0, boolean logMissingCards) {
|
||||
this.rulesByName = rules;
|
||||
this.editions = editions0;
|
||||
List<String> missingCards = new ArrayList<String>();
|
||||
for(CardEdition e : editions.getOrderedEditions()) {
|
||||
boolean worthLogging = logMissingCards && ( e.getType() == Type.CORE || e.getType() == Type.EXPANSION || e.getType() == Type.REPRINT );
|
||||
boolean worthLogging = logMissingCards && ( e.getType() == CardEdition.Type.CORE || e.getType() == CardEdition.Type.EXPANSION || e.getType() == CardEdition.Type.REPRINT );
|
||||
if(worthLogging)
|
||||
System.out.print(e.getName() + " (" + e.getCards().length + " cards)");
|
||||
String lastCardName = null;
|
||||
int artIdx = 0;
|
||||
for(CardEdition.CardInSet cis : e.getCards()) {
|
||||
if ( cis.name.equals(lastCardName) )
|
||||
if ( cis.name.equals(lastCardName) )
|
||||
artIdx++;
|
||||
else {
|
||||
artIdx = 0;
|
||||
lastCardName = cis.name;
|
||||
}
|
||||
CardRules cr = rulesByName.get(lastCardName);
|
||||
if( cr != null )
|
||||
if( cr != null )
|
||||
addCard(new PaperCard(cr, e.getCode(), cis.rarity, artIdx));
|
||||
else if (worthLogging)
|
||||
missingCards.add(cis.name);
|
||||
@@ -121,7 +92,7 @@ public final class CardDb implements ICardDatabase {
|
||||
missingCards.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(CardRules cr : rulesByName.values()) {
|
||||
if( !allCardsByName.containsKey(cr.getName()) )
|
||||
{
|
||||
@@ -129,7 +100,7 @@ public final class CardDb implements ICardDatabase {
|
||||
addCard(new PaperCard(cr, CardEdition.UNKNOWN.getCode(), CardRarity.Special, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
reIndex();
|
||||
}
|
||||
|
||||
@@ -182,7 +153,7 @@ public final class CardDb implements ICardDatabase {
|
||||
public PaperCard tryGetCard(final String cardName0) {
|
||||
return tryGetCard(cardName0, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PaperCard tryGetCard(final String cardName0, boolean fromLastSet) {
|
||||
if (null == cardName0) {
|
||||
@@ -191,23 +162,23 @@ public final class CardDb implements ICardDatabase {
|
||||
|
||||
final boolean isFoil = this.isFoil(cardName0);
|
||||
final String cardName = isFoil ? this.removeFoilSuffix(cardName0) : cardName0;
|
||||
|
||||
|
||||
final ImmutablePair<String, String> nameWithSet = CardDb.splitCardName(cardName);
|
||||
|
||||
final PaperCard res = nameWithSet.right == null
|
||||
? ( fromLastSet ? this.uniqueCardsByName.get(nameWithSet.left) : Aggregates.random(this.allCardsByName.get(nameWithSet.left)) )
|
||||
|
||||
final PaperCard res = nameWithSet.right == null
|
||||
? ( fromLastSet ? this.uniqueCardsByName.get(nameWithSet.left) : Aggregates.random(this.allCardsByName.get(nameWithSet.left)) )
|
||||
: tryGetCard(nameWithSet.left, nameWithSet.right);
|
||||
return null != res && isFoil ? getFoiled(res) : res;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PaperCard tryGetCardPrintedByDate(final String name0, final boolean fromLatestSet, final Date printedBefore) {
|
||||
final boolean isFoil = this.isFoil(name0);
|
||||
final String cardName = isFoil ? this.removeFoilSuffix(name0) : name0;
|
||||
final ImmutablePair<String, String> nameWithSet = CardDb.splitCardName(cardName);
|
||||
|
||||
|
||||
PaperCard res = null;
|
||||
if (null != nameWithSet.right) // set explicitly requested, should return card from it and disregard the date
|
||||
if (null != nameWithSet.right) // set explicitly requested, should return card from it and disregard the date
|
||||
res = tryGetCard(nameWithSet.left, nameWithSet.right);
|
||||
else {
|
||||
Collection<PaperCard> cards = this.allCardsByName.get(nameWithSet.left); // cards are sorted by datetime desc
|
||||
@@ -223,13 +194,12 @@ public final class CardDb implements ICardDatabase {
|
||||
|
||||
return null != res && isFoil ? getFoiled(res) : res;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PaperCard tryGetCard(final String cardName, String setName) {
|
||||
return tryGetCard(cardName, setName, -1);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PaperCard tryGetCard(final String cardName0, String setName, int index) {
|
||||
final boolean isFoil = this.isFoil(cardName0);
|
||||
@@ -239,7 +209,7 @@ public final class CardDb implements ICardDatabase {
|
||||
if ( null == cards ) return null;
|
||||
|
||||
CardEdition edition = editions.get(setName);
|
||||
if ( null == edition )
|
||||
if ( null == edition )
|
||||
return tryGetCard(cardName, true); // set not found, try to get the same card from just any set.
|
||||
String effectiveSet = edition.getCode();
|
||||
|
||||
@@ -254,7 +224,7 @@ public final class CardDb implements ICardDatabase {
|
||||
|
||||
if (cnt == 0 ) return null;
|
||||
result = cnt == 1 ? candidates[0] : candidates[MyRandom.getRandom().nextInt(cnt)];
|
||||
} else
|
||||
} else
|
||||
for( PaperCard pc : cards ) {
|
||||
if( pc.getEdition().equalsIgnoreCase(effectiveSet) && index == pc.getArtIndex() ) {
|
||||
result = pc;
|
||||
@@ -264,7 +234,7 @@ public final class CardDb implements ICardDatabase {
|
||||
if ( result == null ) return null;
|
||||
return isFoil ? getFoiled(result) : result;
|
||||
}
|
||||
|
||||
|
||||
public PaperCard getFoiled(PaperCard card0) {
|
||||
// Here - I am still unsure if there should be a cache Card->Card from unfoiled to foiled, to avoid creation of N instances of single plains
|
||||
return new PaperCard(card0.getRules(), card0.getEdition(), card0.getRarity(), card0.getArtIndex(), true);
|
||||
@@ -279,17 +249,17 @@ public final class CardDb implements ICardDatabase {
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMaxPrintCount(String cardName) {
|
||||
int max = -1;
|
||||
for( PaperCard pc : allCardsByName.get(cardName) ) {
|
||||
if ( max < pc.getArtIndex() )
|
||||
if ( max < pc.getArtIndex() )
|
||||
max = pc.getArtIndex();
|
||||
}
|
||||
return max + 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Single fetch
|
||||
@Override
|
||||
public PaperCard getCard(final String name) {
|
||||
@@ -306,8 +276,7 @@ public final class CardDb implements ICardDatabase {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public PaperCard getCardPrintedByDate(final String name0, final boolean fromLatestSet, Date printedBefore ) {
|
||||
// Sometimes they read from decks things like "CardName|Set" - but we
|
||||
@@ -317,8 +286,8 @@ public final class CardDb implements ICardDatabase {
|
||||
throw new NoSuchElementException(String.format("Card '%s' released before %s not found in our database.", name0, printedBefore.toString()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Advanced fetch by name+set
|
||||
@Override
|
||||
public PaperCard getCard(final String name, final String set) {
|
||||
@@ -327,7 +296,6 @@ public final class CardDb implements ICardDatabase {
|
||||
|
||||
@Override
|
||||
public PaperCard getCard(final String name, final String set, final int artIndex) {
|
||||
|
||||
final PaperCard result = tryGetCard(name, set, artIndex);
|
||||
if (null == result) {
|
||||
final String message = String.format("Asked for '%s' from '%s' #%d: db didn't find that copy.", name, set, artIndex);
|
||||
@@ -336,21 +304,6 @@ public final class CardDb implements ICardDatabase {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Fetch from Forge's Card instance. Well, there should be no errors, but
|
||||
// we'll still check
|
||||
public static PaperCard getCard(final Card forgeCard) {
|
||||
final String name = forgeCard.getName();
|
||||
final String set = forgeCard.getCurSetCode();
|
||||
|
||||
if (StringUtils.isNotBlank(set)) {
|
||||
PaperCard cp = variants().tryGetCard(name, set);
|
||||
|
||||
return cp == null ? instance().getCard(name, set) : cp;
|
||||
}
|
||||
PaperCard cp = variants().tryGetCard(name, true);
|
||||
return cp == null ? instance().getCard(name) : cp;
|
||||
}
|
||||
|
||||
// returns a list of all cards from their respective latest editions
|
||||
@Override
|
||||
public Collection<PaperCard> getUniqueCards() {
|
||||
@@ -368,29 +321,15 @@ public final class CardDb implements ICardDatabase {
|
||||
return Lists.newArrayList(Iterables.filter(this.roAllCards, predicate));
|
||||
}
|
||||
|
||||
private static class CardSorter{
|
||||
// Here are refs, get them by name
|
||||
public final Map<String, CardRules> regularCards = new TreeMap<String, CardRules>(String.CASE_INSENSITIVE_ORDER);
|
||||
public final Map<String, CardRules> variantsCards = new TreeMap<String, CardRules>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
|
||||
CardSorter(final Iterable<CardRules> parser) {
|
||||
for (CardRules card : parser) {
|
||||
if (null == card) continue;
|
||||
|
||||
final String cardName = card.getName();
|
||||
if ( card.isVariant() )
|
||||
variantsCards.put(cardName, card);
|
||||
else
|
||||
regularCards.put(cardName, card);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public Iterator<PaperCard> iterator() {
|
||||
return this.roAllCards.iterator();
|
||||
}
|
||||
|
||||
public Predicate<? super PaperCard> wasPrintedInSets(List<String> setCodes) {
|
||||
return new PredicateExistsInSets(setCodes);
|
||||
}
|
||||
|
||||
|
||||
private class PredicateExistsInSets implements Predicate<PaperCard> {
|
||||
private final List<String> sets;
|
||||
|
||||
@@ -401,9 +340,84 @@ public final class CardDb implements ICardDatabase {
|
||||
@Override
|
||||
public boolean apply(final PaperCard subject) {
|
||||
Collection<PaperCard> cc = allCardsByName.get(subject.getName());
|
||||
for(PaperCard c : cc) if (sets.contains(c.getEdition())) return true;
|
||||
for(PaperCard c : cc)
|
||||
if (sets.contains(c.getEdition()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final Editor editor = new Editor();
|
||||
public Editor getEditor() { return editor; }
|
||||
public class Editor {
|
||||
private boolean immediateReindex = true;
|
||||
public CardRules putCard(CardRules rules) { return putCard(rules, null); /* will use data from editions folder */ }
|
||||
public CardRules putCard(CardRules rules, List<Pair<String, CardRarity>> whenItWasPrinted){ // works similarly to Map<K,V>, returning prev. value
|
||||
String cardName = rules.getName();
|
||||
|
||||
CardRules result = rulesByName.get(cardName);
|
||||
if (result != null && result.getName().equals(cardName)){ // change properties only
|
||||
result.reinitializeFromRules(rules);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = rulesByName.put(cardName, rules);
|
||||
|
||||
// 1. generate all paper cards from edition data we have (either explicit, or found in res/editions, or add to unknown edition)
|
||||
List<PaperCard> paperCards = new ArrayList<PaperCard>();
|
||||
if (null == whenItWasPrinted || whenItWasPrinted.isEmpty()) {
|
||||
for(CardEdition e : editions.getOrderedEditions()) {
|
||||
int artIdx = 0;
|
||||
for(CardInSet cis : e.getCards()) {
|
||||
if( !cis.name.equals(cardName) )
|
||||
continue;
|
||||
paperCards.add(new PaperCard(rules, e.getCode(), cis.rarity, artIdx++));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String lastEdition = null;
|
||||
int artIdx = 0;
|
||||
for(Pair<String, CardRarity> tuple : whenItWasPrinted){
|
||||
if(!tuple.getKey().equals(lastEdition)) {
|
||||
artIdx = 0;
|
||||
lastEdition = tuple.getKey();
|
||||
}
|
||||
CardEdition ed = editions.get(lastEdition);
|
||||
if(null == ed)
|
||||
continue;
|
||||
paperCards.add(new PaperCard(rules, lastEdition, tuple.getValue(), artIdx++));
|
||||
}
|
||||
}
|
||||
if(paperCards.isEmpty())
|
||||
paperCards.add(new PaperCard(rules, CardEdition.UNKNOWN.getCode(), CardRarity.Special, 0));
|
||||
|
||||
// 2. add them to db
|
||||
for (PaperCard paperCard : paperCards)
|
||||
addCard(paperCard);
|
||||
// 3. reindex can be temporary disabled and run after the whole batch of rules is added to db.
|
||||
if(immediateReindex)
|
||||
reIndex();
|
||||
|
||||
return result;
|
||||
}
|
||||
public void removeCard(String name) {
|
||||
allCardsByName.removeAll(name);
|
||||
uniqueCardsByName.remove(name);
|
||||
rulesByName.remove(name);
|
||||
Iterator<PaperCard> it = allCards.iterator();
|
||||
while(it.hasNext()) {
|
||||
PaperCard pc = it.next();
|
||||
if( pc.getName().equalsIgnoreCase(name))
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
public void rebuildIndex() { reIndex(); }
|
||||
|
||||
public boolean isImmediateReindex() {
|
||||
return immediateReindex;
|
||||
}
|
||||
public void setImmediateReindex(boolean immediateReindex) {
|
||||
this.immediateReindex = immediateReindex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,23 +22,29 @@ import java.io.FilenameFilter;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.Constant;
|
||||
import forge.Singletons;
|
||||
import forge.game.GameFormat;
|
||||
import forge.StaticData;
|
||||
import forge.item.SealedProduct;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.FileSection;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.IItemReader;
|
||||
import forge.util.storage.StorageBase;
|
||||
import forge.util.storage.StorageReaderBase;
|
||||
import forge.util.storage.StorageReaderFolder;
|
||||
|
||||
|
||||
@@ -104,7 +110,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
|
||||
|
||||
|
||||
private int boosterArts = 1;
|
||||
private SealedProductTemplate boosterTpl = null;
|
||||
private SealedProduct.Template boosterTpl = null;
|
||||
|
||||
private CardEdition(CardInSet[] cards) {
|
||||
this.cards = cards;
|
||||
@@ -204,76 +210,20 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
|
||||
return whiteBorder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The Class Predicates.
|
||||
*/
|
||||
public abstract static class Predicates {
|
||||
|
||||
/** The Constant canMakeBooster. */
|
||||
public static final Predicate<CardEdition> CAN_MAKE_BOOSTER = new CanMakeBooster();
|
||||
|
||||
private static class CanMakeBooster implements Predicate<CardEdition> {
|
||||
@Override
|
||||
public boolean apply(final CardEdition subject) {
|
||||
return subject.boosterTpl != null;
|
||||
}
|
||||
}
|
||||
|
||||
public static final Predicate<CardEdition> HAS_TOURNAMENT_PACK = new CanMakeStarter();
|
||||
private static class CanMakeStarter implements Predicate<CardEdition> {
|
||||
@Override
|
||||
public boolean apply(final CardEdition subject) {
|
||||
return Singletons.getModel().getTournamentPacks().contains(subject.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static final Predicate<CardEdition> HAS_FAT_PACK = new CanMakeFatPack();
|
||||
private static class CanMakeFatPack implements Predicate<CardEdition> {
|
||||
@Override
|
||||
public boolean apply(final CardEdition subject) {
|
||||
return Singletons.getModel().getFatPacks().contains(subject.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is legal in format.
|
||||
*
|
||||
* @param format the format
|
||||
* @return the predicate
|
||||
*/
|
||||
public static final Predicate<CardEdition> isLegalInFormat(final GameFormat format) {
|
||||
return new LegalInFormat(format);
|
||||
}
|
||||
|
||||
private static class LegalInFormat implements Predicate<CardEdition> {
|
||||
private final GameFormat format;
|
||||
|
||||
public LegalInFormat(final GameFormat fmt) {
|
||||
this.format = fmt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(final CardEdition subject) {
|
||||
return this.format.isSetLegal(subject.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static final Predicate<CardEdition> hasBasicLands = new Predicate<CardEdition>() {
|
||||
@Override
|
||||
public boolean apply(CardEdition ed) {
|
||||
for(String landName : Constant.Color.BASIC_LANDS) {
|
||||
if (null == CardDb.instance().tryGetCard(landName, ed.getCode(), 0))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
};
|
||||
|
||||
public int getCntBoosterPictures() {
|
||||
return boosterArts;
|
||||
}
|
||||
|
||||
public static class EditionReader extends StorageReaderFolder<CardEdition> {
|
||||
public EditionReader(File path) {
|
||||
public SealedProduct.Template getBoosterTemplate() {
|
||||
return boosterTpl;
|
||||
}
|
||||
|
||||
public boolean hasBoosterTemplate() {
|
||||
return boosterTpl != null;
|
||||
}
|
||||
|
||||
public static class Reader extends StorageReaderFolder<CardEdition> {
|
||||
public Reader(File path) {
|
||||
super(path, CardEdition.FN_GET_CODE);
|
||||
}
|
||||
|
||||
@@ -309,7 +259,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
|
||||
|
||||
res.boosterArts = section.getInt("BoosterCovers", 1);
|
||||
String boosterDesc = section.get("Booster");
|
||||
res.boosterTpl = boosterDesc == null ? null : new SealedProductTemplate(res.code, SealedProductTemplate.Reader.parseSlots(boosterDesc));
|
||||
res.boosterTpl = boosterDesc == null ? null : new SealedProduct.Template(res.code, SealedProduct.Template.Reader.parseSlots(boosterDesc));
|
||||
|
||||
res.alias = section.get("alias");
|
||||
res.whiteBorder = "white".equalsIgnoreCase(section.get("border"));
|
||||
@@ -360,16 +310,146 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public final static CardEdition getRandomSetWithAllBasicLands(Iterable<CardEdition> allEditions) {
|
||||
return Aggregates.random(Iterables.filter(allEditions, CardEdition.Predicates.hasBasicLands));
|
||||
}
|
||||
|
||||
public int getCntBoosterPictures() {
|
||||
return boosterArts;
|
||||
}
|
||||
public static class Collection extends StorageBase<CardEdition> {
|
||||
|
||||
public SealedProductTemplate getBoosterTemplate() {
|
||||
return boosterTpl;
|
||||
private final Map<String, CardEdition> aliasToEdition = new TreeMap<String, CardEdition>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
public Collection(IItemReader<CardEdition> reader) {
|
||||
super("Card editions", reader);
|
||||
|
||||
for (CardEdition ee : this) {
|
||||
String alias = ee.getAlias();
|
||||
if (null != alias) {
|
||||
aliasToEdition.put(alias, ee);
|
||||
}
|
||||
aliasToEdition.put(ee.getCode2(), ee);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a sets by code. It will search first by three letter codes, then by aliases and two-letter codes.
|
||||
*
|
||||
* @param code
|
||||
* the code
|
||||
* @return the sets the by code
|
||||
*/
|
||||
@Override
|
||||
public CardEdition get(final String code) {
|
||||
CardEdition baseResult = super.get(code);
|
||||
return baseResult == null ? aliasToEdition.get(code) : baseResult;
|
||||
}
|
||||
|
||||
|
||||
public Iterable<CardEdition> getOrderedEditions() {
|
||||
List<CardEdition> res = Lists.newArrayList(this);
|
||||
Collections.sort(res);
|
||||
Collections.reverse(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sets by code or throw.
|
||||
*
|
||||
* @param code
|
||||
* the code
|
||||
* @return the sets the by code or throw
|
||||
*/
|
||||
public CardEdition getEditionByCodeOrThrow(final String code) {
|
||||
final CardEdition set = this.get(code);
|
||||
if (null == set) {
|
||||
throw new RuntimeException(String.format("Edition with code '%s' not found", code));
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
// used by image generating code
|
||||
/**
|
||||
* Gets the code2 by code.
|
||||
*
|
||||
* @param code
|
||||
* the code
|
||||
* @return the code2 by code
|
||||
*/
|
||||
public String getCode2ByCode(final String code) {
|
||||
final CardEdition set = this.get(code);
|
||||
return set == null ? "" : set.getCode2();
|
||||
}
|
||||
|
||||
public final Function<String, CardEdition> FN_EDITION_BY_CODE = new Function<String, CardEdition>() {
|
||||
@Override
|
||||
public CardEdition apply(String code) {
|
||||
return Collection.this.get(code);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
* @return
|
||||
*/
|
||||
public IItemReader<SealedProduct.Template> getBoosterGenerator() {
|
||||
// TODO Auto-generated method stub
|
||||
return new StorageReaderBase<SealedProduct.Template>(null) {
|
||||
|
||||
@Override
|
||||
public Map<String, SealedProduct.Template> readAll() {
|
||||
Map<String, SealedProduct.Template> map = new TreeMap<String, SealedProduct.Template>(String.CASE_INSENSITIVE_ORDER);
|
||||
for(CardEdition ce : Collection.this) {
|
||||
map.put(ce.getCode(), ce.getBoosterTemplate());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemKey(SealedProduct.Template item) {
|
||||
return item.getEdition();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
public static class Predicates {
|
||||
|
||||
/** The Constant canMakeBooster. */
|
||||
public static final Predicate<CardEdition> CAN_MAKE_BOOSTER = new CanMakeBooster();
|
||||
|
||||
private static class CanMakeBooster implements Predicate<CardEdition> {
|
||||
@Override
|
||||
public boolean apply(final CardEdition subject) {
|
||||
return subject.hasBoosterTemplate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public final static CardEdition getRandomSetWithAllBasicLands(Iterable<CardEdition> allEditions) {
|
||||
return Aggregates.random(Iterables.filter(allEditions, hasBasicLands));
|
||||
}
|
||||
|
||||
public static final Predicate<CardEdition> HAS_TOURNAMENT_PACK = new CanMakeStarter();
|
||||
private static class CanMakeStarter implements Predicate<CardEdition> {
|
||||
@Override
|
||||
public boolean apply(final CardEdition subject) {
|
||||
return StaticData.instance().getTournamentPacks().contains(subject.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static final Predicate<CardEdition> HAS_FAT_PACK = new CanMakeFatPack();
|
||||
private static class CanMakeFatPack implements Predicate<CardEdition> {
|
||||
@Override
|
||||
public boolean apply(final CardEdition subject) {
|
||||
return StaticData.instance().getFatPacks().contains(subject.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static final Predicate<CardEdition> hasBasicLands = new Predicate<CardEdition>() {
|
||||
@Override
|
||||
public boolean apply(CardEdition ed) {
|
||||
for(String landName : MagicColor.Constant.BASIC_LANDS) {
|
||||
if (null == StaticData.instance().getCommonCards().tryGetCard(landName, ed.getCode(), 0))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,13 @@ import forge.card.mana.ManaCost;
|
||||
*/
|
||||
final class CardFace implements ICardFace {
|
||||
|
||||
public enum FaceSelectionMethod { //
|
||||
USE_ACTIVE_FACE,
|
||||
USE_PRIMARY_FACE,
|
||||
COMBINE;
|
||||
}
|
||||
|
||||
|
||||
private final static List<String> emptyList = Collections.unmodifiableList(new ArrayList<String>());
|
||||
private final static Map<String, String> emptyMap = Collections.unmodifiableMap(new TreeMap<String, String>());
|
||||
|
||||
478
forge-core/src/main/java/forge/card/CardRules.java
Normal file
478
forge-core/src/main/java/forge/card/CardRules.java
Normal file
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.card;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.card.mana.IParserManaCost;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.mana.ManaCostShard;
|
||||
|
||||
/**
|
||||
* A collection of methods containing full
|
||||
* meta and gameplay properties of a card.
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: CardRules.java 9708 2011-08-09 19:34:12Z jendave $
|
||||
*/
|
||||
public final class CardRules implements ICardCharacteristics {
|
||||
private CardSplitType splitType;
|
||||
private ICardFace mainPart;
|
||||
private ICardFace otherPart;
|
||||
private CardAiHints aiHints;
|
||||
private ColorSet colorIdentity = null;
|
||||
|
||||
private CardRules(ICardFace[] faces, CardSplitType altMode, CardAiHints cah) {
|
||||
splitType = altMode;
|
||||
mainPart = faces[0];
|
||||
otherPart = faces[1];
|
||||
aiHints = cah;
|
||||
|
||||
//Calculate Color Identity
|
||||
byte colMask = calculateColorIdentity(mainPart);
|
||||
|
||||
if(otherPart != null)
|
||||
{
|
||||
colMask |= calculateColorIdentity(otherPart);
|
||||
}
|
||||
colorIdentity = ColorSet.fromMask(colMask);
|
||||
}
|
||||
|
||||
void reinitializeFromRules(CardRules newRules) {
|
||||
if(!newRules.getName().equals(this.getName()))
|
||||
throw new UnsupportedOperationException("You cannot rename the card using the same CardRules object");
|
||||
|
||||
splitType = newRules.splitType;
|
||||
mainPart = newRules.mainPart;
|
||||
otherPart = newRules.otherPart;
|
||||
aiHints = newRules.aiHints;
|
||||
colorIdentity = newRules.colorIdentity;
|
||||
}
|
||||
|
||||
private byte calculateColorIdentity(ICardFace face) {
|
||||
byte res = face.getColor().getColor();
|
||||
boolean isReminder = false;
|
||||
boolean isSymbol = false;
|
||||
String oracleText = face.getOracleText();
|
||||
int len = oracleText.length();
|
||||
for(int i = 0; i < len; i++) {
|
||||
char c = oracleText.charAt(i); // This is to avoid needless allocations performed by toCharArray()
|
||||
switch(c) {
|
||||
case('('): isReminder = i > 0; break; // if oracle has only reminder, consider it valid rules (basic and true lands need this)
|
||||
case(')'): isReminder = false; break;
|
||||
case('{'): isSymbol = true; break;
|
||||
case('}'): isSymbol = false; break;
|
||||
default:
|
||||
if(isSymbol && !isReminder) {
|
||||
switch(c) {
|
||||
case('W'): res |= MagicColor.WHITE; break;
|
||||
case('U'): res |= MagicColor.BLUE; break;
|
||||
case('B'): res |= MagicColor.BLACK; break;
|
||||
case('R'): res |= MagicColor.RED; break;
|
||||
case('G'): res |= MagicColor.GREEN; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public boolean isVariant() {
|
||||
CardType t = getType();
|
||||
return t.isVanguard() || t.isScheme() || t.isPlane() || t.isPhenomenon();
|
||||
}
|
||||
|
||||
public CardSplitType getSplitType() {
|
||||
return splitType;
|
||||
}
|
||||
|
||||
public ICardFace getMainPart() {
|
||||
return mainPart;
|
||||
}
|
||||
|
||||
public ICardFace getOtherPart() {
|
||||
return otherPart;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
switch(splitType.getAggregationMethod()) {
|
||||
case COMBINE:
|
||||
return mainPart.getName() + " // " + otherPart.getName();
|
||||
default:
|
||||
return mainPart.getName();
|
||||
}
|
||||
}
|
||||
|
||||
public CardAiHints getAiHints() {
|
||||
return aiHints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardType getType() {
|
||||
switch(splitType.getAggregationMethod()) {
|
||||
case COMBINE: // no cards currently have different types
|
||||
return CardType.combine(mainPart.getType(), otherPart.getType());
|
||||
default:
|
||||
return mainPart.getType();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ManaCost getManaCost() {
|
||||
switch(splitType.getAggregationMethod()) {
|
||||
case COMBINE:
|
||||
return ManaCost.combine(mainPart.getManaCost(), otherPart.getManaCost());
|
||||
default:
|
||||
return mainPart.getManaCost();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorSet getColor() {
|
||||
switch(splitType.getAggregationMethod()) {
|
||||
case COMBINE:
|
||||
return ColorSet.fromMask(mainPart.getColor().getColor() | otherPart.getColor().getColor());
|
||||
default:
|
||||
return mainPart.getColor();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public int getIntPower() { return mainPart.getIntPower(); }
|
||||
@Override public int getIntToughness() { return mainPart.getIntToughness(); }
|
||||
@Override public String getPower() { return mainPart.getPower(); }
|
||||
@Override public String getToughness() { return mainPart.getToughness(); }
|
||||
@Override public int getInitialLoyalty() { return mainPart.getInitialLoyalty(); }
|
||||
|
||||
@Override
|
||||
public String getOracleText() {
|
||||
switch(splitType.getAggregationMethod()) {
|
||||
case COMBINE:
|
||||
return mainPart.getOracleText() + "\r\n\r\n" + otherPart.getOracleText();
|
||||
default:
|
||||
return mainPart.getOracleText();
|
||||
}
|
||||
}
|
||||
|
||||
// public Set<String> getSets() { return this.setsPrinted.keySet(); }
|
||||
// public CardInSet getEditionInfo(final String setCode) {
|
||||
// final CardInSet result = this.setsPrinted.get(setCode);
|
||||
// return result; // if returns null, String.format("Card '%s' was never printed in set '%s'", this.getName(), setCode);
|
||||
// }
|
||||
|
||||
// vanguard card fields, they don't use sides.
|
||||
private int deltaHand;
|
||||
private int deltaLife;
|
||||
|
||||
public int getHand() { return deltaHand; }
|
||||
public int getLife() { return deltaLife; }
|
||||
public void setVanguardProperties(String pt) {
|
||||
final int slashPos = pt == null ? -1 : pt.indexOf('/');
|
||||
if (slashPos == -1) {
|
||||
throw new RuntimeException(String.format("Vanguard '%s' has bad hand/life stats", this.getName()));
|
||||
}
|
||||
this.deltaHand = Integer.parseInt(pt.substring(0, slashPos).replace("+", ""));
|
||||
this.deltaLife = Integer.parseInt(pt.substring(slashPos+1).replace("+", ""));
|
||||
}
|
||||
|
||||
// Downloadable image
|
||||
private String dlUrl;
|
||||
private String dlUrlOtherSide;
|
||||
public String getPictureUrl(boolean backface ) { return backface ? dlUrlOtherSide : dlUrl; }
|
||||
public void setDlUrls(String[] dlUrls) { this.dlUrl = dlUrls[0]; this.dlUrlOtherSide = dlUrls[1]; }
|
||||
|
||||
public final List<String> getReplacements() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final List<String> getTriggers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final List<String> getStaticAbilities() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final List<String> getAbilities() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ColorSet getColorIdentity() {
|
||||
return colorIdentity;
|
||||
}
|
||||
|
||||
/** Instantiates class, reads a card. For batch operations better create you own reader instance. */
|
||||
public static CardRules fromScript(Iterable<String> script) {
|
||||
Reader crr = new Reader();
|
||||
for(String line : script) {
|
||||
crr.parseLine(line);
|
||||
}
|
||||
return crr.getCard();
|
||||
}
|
||||
|
||||
// Reads cardname.txt
|
||||
public static class Reader {
|
||||
// fields to build
|
||||
private CardFace[] faces = new CardFace[] { null, null };
|
||||
private String[] pictureUrl = new String[] { null, null };
|
||||
private int curFace = 0;
|
||||
private CardSplitType altMode = CardSplitType.None;
|
||||
private String handLife = null;
|
||||
|
||||
// fields to build CardAiHints
|
||||
private boolean removedFromAIDecks = false;
|
||||
private boolean removedFromRandomDecks = false;
|
||||
private DeckHints hints = null;
|
||||
private DeckHints needs = null;
|
||||
|
||||
/**
|
||||
* Reset all fields to parse next card (to avoid allocating new CardRulesReader N times)
|
||||
*/
|
||||
public final void reset() {
|
||||
this.curFace = 0;
|
||||
this.faces[0] = null;
|
||||
this.faces[1] = null;
|
||||
this.pictureUrl[0] = null;
|
||||
this.pictureUrl[1] = null;
|
||||
|
||||
this.handLife = null;
|
||||
this.altMode = CardSplitType.None;
|
||||
|
||||
this.removedFromAIDecks = false;
|
||||
this.removedFromRandomDecks = false;
|
||||
this.needs = null;
|
||||
this.hints = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the card.
|
||||
*
|
||||
* @return the card
|
||||
*/
|
||||
public final CardRules getCard() {
|
||||
CardAiHints cah = new CardAiHints(removedFromAIDecks, removedFromRandomDecks, hints, needs );
|
||||
faces[0].assignMissingFields();
|
||||
if (null != faces[1]) faces[1].assignMissingFields();
|
||||
final CardRules result = new CardRules(faces, altMode, cah);
|
||||
result.setDlUrls(pictureUrl);
|
||||
if (StringUtils.isNotBlank(handLife))
|
||||
result.setVanguardProperties(handLife);
|
||||
return result;
|
||||
}
|
||||
|
||||
public final CardRules readCard(final Iterable<String> script) {
|
||||
this.reset();
|
||||
for (String line : script) {
|
||||
if (line.isEmpty() || line.charAt(0) == '#') {
|
||||
continue;
|
||||
}
|
||||
this.parseLine(line);
|
||||
}
|
||||
return this.getCard();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the line.
|
||||
*
|
||||
* @param line
|
||||
* the line
|
||||
*/
|
||||
public final void parseLine(final String line) {
|
||||
int colonPos = line.indexOf(':');
|
||||
String key = colonPos > 0 ? line.substring(0, colonPos) : line;
|
||||
String value = colonPos > 0 ? line.substring(1+colonPos).trim() : null;
|
||||
|
||||
switch(key.charAt(0)) {
|
||||
case 'A':
|
||||
if ("A".equals(key))
|
||||
this.faces[curFace].addAbility(value);
|
||||
else if ("AlternateMode".equals(key)) {
|
||||
//System.out.println(faces[curFace].getName());
|
||||
this.altMode = CardSplitType.smartValueOf(value);
|
||||
} else if ("ALTERNATE".equals(key)) {
|
||||
this.curFace = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
if ("Colors".equals(key)) {
|
||||
// This is forge.card.CardColor not forge.CardColor.
|
||||
// Why do we have two classes with the same name?
|
||||
ColorSet newCol = ColorSet.fromNames(value.split(","));
|
||||
this.faces[this.curFace].setColor(newCol);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
if ("DeckHints".equals(key)) {
|
||||
hints = new DeckHints(value);
|
||||
} else if ("DeckNeeds".equals(key)) {
|
||||
needs = new DeckHints(value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
if ("HandLifeModifier".equals(key)) {
|
||||
handLife = value;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'K':
|
||||
if ("K".equals(key)) {
|
||||
this.faces[this.curFace].addKeyword(value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
if ("Loyalty".equals(key)) {
|
||||
this.faces[this.curFace].setInitialLoyalty(Integer.valueOf(value));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if ("ManaCost".equals(key)) {
|
||||
this.faces[this.curFace].setManaCost("no cost".equals(value) ? ManaCost.NO_COST
|
||||
: new ManaCost(new ManaCostParser(value)));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
if ("Name".equals(key)) {
|
||||
this.faces[this.curFace] = new CardFace(value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
if ("Oracle".equals(key)) {
|
||||
this.faces[this.curFace].setOracleText(value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
if ("PT".equals(key)) {
|
||||
this.faces[this.curFace].setPtText(value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
if ("R".equals(key)) {
|
||||
this.faces[this.curFace].addReplacementEffect(value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
if ("S".equals(key)) {
|
||||
this.faces[this.curFace].addStaticAbility(value);
|
||||
} else if ( "SVar".equals(key) ) {
|
||||
if ( null == value ) throw new IllegalArgumentException("SVar has no variable name");
|
||||
|
||||
colonPos = value.indexOf(':');
|
||||
String variable = colonPos > 0 ? value.substring(0, colonPos) : value;
|
||||
value = colonPos > 0 ? value.substring(1+colonPos) : null;
|
||||
|
||||
if ( "RemAIDeck".equals(variable) ) {
|
||||
this.removedFromAIDecks = "True".equalsIgnoreCase(value);
|
||||
} else if ( "RemRandomDeck".equals(variable) ) {
|
||||
this.removedFromRandomDecks = "True".equalsIgnoreCase(value);
|
||||
} else if ( "Picture".equals(variable) ) {
|
||||
this.pictureUrl[this.curFace] = value;
|
||||
} else if ( "Rarity".equals(variable) ) {
|
||||
// discard that, they should supply it in SetInfo
|
||||
} else
|
||||
this.faces[curFace].addSVar(variable, value);
|
||||
} else if ("SetInfo".equals(key)) {
|
||||
// deprecated
|
||||
}
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
if ("T".equals(key)) {
|
||||
this.faces[this.curFace].addTrigger(value);
|
||||
} else if ("Types".equals(key)) {
|
||||
this.faces[this.curFace].setType(CardType.parse(value));
|
||||
} else if ("Text".equals(key) && !"no text".equals(value) && StringUtils.isNotBlank(value)) {
|
||||
this.faces[this.curFace].setNonAbilityText(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Class ParserCardnameTxtManaCost.
|
||||
*/
|
||||
private static class ManaCostParser implements IParserManaCost {
|
||||
private final StringTokenizer st;
|
||||
private int colorlessCost;
|
||||
|
||||
public ManaCostParser(final String cost) {
|
||||
st = new StringTokenizer(cost, " ");
|
||||
this.colorlessCost = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getTotalColorlessCost() {
|
||||
if (this.hasNext()) {
|
||||
throw new RuntimeException("Colorless cost should be obtained after iteration is complete");
|
||||
}
|
||||
return this.colorlessCost;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.util.Iterator#hasNext()
|
||||
*/
|
||||
@Override
|
||||
public final boolean hasNext() {
|
||||
return st.hasMoreTokens();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.util.Iterator#next()
|
||||
*/
|
||||
@Override
|
||||
public final ManaCostShard next() {
|
||||
final String unparsed = st.nextToken();
|
||||
// System.out.println(unparsed);
|
||||
try {
|
||||
int iVal = Integer.parseInt(unparsed);
|
||||
this.colorlessCost += iVal;
|
||||
return null;
|
||||
}
|
||||
catch (NumberFormatException nex) { }
|
||||
|
||||
return ManaCostShard.parseNonGeneric(unparsed);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.util.Iterator#remove()
|
||||
*/
|
||||
@Override
|
||||
public void remove() {
|
||||
} // unsuported
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,7 +170,7 @@ public final class CardRulesPredicates {
|
||||
*/
|
||||
public static Predicate<CardRules> coreType(final boolean isEqual, final String what) {
|
||||
try {
|
||||
return CardRulesPredicates.coreType(isEqual, Enum.valueOf(CardCoreType.class, what));
|
||||
return CardRulesPredicates.coreType(isEqual, Enum.valueOf(CardType.CoreType.class, what));
|
||||
} catch (final Exception e) {
|
||||
return com.google.common.base.Predicates.alwaysFalse();
|
||||
}
|
||||
@@ -185,7 +185,7 @@ public final class CardRulesPredicates {
|
||||
* the type
|
||||
* @return the predicate
|
||||
*/
|
||||
public static Predicate<CardRules> coreType(final boolean isEqual, final CardCoreType type) {
|
||||
public static Predicate<CardRules> coreType(final boolean isEqual, final CardType.CoreType type) {
|
||||
return new PredicateCoreType(type, isEqual);
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ public final class CardRulesPredicates {
|
||||
*/
|
||||
public static Predicate<CardRules> superType(final boolean isEqual, final String what) {
|
||||
try {
|
||||
return CardRulesPredicates.superType(isEqual, Enum.valueOf(CardSuperType.class, what));
|
||||
return CardRulesPredicates.superType(isEqual, Enum.valueOf(CardType.SuperType.class, what));
|
||||
} catch (final Exception e) {
|
||||
return com.google.common.base.Predicates.alwaysFalse();
|
||||
}
|
||||
@@ -215,7 +215,7 @@ public final class CardRulesPredicates {
|
||||
* the type
|
||||
* @return the predicate
|
||||
*/
|
||||
public static Predicate<CardRules> superType(final boolean isEqual, final CardSuperType type) {
|
||||
public static Predicate<CardRules> superType(final boolean isEqual, final CardType.SuperType type) {
|
||||
return new PredicateSuperType(type, isEqual);
|
||||
}
|
||||
|
||||
@@ -396,7 +396,7 @@ public final class CardRulesPredicates {
|
||||
}
|
||||
|
||||
private static class PredicateCoreType implements Predicate<CardRules> {
|
||||
private final CardCoreType operand;
|
||||
private final CardType.CoreType operand;
|
||||
private final boolean shouldBeEqual;
|
||||
|
||||
@Override
|
||||
@@ -407,14 +407,14 @@ public final class CardRulesPredicates {
|
||||
return this.shouldBeEqual == card.getType().typeContains(this.operand);
|
||||
}
|
||||
|
||||
public PredicateCoreType(final CardCoreType type, final boolean wantEqual) {
|
||||
public PredicateCoreType(final CardType.CoreType type, final boolean wantEqual) {
|
||||
this.operand = type;
|
||||
this.shouldBeEqual = wantEqual;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PredicateSuperType implements Predicate<CardRules> {
|
||||
private final CardSuperType operand;
|
||||
private final CardType.SuperType operand;
|
||||
private final boolean shouldBeEqual;
|
||||
|
||||
@Override
|
||||
@@ -422,7 +422,7 @@ public final class CardRulesPredicates {
|
||||
return this.shouldBeEqual == card.getType().superTypeContains(this.operand);
|
||||
}
|
||||
|
||||
public PredicateSuperType(final CardSuperType type, final boolean wantEqual) {
|
||||
public PredicateSuperType(final CardType.SuperType type, final boolean wantEqual) {
|
||||
this.operand = type;
|
||||
this.shouldBeEqual = wantEqual;
|
||||
}
|
||||
@@ -448,21 +448,21 @@ public final class CardRulesPredicates {
|
||||
|
||||
/** The Constant isCreature. */
|
||||
public static final Predicate<CardRules> IS_CREATURE = CardRulesPredicates
|
||||
.coreType(true, CardCoreType.Creature);
|
||||
.coreType(true, CardType.CoreType.Creature);
|
||||
|
||||
public static final Predicate<CardRules> IS_LEGENDARY = CardRulesPredicates
|
||||
.superType(true, CardSuperType.Legendary);
|
||||
.superType(true, CardType.SuperType.Legendary);
|
||||
|
||||
/** The Constant isArtifact. */
|
||||
public static final Predicate<CardRules> IS_ARTIFACT = CardRulesPredicates
|
||||
.coreType(true, CardCoreType.Artifact);
|
||||
.coreType(true, CardType.CoreType.Artifact);
|
||||
|
||||
/** The Constant isEquipment. */
|
||||
public static final Predicate<CardRules> IS_EQUIPMENT = CardRulesPredicates
|
||||
.subType("Equipment");
|
||||
|
||||
/** The Constant isLand. */
|
||||
public static final Predicate<CardRules> IS_LAND = CardRulesPredicates.coreType(true, CardCoreType.Land);
|
||||
public static final Predicate<CardRules> IS_LAND = CardRulesPredicates.coreType(true, CardType.CoreType.Land);
|
||||
|
||||
/** The Constant isBasicLand. */
|
||||
public static final Predicate<CardRules> IS_BASIC_LAND = new Predicate<CardRules>() {
|
||||
@@ -480,31 +480,17 @@ public final class CardRulesPredicates {
|
||||
}
|
||||
};
|
||||
|
||||
/** The Constant isPlaneswalker. */
|
||||
public static final Predicate<CardRules> IS_PLANESWALKER = CardRulesPredicates.coreType(true,
|
||||
CardCoreType.Planeswalker);
|
||||
|
||||
/** The Constant isInstant. */
|
||||
public static final Predicate<CardRules> IS_INSTANT = CardRulesPredicates.coreType(true, CardCoreType.Instant);
|
||||
|
||||
/** The Constant isSorcery. */
|
||||
public static final Predicate<CardRules> IS_SORCERY = CardRulesPredicates.coreType(true, CardCoreType.Sorcery);
|
||||
|
||||
/** The Constant isEnchantment. */
|
||||
public static final Predicate<CardRules> IS_ENCHANTMENT = CardRulesPredicates.coreType(true, CardCoreType.Enchantment);
|
||||
|
||||
public static final Predicate<CardRules> IS_PLANE = CardRulesPredicates.coreType(true, CardCoreType.Plane);
|
||||
public static final Predicate<CardRules> IS_PHENOMENON = CardRulesPredicates.coreType(true, CardCoreType.Phenomenon);
|
||||
public static final Predicate<CardRules> IS_PLANESWALKER = CardRulesPredicates.coreType(true, CardType.CoreType.Planeswalker);
|
||||
public static final Predicate<CardRules> IS_INSTANT = CardRulesPredicates.coreType(true, CardType.CoreType.Instant);
|
||||
public static final Predicate<CardRules> IS_SORCERY = CardRulesPredicates.coreType(true, CardType.CoreType.Sorcery);
|
||||
public static final Predicate<CardRules> IS_ENCHANTMENT = CardRulesPredicates.coreType(true, CardType.CoreType.Enchantment);
|
||||
public static final Predicate<CardRules> IS_PLANE = CardRulesPredicates.coreType(true, CardType.CoreType.Plane);
|
||||
public static final Predicate<CardRules> IS_PHENOMENON = CardRulesPredicates.coreType(true, CardType.CoreType.Phenomenon);
|
||||
public static final Predicate<CardRules> IS_PLANE_OR_PHENOMENON = Predicates.or(IS_PLANE, IS_PHENOMENON);
|
||||
public static final Predicate<CardRules> IS_SCHEME = CardRulesPredicates.coreType(true, CardCoreType.Scheme);
|
||||
public static final Predicate<CardRules> IS_VANGUARD = CardRulesPredicates.coreType(true, CardCoreType.Vanguard);
|
||||
|
||||
/** The Constant isNonLand. */
|
||||
public static final Predicate<CardRules> IS_NON_LAND = CardRulesPredicates.coreType(false, CardCoreType.Land);
|
||||
|
||||
/** The Constant isNonCreatureSpell. */
|
||||
public static final Predicate<CardRules> IS_NON_CREATURE_SPELL = Predicates.not(Predicates.or(
|
||||
Presets.IS_CREATURE, Presets.IS_LAND));
|
||||
public static final Predicate<CardRules> IS_SCHEME = CardRulesPredicates.coreType(true, CardType.CoreType.Scheme);
|
||||
public static final Predicate<CardRules> IS_VANGUARD = CardRulesPredicates.coreType(true, CardType.CoreType.Vanguard);
|
||||
public static final Predicate<CardRules> IS_NON_LAND = CardRulesPredicates.coreType(false, CardType.CoreType.Land);
|
||||
public static final Predicate<CardRules> IS_NON_CREATURE_SPELL = Predicates.not(Predicates.or(Presets.IS_CREATURE, Presets.IS_LAND));
|
||||
|
||||
/** The Constant IS_NONCREATURE_SPELL_FOR_GENERATOR. **/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -1,26 +1,26 @@
|
||||
package forge.card;
|
||||
|
||||
import forge.CardCharacteristicName;
|
||||
import forge.card.CardFace.FaceSelectionMethod;
|
||||
|
||||
public enum CardSplitType
|
||||
{
|
||||
None(AggregationMethod.USE_PRIMARY_FACE, null),
|
||||
Transform(AggregationMethod.USE_ACTIVE_FACE, CardCharacteristicName.Transformed),
|
||||
Split(AggregationMethod.AGGREGATE, CardCharacteristicName.RightSplit),
|
||||
Flip(AggregationMethod.USE_PRIMARY_FACE, CardCharacteristicName.Flipped),
|
||||
None(FaceSelectionMethod.USE_PRIMARY_FACE, null),
|
||||
Transform(FaceSelectionMethod.USE_ACTIVE_FACE, CardCharacteristicName.Transformed),
|
||||
Split(FaceSelectionMethod.COMBINE, CardCharacteristicName.RightSplit),
|
||||
Flip(FaceSelectionMethod.USE_PRIMARY_FACE, CardCharacteristicName.Flipped),
|
||||
// used by 12 licid creatures to switch type into enchantment aura
|
||||
Licid(AggregationMethod.USE_PRIMARY_FACE, CardCharacteristicName.Licid);
|
||||
Licid(FaceSelectionMethod.USE_PRIMARY_FACE, CardCharacteristicName.Licid);
|
||||
|
||||
private CardSplitType(AggregationMethod calcMode, CardCharacteristicName stateName) {
|
||||
private CardSplitType(FaceSelectionMethod calcMode, CardCharacteristicName stateName) {
|
||||
method = calcMode;
|
||||
this.changedStateName = stateName;
|
||||
}
|
||||
|
||||
public AggregationMethod getAggregationMethod() {
|
||||
public FaceSelectionMethod getAggregationMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
private final AggregationMethod method;
|
||||
private final FaceSelectionMethod method;
|
||||
private final CardCharacteristicName changedStateName;
|
||||
|
||||
public static CardSplitType smartValueOf(String text) {
|
||||
@@ -24,8 +24,6 @@ import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.Constant;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Immutable Card type. Can be build only from parsing a string.
|
||||
@@ -36,20 +34,64 @@ import forge.Constant;
|
||||
*/
|
||||
|
||||
public final class CardType implements Comparable<CardType> {
|
||||
|
||||
public enum CoreType {
|
||||
|
||||
/** The Artifact. */
|
||||
Artifact,
|
||||
/** The Creature. */
|
||||
Creature,
|
||||
/** The Enchantment. */
|
||||
Enchantment,
|
||||
/** The Instant. */
|
||||
Instant,
|
||||
/** The Land. */
|
||||
Land,
|
||||
/** The Plane. */
|
||||
Plane,
|
||||
/** The Planeswalker. */
|
||||
Planeswalker,
|
||||
/** The Scheme. */
|
||||
Scheme,
|
||||
/** The Sorcery. */
|
||||
Sorcery,
|
||||
/** The Tribal. */
|
||||
Tribal,
|
||||
/** The Vanguard. */
|
||||
Vanguard,
|
||||
/** The Phenomenon. */
|
||||
Phenomenon
|
||||
}
|
||||
|
||||
public enum SuperType {
|
||||
|
||||
/** The Basic. */
|
||||
Basic,
|
||||
/** The Legendary. */
|
||||
Legendary,
|
||||
/** The Snow. */
|
||||
Snow,
|
||||
/** The Ongoing. */
|
||||
Ongoing,
|
||||
/** The World. */
|
||||
World
|
||||
}
|
||||
|
||||
|
||||
private final List<String> subType = new ArrayList<String>();
|
||||
private final EnumSet<CardCoreType> coreType = EnumSet.noneOf(CardCoreType.class);
|
||||
private final EnumSet<CardSuperType> superType = EnumSet.noneOf(CardSuperType.class);
|
||||
private final EnumSet<CardType.CoreType> coreType = EnumSet.noneOf(CardType.CoreType.class);
|
||||
private final EnumSet<CardType.SuperType> superType = EnumSet.noneOf(CardType.SuperType.class);
|
||||
private String calculatedType = null; // since obj is immutable, this is
|
||||
// calc'd once
|
||||
|
||||
// This will be useful for faster parses
|
||||
private static HashMap<String, CardCoreType> stringToCoreType = new HashMap<String, CardCoreType>();
|
||||
private static HashMap<String, CardSuperType> stringToSuperType = new HashMap<String, CardSuperType>();
|
||||
private static HashMap<String, CardType.CoreType> stringToCoreType = new HashMap<String, CardType.CoreType>();
|
||||
private static HashMap<String, CardType.SuperType> stringToSuperType = new HashMap<String, CardType.SuperType>();
|
||||
static {
|
||||
for (final CardSuperType st : CardSuperType.values()) {
|
||||
for (final CardType.SuperType st : CardType.SuperType.values()) {
|
||||
CardType.stringToSuperType.put(st.name(), st);
|
||||
}
|
||||
for (final CardCoreType ct : CardCoreType.values()) {
|
||||
for (final CardType.CoreType ct : CardType.CoreType.values()) {
|
||||
CardType.stringToCoreType.put(ct.name(), ct);
|
||||
}
|
||||
}
|
||||
@@ -106,13 +148,13 @@ public final class CardType implements Comparable<CardType> {
|
||||
return;
|
||||
}
|
||||
|
||||
final CardCoreType ct = CardType.stringToCoreType.get(type);
|
||||
final CardType.CoreType ct = CardType.stringToCoreType.get(type);
|
||||
if (ct != null) {
|
||||
this.coreType.add(ct);
|
||||
return;
|
||||
}
|
||||
|
||||
final CardSuperType st = CardType.stringToSuperType.get(type);
|
||||
final CardType.SuperType st = CardType.stringToSuperType.get(type);
|
||||
if (st != null) {
|
||||
this.superType.add(st);
|
||||
return;
|
||||
@@ -126,56 +168,56 @@ public final class CardType implements Comparable<CardType> {
|
||||
return this.subType.contains(operand);
|
||||
}
|
||||
|
||||
public boolean typeContains(final CardCoreType operand) {
|
||||
public boolean typeContains(final CardType.CoreType operand) {
|
||||
return this.coreType.contains(operand);
|
||||
}
|
||||
|
||||
public boolean superTypeContains(final CardSuperType operand) {
|
||||
public boolean superTypeContains(final CardType.SuperType operand) {
|
||||
return this.superType.contains(operand);
|
||||
}
|
||||
|
||||
public boolean isCreature() {
|
||||
return this.coreType.contains(CardCoreType.Creature);
|
||||
return this.coreType.contains(CardType.CoreType.Creature);
|
||||
}
|
||||
|
||||
public boolean isPlaneswalker() {
|
||||
return this.coreType.contains(CardCoreType.Planeswalker);
|
||||
return this.coreType.contains(CardType.CoreType.Planeswalker);
|
||||
}
|
||||
|
||||
public boolean isLand() {
|
||||
return this.coreType.contains(CardCoreType.Land);
|
||||
return this.coreType.contains(CardType.CoreType.Land);
|
||||
}
|
||||
|
||||
public boolean isArtifact() {
|
||||
return this.coreType.contains(CardCoreType.Artifact);
|
||||
return this.coreType.contains(CardType.CoreType.Artifact);
|
||||
}
|
||||
|
||||
public boolean isInstant() {
|
||||
return this.coreType.contains(CardCoreType.Instant);
|
||||
return this.coreType.contains(CardType.CoreType.Instant);
|
||||
}
|
||||
|
||||
public boolean isSorcery() {
|
||||
return this.coreType.contains(CardCoreType.Sorcery);
|
||||
return this.coreType.contains(CardType.CoreType.Sorcery);
|
||||
}
|
||||
|
||||
public boolean isVanguard() {
|
||||
return this.coreType.contains(CardCoreType.Vanguard);
|
||||
return this.coreType.contains(CardType.CoreType.Vanguard);
|
||||
}
|
||||
|
||||
public boolean isScheme() {
|
||||
return this.coreType.contains(CardCoreType.Scheme);
|
||||
return this.coreType.contains(CardType.CoreType.Scheme);
|
||||
}
|
||||
|
||||
public boolean isEnchantment() {
|
||||
return this.coreType.contains(CardCoreType.Enchantment);
|
||||
return this.coreType.contains(CardType.CoreType.Enchantment);
|
||||
}
|
||||
|
||||
public boolean isBasic() {
|
||||
return this.superType.contains(CardSuperType.Basic);
|
||||
return this.superType.contains(CardType.SuperType.Basic);
|
||||
}
|
||||
|
||||
public boolean isLegendary() {
|
||||
return this.superType.contains(CardSuperType.Legendary);
|
||||
return this.superType.contains(CardType.SuperType.Legendary);
|
||||
}
|
||||
|
||||
public boolean isBasicLand() {
|
||||
@@ -200,10 +242,10 @@ public final class CardType implements Comparable<CardType> {
|
||||
|
||||
public List<String> getTypesBeforeDash() {
|
||||
final ArrayList<String> types = new ArrayList<String>();
|
||||
for (final CardSuperType st : this.superType) {
|
||||
for (final CardType.SuperType st : this.superType) {
|
||||
types.add(st.name());
|
||||
}
|
||||
for (final CardCoreType ct : this.coreType) {
|
||||
for (final CardType.CoreType ct : this.coreType) {
|
||||
types.add(ct.name());
|
||||
}
|
||||
return types;
|
||||
@@ -229,13 +271,54 @@ public final class CardType implements Comparable<CardType> {
|
||||
}
|
||||
|
||||
public boolean isPlane() {
|
||||
return this.coreType.contains(CardCoreType.Plane);
|
||||
return this.coreType.contains(CardType.CoreType.Plane);
|
||||
}
|
||||
|
||||
public boolean isPhenomenon() {
|
||||
return this.coreType.contains(CardCoreType.Phenomenon);
|
||||
return this.coreType.contains(CardType.CoreType.Phenomenon);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The Interface CardTypes.
|
||||
*/
|
||||
public static class Constant {
|
||||
|
||||
/** The loaded. */
|
||||
public static final boolean[] LOADED = { false };
|
||||
|
||||
/** The card types. */
|
||||
public static final List<String> CARD_TYPES = new ArrayList<String>();
|
||||
|
||||
/** The super types. */
|
||||
public static final List<String> SUPER_TYPES = new ArrayList<String>();
|
||||
|
||||
/** The basic types. */
|
||||
public static final List<String> BASIC_TYPES = new ArrayList<String>();
|
||||
|
||||
/** The land types. */
|
||||
public static final List<String> LAND_TYPES = new ArrayList<String>();
|
||||
|
||||
/** The creature types. */
|
||||
public static final List<String> CREATURE_TYPES = new ArrayList<String>();
|
||||
|
||||
/** The instant types. */
|
||||
public static final List<String> INSTANT_TYPES = new ArrayList<String>();
|
||||
|
||||
/** The sorcery types. */
|
||||
public static final List<String> SORCERY_TYPES = new ArrayList<String>();
|
||||
|
||||
/** The enchantment types. */
|
||||
public static final List<String> ENCHANTMENT_TYPES = new ArrayList<String>();
|
||||
|
||||
/** The artifact types. */
|
||||
public static final List<String> ARTIFACT_TYPES = new ArrayList<String>();
|
||||
|
||||
/** The walker types. */
|
||||
public static final List<String> WALKER_TYPES = new ArrayList<String>();
|
||||
}
|
||||
|
||||
///////// Utility methods
|
||||
public static boolean isACardType(final String cardType) {
|
||||
return CardType.getAllCardTypes().contains(cardType);
|
||||
@@ -245,7 +328,7 @@ public final class CardType implements Comparable<CardType> {
|
||||
final ArrayList<String> types = new ArrayList<String>();
|
||||
|
||||
// types.addAll(getCardTypes());
|
||||
types.addAll(Constant.CardTypes.CARD_TYPES);
|
||||
types.addAll(Constant.CARD_TYPES);
|
||||
|
||||
// not currently used by Forge
|
||||
types.add("Plane");
|
||||
@@ -258,7 +341,7 @@ public final class CardType implements Comparable<CardType> {
|
||||
public static ArrayList<String> getBasicTypes() {
|
||||
final ArrayList<String> types = new ArrayList<String>();
|
||||
|
||||
types.addAll(Constant.CardTypes.BASIC_TYPES);
|
||||
types.addAll(Constant.BASIC_TYPES);
|
||||
|
||||
return types;
|
||||
}
|
||||
@@ -266,8 +349,8 @@ public final class CardType implements Comparable<CardType> {
|
||||
public static ArrayList<String> getLandTypes() {
|
||||
final ArrayList<String> types = new ArrayList<String>();
|
||||
|
||||
types.addAll(Constant.CardTypes.BASIC_TYPES);
|
||||
types.addAll(Constant.CardTypes.LAND_TYPES);
|
||||
types.addAll(Constant.BASIC_TYPES);
|
||||
types.addAll(Constant.LAND_TYPES);
|
||||
|
||||
return types;
|
||||
}
|
||||
@@ -275,13 +358,13 @@ public final class CardType implements Comparable<CardType> {
|
||||
public static ArrayList<String> getCreatureTypes() {
|
||||
final ArrayList<String> types = new ArrayList<String>();
|
||||
|
||||
types.addAll(Constant.CardTypes.CREATURE_TYPES);
|
||||
types.addAll(Constant.CREATURE_TYPES);
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
public static boolean isASuperType(final String cardType) {
|
||||
return (Constant.CardTypes.SUPER_TYPES.contains(cardType));
|
||||
return (Constant.SUPER_TYPES.contains(cardType));
|
||||
}
|
||||
|
||||
public static boolean isASubType(final String cardType) {
|
||||
@@ -289,18 +372,18 @@ public final class CardType implements Comparable<CardType> {
|
||||
}
|
||||
|
||||
public static boolean isACreatureType(final String cardType) {
|
||||
return (Constant.CardTypes.CREATURE_TYPES.contains(cardType));
|
||||
return (Constant.CREATURE_TYPES.contains(cardType));
|
||||
}
|
||||
|
||||
public static boolean isALandType(final String cardType) {
|
||||
return (Constant.CardTypes.LAND_TYPES.contains(cardType));
|
||||
return (Constant.LAND_TYPES.contains(cardType));
|
||||
}
|
||||
|
||||
public static boolean isAPlaneswalkerType(final String cardType) {
|
||||
return (Constant.CardTypes.WALKER_TYPES.contains(cardType));
|
||||
return (Constant.WALKER_TYPES.contains(cardType));
|
||||
}
|
||||
|
||||
public static boolean isABasicLandType(final String cardType) {
|
||||
return (Constant.CardTypes.BASIC_TYPES.contains(cardType));
|
||||
return (Constant.BASIC_TYPES.contains(cardType));
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
package forge.card;
|
||||
|
||||
import forge.Constant;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.util.BinaryUtil;
|
||||
|
||||
@@ -253,7 +252,7 @@ public final class ColorSet implements Comparable<ColorSet> {
|
||||
return "n/a";
|
||||
}
|
||||
String toReturn = MagicColor.toLongString(myColor);
|
||||
if (toReturn == Constant.Color.COLORLESS && myColor != 0) {
|
||||
if (toReturn == MagicColor.Constant.COLORLESS && myColor != 0) {
|
||||
return "multi";
|
||||
}
|
||||
return toReturn;
|
||||
@@ -8,7 +8,7 @@ import com.google.common.base.Predicate;
|
||||
|
||||
import forge.item.PaperCard;
|
||||
|
||||
public interface ICardDatabase {
|
||||
public interface ICardDatabase extends Iterable<PaperCard> {
|
||||
PaperCard tryGetCard(String cardName);
|
||||
PaperCard tryGetCard(String cardName, boolean fromLastSet);
|
||||
PaperCard tryGetCard(String cardName, String edition);
|
||||
111
forge-core/src/main/java/forge/card/MagicColor.java
Normal file
111
forge-core/src/main/java/forge/card/MagicColor.java
Normal file
@@ -0,0 +1,111 @@
|
||||
package forge.card;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* Holds byte values for each color magic has.
|
||||
*
|
||||
*/
|
||||
public class MagicColor {
|
||||
|
||||
public static final byte COLORLESS = 0;
|
||||
public static final byte WHITE = 1 << 1;
|
||||
public static final byte BLUE = 1 << 2;
|
||||
public static final byte BLACK = 1 << 3;
|
||||
public static final byte RED = 1 << 4;
|
||||
public static final byte GREEN = 1 << 5;
|
||||
|
||||
public static final byte ALL_COLORS = BLACK | BLUE | WHITE | RED | GREEN;
|
||||
public static final int NUMBER_OR_COLORS = 5;
|
||||
|
||||
public static final byte[] WUBRG = new byte[] { WHITE, BLUE, BLACK, RED, GREEN };
|
||||
|
||||
public static byte fromName(String s) {
|
||||
if( s == null ) return 0;
|
||||
if (s.equalsIgnoreCase(Constant.WHITE) || s.equalsIgnoreCase("w")) {
|
||||
return MagicColor.WHITE;
|
||||
}
|
||||
if (s.equalsIgnoreCase(Constant.BLUE) || s.equalsIgnoreCase("u")) {
|
||||
return MagicColor.BLUE;
|
||||
}
|
||||
if (s.equalsIgnoreCase(Constant.BLACK) || s.equalsIgnoreCase("b")) {
|
||||
return MagicColor.BLACK;
|
||||
}
|
||||
if (s.equalsIgnoreCase(Constant.RED) || s.equalsIgnoreCase("r")) {
|
||||
return MagicColor.RED;
|
||||
}
|
||||
if (s.equalsIgnoreCase(Constant.GREEN) || s.equalsIgnoreCase("g")) {
|
||||
return MagicColor.GREEN;
|
||||
}
|
||||
return 0; // colorless
|
||||
}
|
||||
|
||||
public static String toShortString(String color) {
|
||||
if (color.equalsIgnoreCase(Constant.SNOW)) return "S"; // compatibility
|
||||
return toShortString(fromName(color));
|
||||
}
|
||||
|
||||
public static String toLongString(String color) {
|
||||
if (color.equalsIgnoreCase("s")) return Constant.SNOW; // compatibility
|
||||
return toLongString(fromName(color));
|
||||
}
|
||||
|
||||
public static String toShortString(byte color) {
|
||||
switch(color){
|
||||
case GREEN: return "G";
|
||||
case RED: return "R";
|
||||
case BLUE: return "U";
|
||||
case BLACK: return "B";
|
||||
case WHITE: return "W";
|
||||
default: return "1";
|
||||
}
|
||||
}
|
||||
|
||||
public static String toLongString(byte color) {
|
||||
switch(color){
|
||||
case GREEN: return Constant.GREEN ;
|
||||
case RED: return Constant.RED;
|
||||
case BLUE: return Constant.BLUE;
|
||||
case BLACK: return Constant.BLACK;
|
||||
case WHITE: return Constant.WHITE;
|
||||
default: return Constant.COLORLESS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Interface Color.
|
||||
*/
|
||||
public static class Constant {
|
||||
|
||||
/** The Black. */
|
||||
public static final String BLACK = "black";
|
||||
|
||||
/** The Blue. */
|
||||
public static final String BLUE = "blue";
|
||||
|
||||
/** The Green. */
|
||||
public static final String GREEN = "green";
|
||||
|
||||
/** The Red. */
|
||||
public static final String RED = "red";
|
||||
|
||||
/** The White. */
|
||||
public static final String WHITE = "white";
|
||||
|
||||
/** The Colorless. */
|
||||
public static final String COLORLESS = "colorless";
|
||||
// color order "wubrg"
|
||||
|
||||
/** The only colors. */
|
||||
public static final ImmutableList<String> ONLY_COLORS = ImmutableList.of(WHITE, BLUE, BLACK, RED, GREEN);
|
||||
|
||||
/** The Snow. */
|
||||
public static final String SNOW = "snow";
|
||||
|
||||
/** The Basic lands. */
|
||||
public static final List<String> BASIC_LANDS = ImmutableList.of("Plains", "Island", "Swamp", "Mountain", "Forest");
|
||||
public static final List<String> SNOW_LANDS = ImmutableList.of("Snow-Covered Plains", "Snow-Covered Island", "Snow-Covered Swamp", "Snow-Covered Mountain", "Snow-Covered Forest");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package forge.item;
|
||||
package forge.card;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.ArrayList;
|
||||
@@ -7,7 +8,9 @@ import java.util.Collection;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.util.ItemPool;
|
||||
import forge.deck.CardPool;
|
||||
import forge.item.PaperCard;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.storage.StorageReaderFileSections;
|
||||
|
||||
@@ -30,7 +33,7 @@ public class PrintSheet {
|
||||
this(name0, null);
|
||||
}
|
||||
|
||||
private PrintSheet(String name0, ItemPool<PaperCard> pool) {
|
||||
public PrintSheet(String name0, ItemPool<PaperCard> pool) {
|
||||
name = name0;
|
||||
cardsWithWeights = pool != null ? pool : new ItemPool<PaperCard>(PaperCard.class);
|
||||
}
|
||||
@@ -105,18 +108,6 @@ public class PrintSheet {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static class Reader extends StorageReaderFileSections<PrintSheet> {
|
||||
public Reader(String fileName) {
|
||||
super(fileName, PrintSheet.FN_GET_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PrintSheet read(String title, Iterable<String> body, int idx) {
|
||||
return new PrintSheet(title, CardPool.fromCardList(body));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return cardsWithWeights.isEmpty();
|
||||
}
|
||||
@@ -125,5 +116,16 @@ public class PrintSheet {
|
||||
return cardsWithWeights.toFlatList();
|
||||
}
|
||||
|
||||
public static class Reader extends StorageReaderFileSections<PrintSheet> {
|
||||
public Reader(File file) {
|
||||
super(file, PrintSheet.FN_GET_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PrintSheet read(String title, Iterable<String> body, int idx) {
|
||||
return new PrintSheet(title, CardPool.fromCardList(body));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,13 +10,15 @@ import org.apache.commons.lang3.tuple.Pair;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.StaticData;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.ItemPoolView;
|
||||
import forge.item.PrintSheet;
|
||||
import forge.item.SealedProduct;
|
||||
import forge.util.ItemPoolView;
|
||||
|
||||
|
||||
public class UnOpenedProduct implements IUnOpenedProduct {
|
||||
|
||||
private final SealedProductTemplate tpl;
|
||||
private final SealedProduct.Template tpl;
|
||||
private final Map<String, PrintSheet> sheets;
|
||||
private boolean poolLimited = false; // if true after successful generation cards are removed from printsheets.
|
||||
|
||||
@@ -30,24 +32,24 @@ public class UnOpenedProduct implements IUnOpenedProduct {
|
||||
|
||||
|
||||
// Means to select from all unique cards (from base game, ie. no schemes or avatars)
|
||||
public UnOpenedProduct(SealedProductTemplate template) {
|
||||
public UnOpenedProduct(SealedProduct.Template template) {
|
||||
tpl = template;
|
||||
sheets = null;
|
||||
}
|
||||
|
||||
// Invoke this constructor only if you are sure that the pool is not equal to deafult carddb
|
||||
public UnOpenedProduct(SealedProductTemplate template, ItemPoolView<PaperCard> pool) {
|
||||
public UnOpenedProduct(SealedProduct.Template template, ItemPoolView<PaperCard> pool) {
|
||||
this(template, pool.toFlatList());
|
||||
}
|
||||
|
||||
public UnOpenedProduct(SealedProductTemplate template, Iterable<PaperCard> cards) {
|
||||
public UnOpenedProduct(SealedProduct.Template template, Iterable<PaperCard> cards) {
|
||||
tpl = template;
|
||||
sheets = new TreeMap<String, PrintSheet>();
|
||||
prebuildSheets(cards);
|
||||
}
|
||||
|
||||
public UnOpenedProduct(SealedProductTemplate sealedProductTemplate, Predicate<PaperCard> filterPrinted) {
|
||||
this(sealedProductTemplate, Iterables.filter(CardDb.instance().getAllCards(), filterPrinted));
|
||||
public UnOpenedProduct(SealedProduct.Template sealedProductTemplate, Predicate<PaperCard> filterPrinted) {
|
||||
this(sealedProductTemplate, Iterables.filter(StaticData.instance().getCommonCards().getAllCards(), filterPrinted));
|
||||
}
|
||||
|
||||
private void prebuildSheets(Iterable<PaperCard> sourceList) {
|
||||
@@ -49,7 +49,7 @@ public final class ManaCost implements Comparable<ManaCost> {
|
||||
public static final ManaCost FOUR = new ManaCost(4);
|
||||
|
||||
public static ManaCost get(int cntColorless) {
|
||||
switch (cntColorless) {
|
||||
switch (cntColorless) {
|
||||
case 0: return ZERO;
|
||||
case 1: return ONE;
|
||||
case 2: return TWO;
|
||||
@@ -58,14 +58,14 @@ public final class ManaCost implements Comparable<ManaCost> {
|
||||
}
|
||||
return cntColorless > 0 ? new ManaCost(cntColorless) : NO_COST;
|
||||
}
|
||||
|
||||
|
||||
// pass mana cost parser here
|
||||
private ManaCost(int cmc) {
|
||||
this.hasNoCost = cmc < 0;
|
||||
this.genericCost = cmc < 0 ? 0 : cmc;
|
||||
sealClass(new ArrayList<ManaCostShard>());
|
||||
}
|
||||
|
||||
|
||||
private void sealClass(List<ManaCostShard> shards0) {
|
||||
this.shards = Collections.unmodifiableList(shards0);
|
||||
this.stringValue = this.getSimpleString();
|
||||
@@ -97,22 +97,19 @@ public final class ManaCost implements Comparable<ManaCost> {
|
||||
return "no cost";
|
||||
}
|
||||
if (this.shards.isEmpty()) {
|
||||
return Integer.toString(this.genericCost);
|
||||
return "{" + this.genericCost + "}";
|
||||
}
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
boolean isFirst = true;
|
||||
if (this.genericCost > 0) {
|
||||
sb.append(this.genericCost);
|
||||
isFirst = false;
|
||||
sb.append("{" + this.genericCost + "}");
|
||||
}
|
||||
for (final ManaCostShard s : this.shards) {
|
||||
if (!isFirst) {
|
||||
sb.append(' ');
|
||||
if (s == ManaCostShard.X) {
|
||||
sb.insert(0, s.toString());
|
||||
} else {
|
||||
isFirst = false;
|
||||
sb.append(s.toString());
|
||||
}
|
||||
sb.append(s.toString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -196,7 +193,7 @@ public final class ManaCost implements Comparable<ManaCost> {
|
||||
public boolean isZero() {
|
||||
return genericCost == 0 && isPureGeneric();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -287,5 +284,4 @@ public final class ManaCost implements Comparable<ManaCost> {
|
||||
res.sealClass(sh);
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,6 +10,17 @@ public class ManaCostParser implements IParserManaCost {
|
||||
private final String[] cost;
|
||||
private int nextToken;
|
||||
private int colorlessCost;
|
||||
|
||||
/**
|
||||
* Parse the given cost and output formatted cost string
|
||||
*
|
||||
* @param cost
|
||||
*/
|
||||
public static String parse(final String cost) {
|
||||
final ManaCostParser parser = new ManaCostParser(cost);
|
||||
final ManaCost manaCost = new ManaCost(parser);
|
||||
return manaCost.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new parser cardname txt mana cost.
|
||||
@@ -54,7 +65,6 @@ public class ManaCostParser implements IParserManaCost {
|
||||
*/
|
||||
@Override
|
||||
public final ManaCostShard next() {
|
||||
|
||||
final String unparsed = this.cost[this.nextToken++];
|
||||
// System.out.println(unparsed);
|
||||
if (StringUtils.isNumeric(unparsed)) {
|
||||
@@ -23,7 +23,7 @@ import forge.util.BinaryUtil;
|
||||
* The Class CardManaCostShard.
|
||||
*/
|
||||
public enum ManaCostShard implements Comparable<ManaCostShard> {
|
||||
// declaration order matters! Place the shards that offer least ways to be paid for first
|
||||
// declaration order matters! Place the shards that offer least ways to be paid for first
|
||||
|
||||
/* Pure colors */
|
||||
WHITE(ManaAtom.WHITE, "W"),
|
||||
@@ -35,14 +35,14 @@ public enum ManaCostShard implements Comparable<ManaCostShard> {
|
||||
/* Hybrid */
|
||||
WU(ManaAtom.WHITE | ManaAtom.BLUE, "W/U", "WU"),
|
||||
WB(ManaAtom.WHITE | ManaAtom.BLACK, "W/B", "WB"),
|
||||
WR(ManaAtom.WHITE | ManaAtom.RED, "W/R", "RW"),
|
||||
WG(ManaAtom.WHITE | ManaAtom.GREEN, "W/G", "GW"),
|
||||
UB(ManaAtom.BLUE | ManaAtom.BLACK, "U/B", "UB"),
|
||||
UR(ManaAtom.BLUE | ManaAtom.RED, "U/R", "UR"),
|
||||
UG(ManaAtom.BLUE | ManaAtom.GREEN, "U/G", "GU"),
|
||||
BR(ManaAtom.BLACK | ManaAtom.RED, "B/R", "BR"),
|
||||
BG(ManaAtom.BLACK | ManaAtom.GREEN, "B/G", "BG"),
|
||||
RW(ManaAtom.RED | ManaAtom.WHITE, "R/W", "RW"),
|
||||
RG(ManaAtom.RED | ManaAtom.GREEN, "R/G", "RG"),
|
||||
GW(ManaAtom.GREEN | ManaAtom.WHITE, "G/W", "GW"),
|
||||
GU(ManaAtom.GREEN | ManaAtom.BLUE, "G/U", "GU"),
|
||||
|
||||
/* Or 2 colorless */
|
||||
W2(ManaAtom.WHITE | ManaAtom.OR_2_COLORLESS, "2/W", "2W"),
|
||||
@@ -55,7 +55,7 @@ public enum ManaCostShard implements Comparable<ManaCostShard> {
|
||||
S(ManaAtom.IS_SNOW, "S"),
|
||||
COLORLESS(ManaAtom.COLORLESS, "1"),
|
||||
|
||||
/* Phyrexian */
|
||||
/* Phyrexian */
|
||||
PW(ManaAtom.WHITE | ManaAtom.OR_2_LIFE, "W/P", "PW"),
|
||||
PU(ManaAtom.BLUE | ManaAtom.OR_2_LIFE, "U/P", "PU"),
|
||||
PB(ManaAtom.BLACK | ManaAtom.OR_2_LIFE, "B/P", "PB"),
|
||||
@@ -102,15 +102,12 @@ public enum ManaCostShard implements Comparable<ManaCostShard> {
|
||||
this.shard = value;
|
||||
this.cmc = this.getCMC();
|
||||
this.cmpc = this.getCmpCost();
|
||||
this.stringValue = sValue;
|
||||
this.stringValue = "{" + sValue + "}";
|
||||
this.imageKey = imgKey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static final int COLORS_SUPERPOSITION = ManaAtom.WHITE | ManaAtom.BLUE | ManaAtom.BLACK | ManaAtom.RED | ManaAtom.GREEN;
|
||||
|
||||
|
||||
private int getCMC() {
|
||||
if (0 != (this.shard & ManaAtom.IS_X)) {
|
||||
return 0;
|
||||
@@ -18,7 +18,6 @@
|
||||
package forge.deck;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -26,10 +25,9 @@ import java.util.NoSuchElementException;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.CardDb;
|
||||
import forge.StaticData;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.ItemPool;
|
||||
import forge.util.ItemPool;
|
||||
|
||||
/**
|
||||
* Deck section.
|
||||
@@ -54,15 +52,6 @@ public class CardPool extends ItemPool<PaperCard> {
|
||||
this.addAll(cards);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the.
|
||||
*
|
||||
* @param card
|
||||
* the card
|
||||
*/
|
||||
public void add(final Card card) {
|
||||
this.add(CardDb.getCard(card));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the.
|
||||
@@ -84,9 +73,9 @@ public class CardPool extends ItemPool<PaperCard> {
|
||||
* @param amount the amount
|
||||
*/
|
||||
public void add(final String cardName, final String setCode, final int amount) {
|
||||
PaperCard cp = CardDb.instance().tryGetCard(cardName, setCode);
|
||||
PaperCard cp = StaticData.instance().getCommonCards().tryGetCard(cardName, setCode);
|
||||
if ( cp == null )
|
||||
cp = CardDb.variants().tryGetCard(cardName, setCode);
|
||||
cp = StaticData.instance().getVariantCards().tryGetCard(cardName, setCode);
|
||||
|
||||
if ( cp != null)
|
||||
this.add(cp, amount);
|
||||
@@ -94,18 +83,6 @@ public class CardPool extends ItemPool<PaperCard> {
|
||||
throw new RuntimeException(String.format("Card %s from %s is not supported by Forge, as it's neither a known common card nor one of casual variants' card.", cardName, setCode ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the.
|
||||
*
|
||||
* @param cardList
|
||||
* the card list
|
||||
*/
|
||||
public void add(final List<Card> cardList) {
|
||||
for (final Card c : cardList) {
|
||||
this.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all from a List of CardPrinted.
|
||||
*
|
||||
@@ -124,9 +101,9 @@ public class CardPool extends ItemPool<PaperCard> {
|
||||
* @param cardName the card name
|
||||
*/
|
||||
public void add(final String cardName, int cnt) {
|
||||
PaperCard cp = CardDb.instance().tryGetCard(cardName);
|
||||
PaperCard cp = StaticData.instance().getCommonCards().tryGetCard(cardName);
|
||||
if ( cp == null )
|
||||
cp = CardDb.variants().tryGetCard(cardName);
|
||||
cp = StaticData.instance().getVariantCards().tryGetCard(cardName);
|
||||
|
||||
if ( cp != null)
|
||||
this.add(cp, cnt);
|
||||
@@ -35,12 +35,12 @@ import com.google.common.base.Function;
|
||||
import forge.card.CardDb;
|
||||
import forge.deck.io.DeckFileHeader;
|
||||
import forge.deck.io.DeckSerializer;
|
||||
import forge.item.ItemPoolSorter;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.item.ItemPoolView;
|
||||
import forge.util.FileSection;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.ItemPoolSorter;
|
||||
import forge.util.ItemPoolView;
|
||||
|
||||
|
||||
/**
|
||||
@@ -52,8 +52,8 @@ public abstract class DeckBase implements Serializable, Comparable<DeckBase>, IH
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (o instanceof Deck) {
|
||||
final Deck d = (Deck) o;
|
||||
if (o instanceof DeckBase) {
|
||||
final DeckBase d = (DeckBase) o;
|
||||
return this.getName().equals(d.getName());
|
||||
}
|
||||
return false;
|
||||
@@ -22,43 +22,37 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang.math.IntRange;
|
||||
|
||||
import forge.Singletons;
|
||||
import forge.card.CardCoreType;
|
||||
import forge.card.CardDb;
|
||||
import org.apache.commons.lang3.Range;
|
||||
|
||||
import forge.StaticData;
|
||||
import forge.card.CardType;
|
||||
import forge.card.ColorSet;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.util.Aggregates;
|
||||
|
||||
/**
|
||||
* GameType is an enum to determine the type of current game. :)
|
||||
*/
|
||||
public enum DeckFormat {
|
||||
|
||||
|
||||
// Main board: allowed size SB: restriction Max distinct non basic cards
|
||||
Constructed ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0, 15), 4),
|
||||
QuestDeck ( new IntRange(40, Integer.MAX_VALUE), new IntRange(0, 15), 4),
|
||||
Limited ( new IntRange(40, Integer.MAX_VALUE), null, Integer.MAX_VALUE),
|
||||
Commander ( new IntRange(99), new IntRange(0, 10), 1),
|
||||
Vanguard ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4),
|
||||
Planechase ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4),
|
||||
Archenemy ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4);
|
||||
Constructed ( Range.between(60, Integer.MAX_VALUE), Range.between(0, 15), 4),
|
||||
QuestDeck ( Range.between(40, Integer.MAX_VALUE), Range.between(0, 15), 4),
|
||||
Limited ( Range.between(40, Integer.MAX_VALUE), null, Integer.MAX_VALUE),
|
||||
Commander ( Range.is(99), Range.between(0, 10), 1),
|
||||
Vanguard ( Range.between(60, Integer.MAX_VALUE), Range.is(0), 4),
|
||||
Planechase ( Range.between(60, Integer.MAX_VALUE), Range.is(0), 4),
|
||||
Archenemy ( Range.between(60, Integer.MAX_VALUE), Range.is(0), 4);
|
||||
|
||||
private final IntRange mainRange;
|
||||
private final IntRange sideRange; // null => no check
|
||||
private final Range<Integer> mainRange;
|
||||
private final Range<Integer> sideRange; // null => no check
|
||||
private final int maxCardCopies;
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates a new game type.
|
||||
*
|
||||
* @param isLimited
|
||||
* the is limited
|
||||
*/
|
||||
DeckFormat(IntRange main, IntRange side, int maxCopies) {
|
||||
|
||||
DeckFormat(Range<Integer> main, Range<Integer> side, int maxCopies) {
|
||||
mainRange = main;
|
||||
sideRange = side;
|
||||
maxCardCopies = maxCopies;
|
||||
@@ -90,7 +84,7 @@ public enum DeckFormat {
|
||||
/**
|
||||
* @return the sideRange
|
||||
*/
|
||||
public IntRange getSideRange() {
|
||||
public Range<Integer> getSideRange() {
|
||||
return sideRange;
|
||||
}
|
||||
|
||||
@@ -98,7 +92,7 @@ public enum DeckFormat {
|
||||
/**
|
||||
* @return the mainRange
|
||||
*/
|
||||
public IntRange getMainRange() {
|
||||
public Range<Integer> getMainRange() {
|
||||
return mainRange;
|
||||
}
|
||||
|
||||
@@ -118,15 +112,10 @@ public enum DeckFormat {
|
||||
return "is not selected";
|
||||
}
|
||||
|
||||
// That's really a bad dependence
|
||||
if (!Singletons.getModel().getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int deckSize = deck.getMain().countAll();
|
||||
|
||||
int min = getMainRange().getMinimumInteger();
|
||||
int max = getMainRange().getMaximumInteger();
|
||||
int min = getMainRange().getMinimum();
|
||||
int max = getMainRange().getMaximum();
|
||||
|
||||
if (deckSize < min) {
|
||||
return String.format("should have a minimum of %d cards", min);
|
||||
@@ -189,7 +178,7 @@ public enum DeckFormat {
|
||||
int phenoms = 0;
|
||||
for (Entry<PaperCard, Integer> cp : planes) {
|
||||
|
||||
if (cp.getKey().getRules().getType().typeContains(CardCoreType.Phenomenon)) {
|
||||
if (cp.getKey().getRules().getType().typeContains(CardType.CoreType.Phenomenon)) {
|
||||
phenoms++;
|
||||
}
|
||||
if (cp.getValue() > 1) {
|
||||
@@ -233,7 +222,7 @@ public enum DeckFormat {
|
||||
// should group all cards by name, so that different editions of same card are really counted as the same card
|
||||
for (Entry<String, Integer> cp : Aggregates.groupSumBy(tmp, PaperCard.FN_GET_NAME)) {
|
||||
|
||||
IPaperCard simpleCard = CardDb.instance().getCard(cp.getKey());
|
||||
IPaperCard simpleCard = StaticData.instance().getCommonCards().getCard(cp.getKey());
|
||||
boolean canHaveMultiple = simpleCard.getRules().getType().isBasicLand() || limitExceptions.contains(cp.getKey());
|
||||
|
||||
if (!canHaveMultiple && cp.getValue() > maxCopies) {
|
||||
@@ -244,11 +233,11 @@ public enum DeckFormat {
|
||||
|
||||
// The sideboard must contain either 0 or 15 cards
|
||||
int sideboardSize = deck.has(DeckSection.Sideboard) ? deck.get(DeckSection.Sideboard).countAll() : 0;
|
||||
IntRange sbRange = getSideRange();
|
||||
if (sbRange != null && sideboardSize > 0 && !sbRange.containsInteger(sideboardSize)) {
|
||||
return sbRange.getMinimumInteger() == sbRange.getMaximumInteger()
|
||||
? String.format("must have a sideboard of %d cards or no sideboard at all", sbRange.getMaximumInteger())
|
||||
: String.format("must have a sideboard of %d to %d cards or no sideboard at all", sbRange.getMinimumInteger(), sbRange.getMaximumInteger());
|
||||
Range<Integer> sbRange = getSideRange();
|
||||
if (sbRange != null && sideboardSize > 0 && !sbRange.contains(sideboardSize)) {
|
||||
return sbRange.getMinimum() == sbRange.getMaximum()
|
||||
? String.format("must have a sideboard of %d cards or no sideboard at all", sbRange.getMaximum())
|
||||
: String.format("must have a sideboard of %d to %d cards or no sideboard at all", sbRange.getMinimum(), sbRange.getMaximum());
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -167,9 +167,9 @@ public class DeckRecognizer {
|
||||
private final ICardDatabase db;
|
||||
private Date recognizeCardsPrintedBefore = null;
|
||||
|
||||
public DeckRecognizer(boolean fromLatestSet) {
|
||||
public DeckRecognizer(boolean fromLatestSet, CardDb db) {
|
||||
useLastSet = fromLatestSet;
|
||||
db = CardDb.instance();
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
public Token recognizeLine(final String rawLine) {
|
||||
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.deck.generate;
|
||||
package forge.deck.generation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -24,10 +24,10 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.ColorSet;
|
||||
import forge.card.ICardDatabase;
|
||||
import forge.card.MagicColor;
|
||||
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.ItemPoolView;
|
||||
import forge.util.ItemPoolView;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -37,17 +37,17 @@ import forge.item.ItemPoolView;
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public class Generate2ColorDeck extends GenerateColoredDeckBase {
|
||||
public class DeckGenerator2Color extends DeckGeneratorBase {
|
||||
@Override protected final float getLandsPercentage() { return 0.39f; }
|
||||
@Override protected final float getCreatPercentage() { return 0.36f; }
|
||||
@Override protected final float getSpellPercentage() { return 0.25f; }
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<ImmutablePair<FilterCMC, Integer>> cmcRelativeWeights = Lists.newArrayList(
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(0, 2), 6),
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(3, 4), 4),
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(5, 6), 2),
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(7, 20), 1)
|
||||
ImmutablePair.of(new FilterCMC(0, 2), 6),
|
||||
ImmutablePair.of(new FilterCMC(3, 4), 4),
|
||||
ImmutablePair.of(new FilterCMC(5, 6), 2),
|
||||
ImmutablePair.of(new FilterCMC(7, 20), 1)
|
||||
);
|
||||
|
||||
// mana curve of the card pool
|
||||
@@ -67,7 +67,8 @@ public class Generate2ColorDeck extends GenerateColoredDeckBase {
|
||||
* @param clr2
|
||||
* a {@link java.lang.String} object.
|
||||
*/
|
||||
public Generate2ColorDeck(final String clr1, final String clr2) {
|
||||
public DeckGenerator2Color(ICardDatabase cardDb, final String clr1, final String clr2) {
|
||||
super(cardDb);
|
||||
int c1 = MagicColor.fromName(clr1);
|
||||
int c2 = MagicColor.fromName(clr2);
|
||||
|
||||
@@ -96,7 +97,7 @@ public class Generate2ColorDeck extends GenerateColoredDeckBase {
|
||||
tmpDeck.append(String.format("Adjusted deck size to: %d, should add %d land(s)%n", size - numLands, numLands));
|
||||
|
||||
// Add dual lands
|
||||
List<String> duals = GenerateDeckUtil.getDualLandList(colors);
|
||||
List<String> duals = getDualLandList();
|
||||
for (String s : duals) {
|
||||
this.cardCounts.put(s, 0);
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.deck.generate;
|
||||
package forge.deck.generation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -24,10 +24,10 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.ColorSet;
|
||||
import forge.card.ICardDatabase;
|
||||
import forge.card.MagicColor;
|
||||
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.ItemPoolView;
|
||||
import forge.util.ItemPoolView;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
/**
|
||||
@@ -38,12 +38,12 @@ import forge.util.MyRandom;
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public class Generate3ColorDeck extends GenerateColoredDeckBase {
|
||||
public class DeckGenerator3Color extends DeckGeneratorBase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(0, 2), 12),
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(3, 5), 9),
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(6, 20), 3)
|
||||
ImmutablePair.of(new FilterCMC(0, 2), 12),
|
||||
ImmutablePair.of(new FilterCMC(3, 5), 9),
|
||||
ImmutablePair.of(new FilterCMC(6, 20), 3)
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -58,7 +58,8 @@ public class Generate3ColorDeck extends GenerateColoredDeckBase {
|
||||
* @param clr3
|
||||
* a {@link java.lang.String} object.
|
||||
*/
|
||||
public Generate3ColorDeck(final String clr1, final String clr2, final String clr3) {
|
||||
public DeckGenerator3Color(ICardDatabase cardDb, final String clr1, final String clr2, final String clr3) {
|
||||
super(cardDb);
|
||||
int c1 = MagicColor.fromName(clr1);
|
||||
int c2 = MagicColor.fromName(clr2);
|
||||
int c3 = MagicColor.fromName(clr3);
|
||||
@@ -105,7 +106,7 @@ public class Generate3ColorDeck extends GenerateColoredDeckBase {
|
||||
tmpDeck.append("numLands:").append(numLands).append("\n");
|
||||
|
||||
// Add dual lands
|
||||
List<String> duals = GenerateDeckUtil.getDualLandList(colors);
|
||||
List<String> duals = getDualLandList();
|
||||
for (String s : duals) {
|
||||
this.cardCounts.put(s, 0);
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.deck.generate;
|
||||
package forge.deck.generation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -24,9 +24,9 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.ColorSet;
|
||||
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
||||
import forge.card.ICardDatabase;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.ItemPoolView;
|
||||
import forge.util.ItemPoolView;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -36,12 +36,12 @@ import forge.item.ItemPoolView;
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public class Generate5ColorDeck extends GenerateColoredDeckBase {
|
||||
public class DeckGenerator5Color extends DeckGeneratorBase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(0, 2), 3),
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(3, 5), 2),
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(6, 20), 1)
|
||||
ImmutablePair.of(new FilterCMC(0, 2), 3),
|
||||
ImmutablePair.of(new FilterCMC(3, 5), 2),
|
||||
ImmutablePair.of(new FilterCMC(6, 20), 1)
|
||||
);
|
||||
|
||||
// resulting mana curve of the card pool
|
||||
@@ -53,7 +53,8 @@ public class Generate5ColorDeck extends GenerateColoredDeckBase {
|
||||
/**
|
||||
* Instantiates a new generate5 color deck.
|
||||
*/
|
||||
public Generate5ColorDeck() {
|
||||
public DeckGenerator5Color(ICardDatabase cardDb) {
|
||||
super(cardDb);
|
||||
colors = ColorSet.fromMask(0).inverse();
|
||||
}
|
||||
|
||||
@@ -68,7 +69,7 @@ public class Generate5ColorDeck extends GenerateColoredDeckBase {
|
||||
tmpDeck.append("numLands:").append(numLands).append("\n");
|
||||
|
||||
// Add dual lands
|
||||
List<String> duals = GenerateDeckUtil.getDualLandList(colors);
|
||||
List<String> duals = getDualLandList();
|
||||
for (String s : duals) {
|
||||
this.cardCounts.put(s, 0);
|
||||
}
|
||||
@@ -15,8 +15,9 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.deck.generate;
|
||||
package forge.deck.generation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -31,19 +32,16 @@ import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.Constant;
|
||||
import forge.Singletons;
|
||||
import forge.card.CardDb;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.CardRulesPredicates;
|
||||
import forge.card.ColorSet;
|
||||
import forge.card.ICardDatabase;
|
||||
import forge.card.MagicColor;
|
||||
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.ItemPool;
|
||||
import forge.item.ItemPoolView;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.ItemPool;
|
||||
import forge.util.ItemPoolView;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
/**
|
||||
@@ -54,13 +52,15 @@ import forge.util.MyRandom;
|
||||
* @author Forge
|
||||
* @version $Id: Generate2ColorDeck.java 14959 2012-03-28 14:03:43Z Chris H. $
|
||||
*/
|
||||
public abstract class GenerateColoredDeckBase {
|
||||
public abstract class DeckGeneratorBase {
|
||||
protected final Random r = MyRandom.getRandom();
|
||||
protected final Map<String, Integer> cardCounts = new HashMap<String, Integer>();
|
||||
protected int maxDuplicates;
|
||||
protected int maxDuplicates = 4;
|
||||
protected boolean useArtifacts = true;
|
||||
|
||||
protected ColorSet colors;
|
||||
protected final ItemPool<PaperCard> tDeck;
|
||||
protected final ItemPool<PaperCard> tDeck = new ItemPool<PaperCard>(PaperCard.class);
|
||||
protected final ICardDatabase cardDb;
|
||||
|
||||
// 2-colored deck generator has its own constants. The rest works fine with these ones
|
||||
protected float getLandsPercentage() { return 0.44f; }
|
||||
@@ -69,9 +69,15 @@ public abstract class GenerateColoredDeckBase {
|
||||
|
||||
StringBuilder tmpDeck = new StringBuilder();
|
||||
|
||||
public GenerateColoredDeckBase() {
|
||||
this.maxDuplicates = Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_SINGLETONS) ? 1 : 4;
|
||||
tDeck = new ItemPool<PaperCard>(PaperCard.class);
|
||||
public DeckGeneratorBase(ICardDatabase cardDb) {
|
||||
this.cardDb = cardDb;
|
||||
}
|
||||
|
||||
public void setSingleton(boolean singleton){
|
||||
this.maxDuplicates = singleton ? 1 : 4;
|
||||
}
|
||||
public void setUseArtifacts(boolean value) {
|
||||
this.useArtifacts = value;
|
||||
}
|
||||
|
||||
protected void addCreaturesAndSpells(int size, List<ImmutablePair<FilterCMC, Integer>> cmcLevels, boolean forAi) {
|
||||
@@ -132,8 +138,7 @@ public abstract class GenerateColoredDeckBase {
|
||||
} while ((this.cardCounts.get(s) > 3) && (lc <= 20));
|
||||
// not an error if looped too much - could play singleton mode, with 6 slots for 3 non-basic lands.
|
||||
|
||||
PaperCard cp = CardDb.instance().getCard(s);
|
||||
tDeck.add(CardDb.instance().getCard(cp.getName(), false));
|
||||
tDeck.add(cardDb.getCard(s, false));
|
||||
|
||||
final int n = this.cardCounts.get(s);
|
||||
this.cardCounts.put(s, n + 1);
|
||||
@@ -159,20 +164,20 @@ public abstract class GenerateColoredDeckBase {
|
||||
|
||||
int landsLeft = cnt;
|
||||
for (Entry<String, Integer> c : clrCnts.entrySet()) {
|
||||
String color = c.getKey();
|
||||
String basicLandName = c.getKey();
|
||||
|
||||
|
||||
// calculate number of lands for each color
|
||||
final int nLand = Math.min(landsLeft, Math.round(cnt * c.getValue() / totalColor));
|
||||
tmpDeck.append("nLand-").append(color).append(":").append(nLand).append("\n");
|
||||
tmpDeck.append("nLand-").append(basicLandName).append(":").append(nLand).append("\n");
|
||||
|
||||
// just to prevent a null exception by the deck size fixing code
|
||||
this.cardCounts.put(color, nLand);
|
||||
this.cardCounts.put(basicLandName, nLand);
|
||||
|
||||
PaperCard cp = CardDb.instance().getCard(color);
|
||||
PaperCard cp = cardDb.getCard(basicLandName);
|
||||
String basicLandSet = cp.getEdition();
|
||||
|
||||
tDeck.add(CardDb.instance().getCard(cp.getName(), basicLandSet), nLand);
|
||||
tDeck.add(cardDb.getCard(cp.getName(), basicLandSet), nLand);
|
||||
landsLeft -= nLand;
|
||||
}
|
||||
}
|
||||
@@ -222,7 +227,7 @@ public abstract class GenerateColoredDeckBase {
|
||||
final List<PaperCard> curvedRandomized = Lists.newArrayList();
|
||||
for (PaperCard c : curved) {
|
||||
this.cardCounts.put(c.getName(), 0);
|
||||
curvedRandomized.add(CardDb.instance().getCard(c.getName(), false));
|
||||
curvedRandomized.add(cardDb.getCard(c.getName(), false));
|
||||
}
|
||||
|
||||
addSome(addOfThisCmc, curvedRandomized);
|
||||
@@ -233,13 +238,13 @@ public abstract class GenerateColoredDeckBase {
|
||||
|
||||
// start with all cards
|
||||
// remove cards that generated decks don't like
|
||||
Predicate<CardRules> canPlay = forAi ? GenerateDeckUtil.AI_CAN_PLAY : GenerateDeckUtil.HUMAN_CAN_PLAY;
|
||||
Predicate<CardRules> hasColor = new GenerateDeckUtil.MatchColorIdentity(colors);
|
||||
Predicate<CardRules> canPlay = forAi ? AI_CAN_PLAY : HUMAN_CAN_PLAY;
|
||||
Predicate<CardRules> hasColor = new MatchColorIdentity(colors);
|
||||
|
||||
if (!Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS)) {
|
||||
hasColor = Predicates.or(hasColor, GenerateDeckUtil.COLORLESS_CARDS);
|
||||
if (useArtifacts) {
|
||||
hasColor = Predicates.or(hasColor, COLORLESS_CARDS);
|
||||
}
|
||||
return Iterables.filter(CardDb.instance().getAllCards(), Predicates.compose(Predicates.and(canPlay, hasColor), PaperCard.FN_GET_RULES));
|
||||
return Iterables.filter(cardDb.getAllCards(), Predicates.compose(Predicates.and(canPlay, hasColor), PaperCard.FN_GET_RULES));
|
||||
}
|
||||
|
||||
protected static Map<String, Integer> countLands(ItemPool<PaperCard> outList) {
|
||||
@@ -254,15 +259,15 @@ public abstract class GenerateColoredDeckBase {
|
||||
int profile = cpe.getKey().getRules().getManaCost().getColorProfile();
|
||||
|
||||
if ((profile & MagicColor.WHITE) != 0) {
|
||||
increment(res, Constant.Color.BASIC_LANDS.get(0), cpe.getValue());
|
||||
increment(res, MagicColor.Constant.BASIC_LANDS.get(0), cpe.getValue());
|
||||
} else if ((profile & MagicColor.BLUE) != 0) {
|
||||
increment(res, Constant.Color.BASIC_LANDS.get(1), cpe.getValue());
|
||||
increment(res, MagicColor.Constant.BASIC_LANDS.get(1), cpe.getValue());
|
||||
} else if ((profile & MagicColor.BLACK) != 0) {
|
||||
increment(res, Constant.Color.BASIC_LANDS.get(2), cpe.getValue());
|
||||
increment(res, MagicColor.Constant.BASIC_LANDS.get(2), cpe.getValue());
|
||||
} else if ((profile & MagicColor.RED) != 0) {
|
||||
increment(res, Constant.Color.BASIC_LANDS.get(3), cpe.getValue());
|
||||
increment(res, MagicColor.Constant.BASIC_LANDS.get(3), cpe.getValue());
|
||||
} else if ((profile & MagicColor.GREEN) != 0) {
|
||||
increment(res, Constant.Color.BASIC_LANDS.get(4), cpe.getValue());
|
||||
increment(res, MagicColor.Constant.BASIC_LANDS.get(4), cpe.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -274,4 +279,127 @@ public abstract class GenerateColoredDeckBase {
|
||||
final Integer boxed = map.get(key);
|
||||
map.put(key, boxed == null ? delta : boxed.intValue() + delta);
|
||||
}
|
||||
|
||||
public static final Predicate<CardRules> AI_CAN_PLAY = new Predicate<CardRules>() {
|
||||
@Override
|
||||
public boolean apply(CardRules c) {
|
||||
return !c.getAiHints().getRemAIDecks() && !c.getAiHints().getRemRandomDecks();
|
||||
}
|
||||
};
|
||||
|
||||
public static final Predicate<CardRules> HUMAN_CAN_PLAY = new Predicate<CardRules>() {
|
||||
@Override
|
||||
public boolean apply(CardRules c) {
|
||||
return !c.getAiHints().getRemRandomDecks();
|
||||
}
|
||||
};
|
||||
|
||||
public static final Predicate<CardRules> COLORLESS_CARDS = new Predicate<CardRules>() {
|
||||
@Override
|
||||
public boolean apply(CardRules c) {
|
||||
ManaCost mc = c.getManaCost();
|
||||
return c.getColorIdentity().isColorless() && !mc.isNoCost();
|
||||
}
|
||||
};
|
||||
|
||||
public static class MatchColorIdentity implements Predicate<CardRules> {
|
||||
private final ColorSet allowedColor;
|
||||
|
||||
public MatchColorIdentity(ColorSet color) {
|
||||
allowedColor = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(CardRules subject) {
|
||||
ManaCost mc = subject.getManaCost();
|
||||
return !mc.isPureGeneric() && allowedColor.containsAllColorsFrom(subject.getColorIdentity().getColor());
|
||||
//return mc.canBePaidWithAvaliable(allowedColor);
|
||||
// return allowedColor.containsAllColorsFrom(mc.getColorProfile());
|
||||
}
|
||||
}
|
||||
|
||||
public static class FilterCMC implements Predicate<CardRules> {
|
||||
private final int min;
|
||||
private final int max;
|
||||
|
||||
public FilterCMC(int from, int to) {
|
||||
min = from;
|
||||
max = to;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(CardRules c) {
|
||||
ManaCost mc = c.getManaCost();
|
||||
int cmc = mc.getCMC();
|
||||
return cmc >= min && cmc <= max && !mc.isNoCost();
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<Integer, String[]> dualLands = new HashMap<Integer, String[]>();
|
||||
static {
|
||||
dualLands.put(MagicColor.WHITE | MagicColor.BLUE, new String[] { "Tundra", "Hallowed Fountain", "Flooded Strand" });
|
||||
dualLands.put(MagicColor.BLACK | MagicColor.BLUE, new String[] { "Underground Sea", "Watery Grave", "Polluted Delta" });
|
||||
dualLands.put(MagicColor.BLACK | MagicColor.RED, new String[] { "Badlands", "Blood Crypt", "Bloodstained Mire" });
|
||||
dualLands.put(MagicColor.GREEN | MagicColor.RED, new String[] { "Taiga", "Stomping Ground", "Wooded Foothills" });
|
||||
dualLands.put(MagicColor.GREEN | MagicColor.WHITE, new String[] { "Savannah", "Temple Garden", "Windswept Heath" });
|
||||
|
||||
dualLands.put(MagicColor.WHITE | MagicColor.BLACK, new String[] { "Scrubland", "Godless Shrine", "Marsh Flats" });
|
||||
dualLands.put(MagicColor.BLUE | MagicColor.RED, new String[] { "Volcanic Island", "Steam Vents", "Scalding Tarn" });
|
||||
dualLands.put(MagicColor.BLACK | MagicColor.GREEN, new String[] { "Bayou", "Overgrown Tomb", "Verdant Catacombs" });
|
||||
dualLands.put(MagicColor.WHITE | MagicColor.RED, new String[] { "Plateau", "Sacred Foundry", "Arid Mesa" });
|
||||
dualLands.put(MagicColor.GREEN | MagicColor.BLUE, new String[] { "Tropical Island", "Breeding Pool", "Misty Rainforest" });
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of dual lands for this color combo.
|
||||
*
|
||||
* @param color
|
||||
* the color
|
||||
* @return dual land names
|
||||
*/
|
||||
protected List<String> getDualLandList() {
|
||||
|
||||
final List<String> dLands = new ArrayList<String>();
|
||||
|
||||
if (colors.countColors() > 3) {
|
||||
dLands.add("Rupture Spire");
|
||||
dLands.add("Undiscovered Paradise");
|
||||
}
|
||||
|
||||
if (colors.countColors() > 2) {
|
||||
dLands.add("Evolving Wilds");
|
||||
dLands.add("Terramorphic Expanse");
|
||||
}
|
||||
for (Entry<Integer, String[]> dual : dualLands.entrySet()) {
|
||||
if (colors.hasAllColors(dual.getKey())) {
|
||||
for (String s : dual.getValue()) {
|
||||
dLands.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dLands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all dual lands that do not match this color combo.
|
||||
*
|
||||
* @param color
|
||||
* the color
|
||||
* @return dual land names
|
||||
*/
|
||||
protected List<String> getInverseDualLandList() {
|
||||
|
||||
final List<String> dLands = new ArrayList<String>();
|
||||
|
||||
for (Entry<Integer, String[]> dual : dualLands.entrySet()) {
|
||||
if (!colors.hasAllColors(dual.getKey())) {
|
||||
for (String s : dual.getValue()) {
|
||||
dLands.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dLands;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.deck.generate;
|
||||
package forge.deck.generation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -24,10 +24,10 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.ColorSet;
|
||||
import forge.card.ICardDatabase;
|
||||
import forge.card.MagicColor;
|
||||
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.ItemPoolView;
|
||||
import forge.util.ItemPoolView;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -37,17 +37,17 @@ import forge.item.ItemPoolView;
|
||||
* @author Forge
|
||||
* @version $Id: Generate2ColorDeck.java 19765 2013-02-20 03:01:37Z myk $
|
||||
*/
|
||||
public class GenerateMonoColorDeck extends GenerateColoredDeckBase {
|
||||
public class DeckGeneratorMonoColor extends DeckGeneratorBase {
|
||||
@Override protected final float getLandsPercentage() { return 0.39f; }
|
||||
@Override protected final float getCreatPercentage() { return 0.36f; }
|
||||
@Override protected final float getSpellPercentage() { return 0.25f; }
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(0, 2), 10),
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(3, 4), 8),
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(5, 6), 5),
|
||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(7, 20), 3)
|
||||
ImmutablePair.of(new FilterCMC(0, 2), 10),
|
||||
ImmutablePair.of(new FilterCMC(3, 4), 8),
|
||||
ImmutablePair.of(new FilterCMC(5, 6), 5),
|
||||
ImmutablePair.of(new FilterCMC(7, 20), 3)
|
||||
);
|
||||
|
||||
// mana curve of the card pool
|
||||
@@ -67,7 +67,8 @@ public class GenerateMonoColorDeck extends GenerateColoredDeckBase {
|
||||
* @param clr2
|
||||
* a {@link java.lang.String} object.
|
||||
*/
|
||||
public GenerateMonoColorDeck(final String clr1) {
|
||||
public DeckGeneratorMonoColor(ICardDatabase cardDb, final String clr1) {
|
||||
super(cardDb);
|
||||
if (MagicColor.fromName(clr1) == 0) {
|
||||
int color1 = r.nextInt(5);
|
||||
colors = ColorSet.fromMask(MagicColor.WHITE << color1);
|
||||
@@ -0,0 +1,3 @@
|
||||
/** Forge Card Game. */
|
||||
package forge.deck.generation;
|
||||
|
||||
@@ -23,7 +23,6 @@ import java.util.TreeSet;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.deck.DeckFormat;
|
||||
import forge.game.player.PlayerType;
|
||||
import forge.util.FileSection;
|
||||
|
||||
/**
|
||||
@@ -48,7 +47,6 @@ public class DeckFileHeader {
|
||||
private static final String PLAYER_TYPE = "PlayerType";
|
||||
|
||||
private final DeckFormat deckType;
|
||||
private final PlayerType playerType;
|
||||
private final boolean customPool;
|
||||
|
||||
private final String name;
|
||||
@@ -56,6 +54,15 @@ public class DeckFileHeader {
|
||||
|
||||
private final Set<String> tags;
|
||||
|
||||
private final boolean intendedForAi;
|
||||
|
||||
/**
|
||||
* @return the intendedForAi
|
||||
*/
|
||||
public boolean isIntendedForAi() {
|
||||
return intendedForAi;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
*
|
||||
@@ -67,8 +74,7 @@ public class DeckFileHeader {
|
||||
this.comment = kvPairs.get(DeckFileHeader.COMMENT);
|
||||
this.deckType = DeckFormat.smartValueOf(kvPairs.get(DeckFileHeader.DECK_TYPE), DeckFormat.Constructed);
|
||||
this.customPool = kvPairs.getBoolean(DeckFileHeader.CSTM_POOL);
|
||||
boolean isForAi = "computer".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER)) || "ai".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER_TYPE));
|
||||
this.playerType = isForAi ? PlayerType.COMPUTER : PlayerType.HUMAN;
|
||||
this.intendedForAi = "computer".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER)) || "ai".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER_TYPE));
|
||||
this.tags = new TreeSet<String>();
|
||||
|
||||
String rawTags = kvPairs.get(DeckFileHeader.TAGS);
|
||||
@@ -81,15 +87,6 @@ public class DeckFileHeader {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player type.
|
||||
*
|
||||
* @return the player type
|
||||
*/
|
||||
public final PlayerType getPlayerType() {
|
||||
return this.playerType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is custom pool.
|
||||
*
|
||||
135
forge-core/src/main/java/forge/deck/io/DeckSerializer.java
Normal file
135
forge-core/src/main/java/forge/deck/io/DeckSerializer.java
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.deck.io;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.deck.Deck;
|
||||
import forge.util.FileSection;
|
||||
import forge.util.FileSectionManual;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.IItemReader;
|
||||
import forge.util.IItemSerializer;
|
||||
import forge.util.storage.StorageReaderFolder;
|
||||
|
||||
/**
|
||||
* This class knows how to make a file out of a deck object and vice versa.
|
||||
*/
|
||||
public class DeckSerializer extends StorageReaderFolder<Deck> implements IItemSerializer<Deck> {
|
||||
private final boolean moveWronglyNamedDecks;
|
||||
public static final String FILE_EXTENSION = ".dck";
|
||||
|
||||
public DeckSerializer(final File deckDir0) {
|
||||
this(deckDir0, false);
|
||||
}
|
||||
|
||||
public DeckSerializer(final File deckDir0, boolean moveWrongDecks) {
|
||||
super(deckDir0, Deck.FN_NAME_SELECTOR);
|
||||
moveWronglyNamedDecks = moveWrongDecks;
|
||||
}
|
||||
|
||||
/** Constant <code>DCKFileFilter</code>. */
|
||||
public static final FilenameFilter DCK_FILE_FILTER = new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(final File dir, final String name) {
|
||||
return name.endsWith(FILE_EXTENSION);
|
||||
}
|
||||
};
|
||||
public static void writeDeck(final Deck d, final File f) {
|
||||
FileUtil.writeFile(f, d.save());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final Deck unit) {
|
||||
FileUtil.writeFile(this.makeFileFor(unit), unit.save());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void erase(final Deck unit) {
|
||||
this.makeFileFor(unit).delete();
|
||||
}
|
||||
|
||||
public File makeFileFor(final Deck deck) {
|
||||
return new File(this.directory, deck.getBestFileName() + FILE_EXTENSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Deck read(final File file) {
|
||||
final Map<String, List<String>> sections = FileSection.parseSections(FileUtil.readFile(file));
|
||||
Deck result = Deck.fromSections(sections, true);
|
||||
|
||||
if (moveWronglyNamedDecks) {
|
||||
adjustFileLocation(file, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void adjustFileLocation(final File file, final Deck result) {
|
||||
if (result == null) {
|
||||
file.delete();
|
||||
} else {
|
||||
String destFilename = result.getBestFileName() + FILE_EXTENSION;
|
||||
if (!file.getName().equals(destFilename)) {
|
||||
file.renameTo(new File(file.getParentFile().getParentFile(), destFilename));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FilenameFilter getFileFilter() {
|
||||
return DeckSerializer.DCK_FILE_FILTER;
|
||||
}
|
||||
|
||||
public static DeckFileHeader readDeckMetadata(final Map<String, List<String>> map, final boolean canThrow) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
final List<String> metadata = map.get("metadata");
|
||||
if (metadata != null) {
|
||||
return new DeckFileHeader(FileSection.parse(metadata, "="));
|
||||
}
|
||||
final List<String> general = map.get("general");
|
||||
if (general != null) {
|
||||
if (canThrow) {
|
||||
throw new OldDeckFileFormatException();
|
||||
}
|
||||
final FileSectionManual fs = new FileSectionManual();
|
||||
fs.put(DeckFileHeader.NAME, StringUtils.join(map.get(""), " "));
|
||||
fs.put(DeckFileHeader.DECK_TYPE, StringUtils.join(general, " "));
|
||||
return new DeckFileHeader(fs);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.util.storage.StorageReaderBase#getReaderForFolder(java.io.File)
|
||||
*/
|
||||
@Override
|
||||
public IItemReader<Deck> getReaderForFolder(File subfolder) {
|
||||
if ( !subfolder.getParentFile().equals(directory) )
|
||||
throw new UnsupportedOperationException("Only child folders of " + directory + " may be processed");
|
||||
return new DeckSerializer(subfolder, false);
|
||||
}
|
||||
}
|
||||
8
forge-core/src/main/java/forge/deck/io/package-info.java
Normal file
8
forge-core/src/main/java/forge/deck/io/package-info.java
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @author Max
|
||||
*
|
||||
*/
|
||||
package forge.deck.io;
|
||||
8
forge-core/src/main/java/forge/deck/package-info.java
Normal file
8
forge-core/src/main/java/forge/deck/package-info.java
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @author Max
|
||||
*
|
||||
*/
|
||||
package forge.deck;
|
||||
@@ -20,26 +20,25 @@ package forge.item;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.Singletons;
|
||||
import forge.StaticData;
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.SealedProductTemplate;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
public class BoosterPack extends OpenablePack {
|
||||
public class BoosterPack extends SealedProduct {
|
||||
private final int artIndex;
|
||||
private final int hash;
|
||||
|
||||
public static final Function<CardEdition, BoosterPack> FN_FROM_SET = new Function<CardEdition, BoosterPack>() {
|
||||
@Override
|
||||
public BoosterPack apply(final CardEdition arg1) {
|
||||
SealedProductTemplate d = Singletons.getModel().getBoosters().get(arg1.getCode());
|
||||
Template d = StaticData.instance().getBoosters().get(arg1.getCode());
|
||||
return new BoosterPack(arg1.getName(), d);
|
||||
}
|
||||
};
|
||||
|
||||
public BoosterPack(final String name0, final SealedProductTemplate boosterData) {
|
||||
public BoosterPack(final String name0, final Template boosterData) {
|
||||
super(name0, boosterData);
|
||||
int maxIdx = Singletons.getModel().getEditions().get(boosterData.getEdition()).getCntBoosterPictures();
|
||||
int maxIdx = StaticData.instance().getEditions().get(boosterData.getEdition()).getCntBoosterPictures();
|
||||
artIndex = MyRandom.getRandom().nextInt(maxIdx) + 1;
|
||||
hash = super.hashCode() ^ artIndex;
|
||||
}
|
||||
@@ -58,7 +57,7 @@ public class BoosterPack extends OpenablePack {
|
||||
return new BoosterPack(name, contents);
|
||||
}
|
||||
|
||||
public SealedProductTemplate getBoosterData() {
|
||||
public Template getBoosterData() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
141
forge-core/src/main/java/forge/item/FatPack.java
Normal file
141
forge-core/src/main/java/forge/item/FatPack.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package forge.item;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.StaticData;
|
||||
import forge.card.BoosterGenerator;
|
||||
import forge.card.CardEdition;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.storage.StorageReaderFile;
|
||||
|
||||
public class FatPack extends SealedProduct {
|
||||
public static final Function<CardEdition, FatPack> FN_FROM_SET = new Function<CardEdition, FatPack>() {
|
||||
@Override
|
||||
public FatPack apply(final CardEdition arg1) {
|
||||
FatPack.Template d = StaticData.instance().getFatPacks().get(arg1.getCode());
|
||||
return new FatPack(arg1.getName(), d);
|
||||
}
|
||||
};
|
||||
|
||||
private final FatPack.Template fpData;
|
||||
|
||||
public FatPack(final String name0, final FatPack.Template fpData0) {
|
||||
super(name0, StaticData.instance().getBoosters().get(fpData0.getEdition()));
|
||||
fpData = fpData0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return fpData.toString() + contents.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getItemType() {
|
||||
return "Fat Pack";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PaperCard> generate() {
|
||||
List<PaperCard> result = new ArrayList<PaperCard>();
|
||||
for (int i = 0; i < fpData.getCntBoosters(); i++) {
|
||||
result.addAll(super.generate());
|
||||
}
|
||||
result.addAll(BoosterGenerator.getBoosterPack(fpData));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object clone() {
|
||||
return new FatPack(name, fpData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalCards() {
|
||||
return super.getTotalCards() * fpData.getCntBoosters() + fpData.getNumberOfCardsExpected();
|
||||
}
|
||||
|
||||
public static class Template extends SealedProduct.Template {
|
||||
private final int cntBoosters;
|
||||
|
||||
|
||||
public int getCntBoosters() { return cntBoosters; }
|
||||
|
||||
private Template(String edition, int boosters, Iterable<Pair<String, Integer>> itrSlots)
|
||||
{
|
||||
super(edition, itrSlots);
|
||||
cntBoosters = boosters;
|
||||
}
|
||||
|
||||
public static final class Reader extends StorageReaderFile<Template> {
|
||||
public Reader(String pathname) {
|
||||
super(pathname, Template.FN_GET_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Template read(String line, int i) {
|
||||
String[] headAndData = TextUtil.split(line, ':', 2);
|
||||
final String edition = headAndData[0];
|
||||
final String[] data = TextUtil.splitWithParenthesis(headAndData[1], ',');
|
||||
int nBoosters = 6;
|
||||
|
||||
List<Pair<String, Integer>> slots = new ArrayList<Pair<String,Integer>>();
|
||||
for(String slotDesc : data) {
|
||||
String[] kv = TextUtil.split(slotDesc, ' ', 2);
|
||||
if (kv[1].startsWith("Booster"))
|
||||
nBoosters = Integer.parseInt(kv[0]);
|
||||
else
|
||||
slots.add(ImmutablePair.of(kv[1], Integer.parseInt(kv[0])));
|
||||
}
|
||||
|
||||
return new FatPack.Template(edition, nBoosters, slots);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (0 >= cntBoosters) {
|
||||
return "no cards";
|
||||
}
|
||||
|
||||
StringBuilder s = new StringBuilder();
|
||||
for(Pair<String, Integer> p : slots) {
|
||||
s.append(p.getRight()).append(" ").append(p.getLeft()).append(", ");
|
||||
}
|
||||
// trim the last comma and space
|
||||
if( s.length() > 0 )
|
||||
s.replace(s.length() - 2, s.length(), "");
|
||||
|
||||
if (0 < cntBoosters) {
|
||||
if( s.length() > 0 )
|
||||
s.append(" and ");
|
||||
|
||||
s.append(cntBoosters).append(" booster packs ");
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,9 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.Card;
|
||||
//import forge.Card;
|
||||
import forge.card.CardRarity;
|
||||
import forge.card.CardRules;
|
||||
import forge.game.player.Player;
|
||||
import forge.util.PredicateString;
|
||||
|
||||
public interface IPaperCard extends InventoryItem {
|
||||
@@ -161,7 +160,4 @@ public interface IPaperCard extends InventoryItem {
|
||||
|
||||
public abstract String getItemType();
|
||||
|
||||
public abstract Card getMatchingForgeCard();
|
||||
public abstract Card toForgeCard(Player owner);
|
||||
|
||||
}
|
||||
@@ -17,16 +17,10 @@
|
||||
*/
|
||||
package forge.item;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.CardRarity;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.cardfactory.CardFactory;
|
||||
import forge.game.player.Player;
|
||||
|
||||
|
||||
/**
|
||||
@@ -40,7 +34,7 @@ import forge.game.player.Player;
|
||||
*/
|
||||
public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet, IPaperCard {
|
||||
// Reference to rules
|
||||
private final transient CardRules card;
|
||||
private final transient CardRules rules;
|
||||
|
||||
// These fields are kinda PK for PrintedCard
|
||||
public final String name;
|
||||
@@ -55,7 +49,7 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getEdition() {
|
||||
return this.edition;
|
||||
@@ -78,7 +72,7 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
||||
|
||||
@Override
|
||||
public CardRules getRules() {
|
||||
return this.card;
|
||||
return this.rules;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,15 +80,11 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
||||
return this.rarity;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// @Override
|
||||
// public String getImageKey() {
|
||||
// return getImageLocator(getImageName(), getArtIndex(), true, false);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getItemType() {
|
||||
return "Card";
|
||||
@@ -106,7 +96,7 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
||||
public static final Function<PaperCard, CardRules> FN_GET_RULES = new Function<PaperCard, CardRules>() {
|
||||
@Override
|
||||
public CardRules apply(final PaperCard from) {
|
||||
return from.card;
|
||||
return from.rules;
|
||||
}
|
||||
};
|
||||
public static final Function<PaperCard, String> FN_GET_NAME = new Function<PaperCard, String>() {
|
||||
@@ -114,16 +104,16 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
||||
public String apply(final PaperCard from) {
|
||||
return from.getName();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
public PaperCard(final CardRules c, final String edition0, final CardRarity rare, final int index) {
|
||||
this(c, edition0, rare, index, false);
|
||||
}
|
||||
|
||||
|
||||
public PaperCard(final CardRules c, final String edition0, final CardRarity rare, final int index, final boolean foil) {
|
||||
if ( edition0 == null || c == null || rare == null )
|
||||
throw new IllegalArgumentException("Cannot create card without rules, edition or rarity");
|
||||
this.card = c;
|
||||
this.rules = c;
|
||||
this.name = c.getName();
|
||||
this.edition = edition0;
|
||||
this.artIndex = index;
|
||||
@@ -184,34 +174,6 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
||||
// return String.format("%s|%s", name, cardSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* To forge card.
|
||||
*
|
||||
* @return the card
|
||||
*/
|
||||
private static final Map<PaperCard, Card> cp2card = new HashMap<PaperCard, Card>();
|
||||
/* (non-Javadoc)
|
||||
* @see forge.item.ICardPrinted#getMatchingForgeCard()
|
||||
*/
|
||||
@Override
|
||||
public Card getMatchingForgeCard() {
|
||||
Card res = cp2card.get(this);
|
||||
if (null == res) {
|
||||
res = toForgeCard(null);
|
||||
cp2card.put(this, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.item.ICardPrinted#toForgeCard(forge.game.player.Player)
|
||||
*/
|
||||
@Override
|
||||
public Card toForgeCard(Player owner) {
|
||||
final Card c = CardFactory.getCard(this, owner);
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -2,12 +2,10 @@ package forge.item;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.CardRarity;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.cardfactory.CardFactory;
|
||||
import forge.game.player.Player;
|
||||
|
||||
|
||||
public class PaperToken implements InventoryItemFromSet, IPaperCard {
|
||||
private String name;
|
||||
@@ -61,13 +59,6 @@ public class PaperToken implements InventoryItemFromSet, IPaperCard {
|
||||
public String getImageFilename() { return imageFileName; }
|
||||
|
||||
@Override public String getItemType() { return "Token"; }
|
||||
@Override public Card getMatchingForgeCard() { return toForgeCard(null); } // hope this won't be queried too frequently, so no cache
|
||||
|
||||
@Override
|
||||
public Card toForgeCard(Player owner) {
|
||||
final Card c = CardFactory.getCard(this, owner);
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override public boolean isToken() { return true; }
|
||||
}
|
||||
@@ -18,16 +18,18 @@
|
||||
package forge.item;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.Singletons;
|
||||
import forge.StaticData;
|
||||
import forge.deck.Deck;
|
||||
import forge.quest.SellRules;
|
||||
import forge.deck.io.DeckSerializer;
|
||||
import forge.util.FileSection;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.storage.StorageReaderFolder;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
@@ -36,11 +38,11 @@ import forge.util.FileUtil;
|
||||
public class PreconDeck implements InventoryItemFromSet {
|
||||
|
||||
private final Deck deck;
|
||||
private final String imageFilename;
|
||||
private final String set;
|
||||
private final String description;
|
||||
|
||||
private final SellRules recommendedDeals;
|
||||
private String imageFilename;
|
||||
|
||||
// private final SellRules recommendedDeals;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@@ -62,34 +64,12 @@ public class PreconDeck implements InventoryItemFromSet {
|
||||
return "Prebuilt Deck";
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new precon deck.
|
||||
*
|
||||
* @param f
|
||||
* the f
|
||||
*/
|
||||
public PreconDeck(final File f) {
|
||||
final List<String> deckLines = FileUtil.readFile(f);
|
||||
final Map<String, List<String>> sections = FileSection.parseSections(deckLines);
|
||||
this.deck = Deck.fromSections(sections);
|
||||
|
||||
|
||||
|
||||
FileSection kv = FileSection.parse(sections.get("metadata"), "=");
|
||||
|
||||
imageFilename = kv.get("Image");
|
||||
description = kv.get("Description");
|
||||
String deckEdition = kv.get("set");
|
||||
this.set = deckEdition == null || Singletons.getModel().getEditions().get(deckEdition.toUpperCase()) == null ? "n/a" : deckEdition;
|
||||
this.recommendedDeals = new SellRules(sections.get("shop"));
|
||||
|
||||
public PreconDeck(final Deck d, String set, String description) {
|
||||
deck = d;
|
||||
this.set = set;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the deck.
|
||||
*
|
||||
* @return the deck
|
||||
*/
|
||||
|
||||
public final Deck getDeck() {
|
||||
return this.deck;
|
||||
}
|
||||
@@ -99,9 +79,9 @@ public class PreconDeck implements InventoryItemFromSet {
|
||||
*
|
||||
* @return the recommended deals
|
||||
*/
|
||||
public final SellRules getRecommendedDeals() {
|
||||
return this.recommendedDeals;
|
||||
}
|
||||
// public final SellRules getRecommendedDeals() {
|
||||
// return this.recommendedDeals;
|
||||
// }
|
||||
|
||||
public final String getImageFilename() {
|
||||
return imageFilename;
|
||||
@@ -132,5 +112,38 @@ public class PreconDeck implements InventoryItemFromSet {
|
||||
return arg1.getName();
|
||||
}
|
||||
};
|
||||
|
||||
public static class Reader extends StorageReaderFolder<PreconDeck> {
|
||||
|
||||
|
||||
public Reader(final File deckDir0) {
|
||||
super(deckDir0, PreconDeck.FN_NAME_SELECTOR);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected PreconDeck read(final File file) {
|
||||
return getPreconDeckFromSections(FileSection.parseSections(FileUtil.readFile(file)));
|
||||
}
|
||||
|
||||
// To be able to read "shops" section in overloads
|
||||
protected PreconDeck getPreconDeckFromSections(final Map<String, List<String>> sections) {
|
||||
FileSection kv = FileSection.parse(sections.get("metadata"), "=");
|
||||
String imageFilename = kv.get("Image");
|
||||
String description = kv.get("Description");
|
||||
String deckEdition = kv.get("set");
|
||||
String set = deckEdition == null || StaticData.instance().getEditions().get(deckEdition.toUpperCase()) == null ? "n/a" : deckEdition;
|
||||
PreconDeck result = new PreconDeck(Deck.fromSections(sections), set, description);
|
||||
result.imageFilename = imageFilename;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FilenameFilter getFileFilter() {
|
||||
return DeckSerializer.DCK_FILE_FILTER;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
213
forge-core/src/main/java/forge/item/SealedProduct.java
Normal file
213
forge-core/src/main/java/forge/item/SealedProduct.java
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package forge.item;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.StaticData;
|
||||
import forge.card.BoosterGenerator;
|
||||
import forge.card.BoosterSlots;
|
||||
import forge.card.CardRulesPredicates;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.storage.StorageReaderFile;
|
||||
|
||||
public abstract class SealedProduct implements InventoryItemFromSet {
|
||||
protected final Template contents;
|
||||
protected final String name;
|
||||
private final int hash;
|
||||
private List<PaperCard> cards = null;
|
||||
|
||||
public SealedProduct(String name0, Template boosterData) {
|
||||
if (null == name0) { throw new IllegalArgumentException("name0 must not be null"); }
|
||||
if (null == boosterData) { throw new IllegalArgumentException("boosterData must not be null"); }
|
||||
contents = boosterData;
|
||||
name = name0;
|
||||
hash = name.hashCode() ^ getClass().hashCode() ^ contents.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getName() {
|
||||
return name + " " + getItemType();
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return contents.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getEdition() {
|
||||
return contents.getEdition();
|
||||
}
|
||||
|
||||
public final List<PaperCard> getCards() {
|
||||
if (null == cards) {
|
||||
cards = generate();
|
||||
}
|
||||
|
||||
return cards;
|
||||
}
|
||||
|
||||
public int getTotalCards() {
|
||||
return contents.getNumberOfCardsExpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (this.getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
SealedProduct other = (SealedProduct)obj;
|
||||
return name.equals(other.name) && contents.equals(other.contents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
protected List<PaperCard> generate() {
|
||||
return BoosterGenerator.getBoosterPack(contents);
|
||||
}
|
||||
|
||||
protected PaperCard getRandomBasicLand(final String setCode) {
|
||||
return this.getRandomBasicLands(setCode, 1).get(0);
|
||||
}
|
||||
|
||||
protected List<PaperCard> getRandomBasicLands(final String setCode, final int count) {
|
||||
Predicate<PaperCard> cardsRule = Predicates.and(
|
||||
IPaperCard.Predicates.printedInSet(setCode),
|
||||
Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard.FN_GET_RULES));
|
||||
return Aggregates.random(Iterables.filter(StaticData.instance().getCommonCards().getAllCards(), cardsRule), count);
|
||||
}
|
||||
|
||||
|
||||
public static class Template {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final static Template genericBooster = new Template(null, Lists.newArrayList(
|
||||
Pair.of(BoosterSlots.COMMON, 10), Pair.of(BoosterSlots.UNCOMMON, 3),
|
||||
Pair.of(BoosterSlots.RARE_MYTHIC, 1), Pair.of(BoosterSlots.BASIC_LAND, 1)
|
||||
));
|
||||
|
||||
|
||||
protected final List<Pair<String, Integer>> slots;
|
||||
protected final String name;
|
||||
|
||||
|
||||
public final List<Pair<String, Integer>> getSlots() {
|
||||
return slots;
|
||||
}
|
||||
|
||||
public final String getEdition() {
|
||||
return name;
|
||||
}
|
||||
public Template(Iterable<Pair<String, Integer>> itrSlots)
|
||||
{
|
||||
this(null, itrSlots);
|
||||
}
|
||||
|
||||
public Template(String name0, Iterable<Pair<String, Integer>> itrSlots)
|
||||
{
|
||||
slots = Lists.newArrayList(itrSlots);
|
||||
name = name0;
|
||||
}
|
||||
|
||||
public Template(String code, String boosterDesc) {
|
||||
this(code, Reader.parseSlots(boosterDesc));
|
||||
}
|
||||
|
||||
public int getNumberOfCardsExpected() {
|
||||
int sum = 0;
|
||||
for(Pair<String, Integer> p : slots) {
|
||||
sum += p.getRight().intValue();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public static final Function<? super Template, String> FN_GET_NAME = new Function<Template, String>() {
|
||||
@Override
|
||||
public String apply(Template arg1) {
|
||||
return arg1.name;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder s = new StringBuilder();
|
||||
|
||||
|
||||
s.append("consisting of ");
|
||||
for(Pair<String, Integer> p : slots) {
|
||||
s.append(p.getRight()).append(" ").append(p.getLeft()).append(", ");
|
||||
}
|
||||
|
||||
// trim the last comma and space
|
||||
s.replace(s.length() - 2, s.length(), "");
|
||||
|
||||
// put an 'and' before the previous comma
|
||||
int lastCommaIdx = s.lastIndexOf(",");
|
||||
if (0 < lastCommaIdx) {
|
||||
s.replace(lastCommaIdx+1, lastCommaIdx+1, " and");
|
||||
}
|
||||
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
public final static class Reader extends StorageReaderFile<Template> {
|
||||
public Reader(File file) {
|
||||
super(file, Template.FN_GET_NAME);
|
||||
}
|
||||
|
||||
public static List<Pair<String, Integer>> parseSlots(String data) {
|
||||
final String[] dataz = TextUtil.splitWithParenthesis(data, ',');
|
||||
List<Pair<String, Integer>> slots = new ArrayList<Pair<String,Integer>>();
|
||||
for(String slotDesc : dataz) {
|
||||
String[] kv = TextUtil.splitWithParenthesis(slotDesc, ' ', 2);
|
||||
slots.add(ImmutablePair.of(kv[1], Integer.parseInt(kv[0])));
|
||||
}
|
||||
return slots;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Template read(String line, int i) {
|
||||
String[] headAndData = TextUtil.split(line, ':', 2);
|
||||
return new Template(headAndData[0], parseSlots(headAndData[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,23 +21,22 @@ import java.util.List;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.Singletons;
|
||||
import forge.StaticData;
|
||||
import forge.card.BoosterGenerator;
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.SealedProductTemplate;
|
||||
|
||||
public class TournamentPack extends OpenablePack {
|
||||
public class TournamentPack extends SealedProduct {
|
||||
|
||||
/** The Constant fnFromSet. */
|
||||
public static final Function<CardEdition, TournamentPack> FN_FROM_SET = new Function<CardEdition, TournamentPack>() {
|
||||
@Override
|
||||
public TournamentPack apply(final CardEdition arg1) {
|
||||
SealedProductTemplate d = Singletons.getModel().getTournamentPacks().get(arg1.getCode());
|
||||
Template d = StaticData.instance().getTournamentPacks().get(arg1.getCode());
|
||||
return new TournamentPack(arg1.getName(), d);
|
||||
}
|
||||
};
|
||||
|
||||
public TournamentPack(final String name0, final SealedProductTemplate boosterData) {
|
||||
public TournamentPack(final String name0, final Template boosterData) {
|
||||
super(name0, boosterData);
|
||||
}
|
||||
|
||||
8
forge-core/src/main/java/forge/item/package-info.java
Normal file
8
forge-core/src/main/java/forge/item/package-info.java
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @author Max
|
||||
*
|
||||
*/
|
||||
package forge.item;
|
||||
8
forge-core/src/main/java/forge/package-info.java
Normal file
8
forge-core/src/main/java/forge/package-info.java
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @author Max
|
||||
*
|
||||
*/
|
||||
package forge;
|
||||
@@ -1,4 +1,4 @@
|
||||
package forge.util.maps;
|
||||
package forge.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
@@ -31,8 +31,6 @@ import java.util.regex.Pattern;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import forge.error.BugReporter;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* FileUtil class.
|
||||
@@ -109,17 +107,12 @@ public final class FileUtil {
|
||||
}
|
||||
p.close();
|
||||
} catch (final Exception ex) {
|
||||
BugReporter.reportException(ex);
|
||||
throw new RuntimeException("FileUtil : writeFile() error, problem writing file - " + file + " : " + ex);
|
||||
}
|
||||
} // writeAllDecks()
|
||||
|
||||
public static String readFileToString(String filename) {
|
||||
StringBuilder s = new StringBuilder();
|
||||
for (String line : readFile(filename)) {
|
||||
s.append(line).append('\n');
|
||||
}
|
||||
return s.toString();
|
||||
return TextUtil.join(readFile(filename), "\n");
|
||||
}
|
||||
|
||||
public static List<String> readFile(final String filename) {
|
||||
@@ -145,7 +138,6 @@ public final class FileUtil {
|
||||
}
|
||||
return FileUtil.readAllLines(new FileReader(file), false);
|
||||
} catch (final Exception ex) {
|
||||
BugReporter.reportException(ex);
|
||||
throw new RuntimeException("FileUtil : readFile() error, " + ex);
|
||||
}
|
||||
} // readFile()
|
||||
@@ -180,7 +172,6 @@ public final class FileUtil {
|
||||
}
|
||||
in.close();
|
||||
} catch (final IOException ex) {
|
||||
BugReporter.reportException(ex);
|
||||
throw new RuntimeException("FileUtil : readAllLines() error, " + ex);
|
||||
}
|
||||
return list;
|
||||
@@ -15,11 +15,13 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.item;
|
||||
package forge.util;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* ItemPool class.
|
||||
@@ -111,12 +113,12 @@ public class ItemPool<T extends InventoryItem> extends ItemPoolView<T> {
|
||||
return;
|
||||
}
|
||||
this.getItems().put(item, Integer.valueOf(this.count(item) + amount));
|
||||
this.setListInSync(false);
|
||||
this.isListInSync = false;
|
||||
}
|
||||
|
||||
private void put(final T item, final int amount) {
|
||||
this.getItems().put(item, amount);
|
||||
this.setListInSync(false);
|
||||
this.isListInSync = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,7 +136,7 @@ public class ItemPool<T extends InventoryItem> extends ItemPoolView<T> {
|
||||
this.add((T) cr);
|
||||
}
|
||||
}
|
||||
this.setListInSync(false);
|
||||
this.isListInSync = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,7 +155,7 @@ public class ItemPool<T extends InventoryItem> extends ItemPoolView<T> {
|
||||
this.add((T) e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
this.setListInSync(false);
|
||||
this.isListInSync = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,7 +188,7 @@ public class ItemPool<T extends InventoryItem> extends ItemPoolView<T> {
|
||||
} else {
|
||||
this.getItems().put(item, count - amount);
|
||||
}
|
||||
this.setListInSync(false);
|
||||
this.isListInSync = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -222,6 +224,6 @@ public class ItemPool<T extends InventoryItem> extends ItemPoolView<T> {
|
||||
*/
|
||||
public void clear() {
|
||||
this.getItems().clear();
|
||||
this.setListInSync(false);
|
||||
this.isListInSync = false;
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,15 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.item;
|
||||
package forge.util;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.item.PaperCard;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.item;
|
||||
package forge.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
@@ -27,6 +27,8 @@ import java.util.Map.Entry;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -88,7 +90,7 @@ public class ItemPoolView<T extends InventoryItem> implements Iterable<Entry<T,
|
||||
private final transient List<Entry<T, Integer>> itemsOrdered = new ArrayList<Map.Entry<T, Integer>>();
|
||||
|
||||
/** Whether list is in sync. */
|
||||
private transient boolean isListInSync = false;
|
||||
protected transient boolean isListInSync = false;
|
||||
|
||||
/**
|
||||
* iterator.
|
||||
@@ -188,7 +190,7 @@ public class ItemPoolView<T extends InventoryItem> implements Iterable<Entry<T,
|
||||
* @return List<Entry<T, Integer>>
|
||||
*/
|
||||
public final List<Entry<T, Integer>> getOrderedList() {
|
||||
if (!this.isListInSync()) {
|
||||
if (!this.isListInSync) {
|
||||
this.rebuildOrderedList();
|
||||
}
|
||||
return this.itemsOrdered;
|
||||
@@ -201,7 +203,7 @@ public class ItemPoolView<T extends InventoryItem> implements Iterable<Entry<T,
|
||||
this.itemsOrdered.add(e);
|
||||
}
|
||||
}
|
||||
this.setListInSync(true);
|
||||
this.isListInSync = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,24 +240,6 @@ public class ItemPoolView<T extends InventoryItem> implements Iterable<Entry<T,
|
||||
return this.myClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is list in sync.
|
||||
*
|
||||
* @return the isListInSync
|
||||
*/
|
||||
public boolean isListInSync() {
|
||||
return this.isListInSync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list in sync.
|
||||
*
|
||||
* @param isListInSync0
|
||||
* the isListInSync to set
|
||||
*/
|
||||
protected void setListInSync(final boolean isListInSync0) {
|
||||
this.isListInSync = isListInSync0;
|
||||
}
|
||||
|
||||
/**
|
||||
* To item list string.
|
||||
@@ -43,7 +43,7 @@ public class TextUtil {
|
||||
return mapAsString.toString();
|
||||
}
|
||||
|
||||
public static String[] split(CharSequence input, char delimiter) {
|
||||
public static String[] split(CharSequence input, char delimiter) {
|
||||
return splitWithParenthesis(input, delimiter, Integer.MAX_VALUE, '\0', '\0', true);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class TextUtil {
|
||||
|
||||
/**
|
||||
* Split string separated by a single char delimiter, can take parenthesis in account
|
||||
* It's faster than String.split, and allows parenthesis
|
||||
* It's faster than String.split, and allows parenthesis
|
||||
*/
|
||||
public static String[] splitWithParenthesis(CharSequence input, char delimiter, int maxEntries, char openPar, char closePar, boolean skipEmpty) {
|
||||
List<String> result = new ArrayList<String>();
|
||||
@@ -98,7 +98,18 @@ public class TextUtil {
|
||||
String[] toReturn = result.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
|
||||
return trimParenthesis ? StringUtils.stripAll(toReturn, String.valueOf(openPar)) : toReturn;
|
||||
}
|
||||
|
||||
|
||||
public static String join(Iterable<String> strs, String delim) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String str : strs) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(delim);
|
||||
}
|
||||
sb.append(str);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an enum value to a printable label but upcasing the first letter
|
||||
* and lcasing all subsequent letters
|
||||
54
forge-core/src/main/java/forge/util/ThreadUtil.java
Normal file
54
forge-core/src/main/java/forge/util/ThreadUtil.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package forge.util;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ThreadUtil {
|
||||
|
||||
static {
|
||||
System.out.printf("(ThreadUtil first call): Running on a machine with %d cpu core(s)%n", Runtime.getRuntime().availableProcessors() );
|
||||
}
|
||||
|
||||
private static class WorkerThreadFactory implements ThreadFactory {
|
||||
private int countr = 0;
|
||||
private String prefix = "";
|
||||
|
||||
public WorkerThreadFactory(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public Thread newThread(Runnable r) {
|
||||
return new Thread(r, prefix + "-" + countr++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private final static ExecutorService gameThreadPool = Executors.newCachedThreadPool(new WorkerThreadFactory("Game"));
|
||||
private static ExecutorService getGameThreadPool() { return gameThreadPool; }
|
||||
private final static ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2, new WorkerThreadFactory("Delayed"));
|
||||
private static ScheduledExecutorService getScheduledPool() { return scheduledPool; }
|
||||
|
||||
// This pool is designed to parallel CPU or IO intensive tasks like parse cards or download images, assuming a load factor of 0.5
|
||||
public final static ExecutorService getComputingPool(float loadFactor) {
|
||||
return Executors.newFixedThreadPool((int)(Runtime.getRuntime().availableProcessors() / (1-loadFactor)));
|
||||
}
|
||||
|
||||
public static boolean isMultiCoreSystem() {
|
||||
return Runtime.getRuntime().availableProcessors() > 1;
|
||||
}
|
||||
|
||||
public static void invokeInGameThread(Runnable toRun) {
|
||||
getGameThreadPool().execute(toRun);
|
||||
}
|
||||
public static void delay(int milliseconds, Runnable inputUpdater) {
|
||||
getScheduledPool().schedule(inputUpdater, milliseconds, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public static boolean isGameThread() {
|
||||
return Thread.currentThread().getName().startsWith("Game");
|
||||
}
|
||||
}
|
||||
8
forge-core/src/main/java/forge/util/package-info.java
Normal file
8
forge-core/src/main/java/forge/util/package-info.java
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @author Max
|
||||
*
|
||||
*/
|
||||
package forge.util;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user