mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +00:00
Compare commits
579 Commits
forge-1.5.
...
forge-1.5.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23a012364b | ||
|
|
ed0f3600f5 | ||
|
|
dd4e250432 | ||
|
|
2ffb71e053 | ||
|
|
be25cf699c | ||
|
|
1cc15fe50c | ||
|
|
a04e5c1da2 | ||
|
|
5b18ba9058 | ||
|
|
753f4d989b | ||
|
|
8960fa20c3 | ||
|
|
38344027ca | ||
|
|
90ff1abab8 | ||
|
|
7fe3799ea6 | ||
|
|
5ed6fba085 | ||
|
|
6c3573d854 | ||
|
|
d00aeffbda | ||
|
|
e247b8e368 | ||
|
|
3d54fd3b7b | ||
|
|
b19b5daf48 | ||
|
|
f48952aa94 | ||
|
|
e8d4433bb3 | ||
|
|
84b0e17572 | ||
|
|
e4ba6f56dd | ||
|
|
bdfd2e9adf | ||
|
|
849655cb2f | ||
|
|
1c391a7c7e | ||
|
|
cf1990ddf7 | ||
|
|
fad3ea497d | ||
|
|
f586525a61 | ||
|
|
832a290778 | ||
|
|
ecbba9f1c0 | ||
|
|
afeb4eb815 | ||
|
|
d0b5e78f7a | ||
|
|
1837234650 | ||
|
|
c65031ea31 | ||
|
|
14a7176325 | ||
|
|
a0c3a1eb05 | ||
|
|
f7af3865b7 | ||
|
|
51a0c08042 | ||
|
|
abc2118a77 | ||
|
|
776ac3ee2b | ||
|
|
63eaec8348 | ||
|
|
ddb8464c1c | ||
|
|
29ef7a7d3b | ||
|
|
49aa0cc459 | ||
|
|
cdf1b44cb0 | ||
|
|
61fe9f2282 | ||
|
|
0b9d254e12 | ||
|
|
77b241eb68 | ||
|
|
b98ae5844c | ||
|
|
507ce6f220 | ||
|
|
4d2a27f7e8 | ||
|
|
a90841a6b6 | ||
|
|
e9bb6e42f6 | ||
|
|
ed4b11d9ef | ||
|
|
c115f01edf | ||
|
|
8fd6bbef3b | ||
|
|
8fa68731d1 | ||
|
|
b6b586a865 | ||
|
|
457ba444f1 | ||
|
|
31a367c434 | ||
|
|
e83eb92948 | ||
|
|
5ee779846d | ||
|
|
7a3ecf8e38 | ||
|
|
9e2c96a18e | ||
|
|
6550fa28ca | ||
|
|
de9ce7ebb9 | ||
|
|
caae78b6ee | ||
|
|
495701c46c | ||
|
|
ed99ce1694 | ||
|
|
51a37e896d | ||
|
|
b431315e88 | ||
|
|
ea59f120da | ||
|
|
9bd30e8d5d | ||
|
|
39d1ef7e13 | ||
|
|
83a1b70efe | ||
|
|
01b4f803a8 | ||
|
|
5c31890066 | ||
|
|
be7f4e5192 | ||
|
|
4124c45875 | ||
|
|
06e785c75a | ||
|
|
2f384c079c | ||
|
|
e4adada542 | ||
|
|
efa86891cc | ||
|
|
bcc20bb774 | ||
|
|
937a095209 | ||
|
|
1661228168 | ||
|
|
b17b9eb4e1 | ||
|
|
2ffa1510ed | ||
|
|
d1ef107b48 | ||
|
|
aa48e9cacc | ||
|
|
3c0bfa7843 | ||
|
|
803b6331f4 | ||
|
|
fe8af8705d | ||
|
|
624365cda3 | ||
|
|
4fb59b6071 | ||
|
|
d15948e44b | ||
|
|
bf629ff518 | ||
|
|
ee9ee7f207 | ||
|
|
311d4091ff | ||
|
|
4e79f508c0 | ||
|
|
90828e6eab | ||
|
|
7d3afc35cc | ||
|
|
6f4c046732 | ||
|
|
503a8da70f | ||
|
|
1cf9a005d9 | ||
|
|
fe04d56568 | ||
|
|
93b6ac15dd | ||
|
|
500632515c | ||
|
|
598d2da9d6 | ||
|
|
05f7a9b30a | ||
|
|
0b6be04428 | ||
|
|
dcb9553807 | ||
|
|
c9c9be68b1 | ||
|
|
53e6671143 | ||
|
|
3d063d8188 | ||
|
|
8d3633fe63 | ||
|
|
ee7d64c533 | ||
|
|
5009ebe0ab | ||
|
|
9b2f3f3108 | ||
|
|
9ca9dc797e | ||
|
|
2ffc18cc89 | ||
|
|
cfeeda3c93 | ||
|
|
a2277bc2d4 | ||
|
|
694e4e7988 | ||
|
|
1c0e786489 | ||
|
|
7420e94876 | ||
|
|
73c921bb95 | ||
|
|
7a22f4f74a | ||
|
|
cdb76d344e | ||
|
|
6cbded92cb | ||
|
|
bc032a074c | ||
|
|
89a4afdc08 | ||
|
|
be6266d633 | ||
|
|
705264ba9a | ||
|
|
a0b181e6fe | ||
|
|
df50a0a38d | ||
|
|
abd182e17f | ||
|
|
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"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<classpath>
|
<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.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.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
|
||||||
<classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
|
<classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
|
||||||
|
|||||||
31247
.gitattributes
vendored
31247
.gitattributes
vendored
File diff suppressed because it is too large
Load Diff
26
.gitignore
vendored
26
.gitignore
vendored
@@ -2,20 +2,28 @@
|
|||||||
/*.iml
|
/*.iml
|
||||||
/*.tmp
|
/*.tmp
|
||||||
/.metadata
|
/.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
|
/forge.profile.properties
|
||||||
/nbactions.xml
|
/nbactions.xml
|
||||||
/pom.xml.next
|
/pom.xml.next
|
||||||
/pom.xml.releaseBackup
|
/pom.xml.releaseBackup
|
||||||
/pom.xml.tag
|
/pom.xml.tag
|
||||||
/release.properties
|
/release.properties
|
||||||
res/*.log
|
|
||||||
res/PerSetTrackingResults
|
|
||||||
res/cardsfolder/*.bat
|
|
||||||
res/decks
|
|
||||||
res/layouts
|
|
||||||
res/pics*
|
|
||||||
res/pics_product
|
|
||||||
/target
|
/target
|
||||||
/test-output
|
/test-output
|
||||||
tools/PerSetTrackingResults
|
|
||||||
tools/oracleScript.log
|
|
||||||
|
|||||||
29
.project
29
.project
@@ -4,36 +4,7 @@
|
|||||||
<comment></comment>
|
<comment></comment>
|
||||||
<projects>
|
<projects>
|
||||||
</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>
|
<natures>
|
||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
|
||||||
<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
|
|
||||||
</natures>
|
</natures>
|
||||||
</projectDescription>
|
</projectDescription>
|
||||||
|
|||||||
101
CHANGES.txt
101
CHANGES.txt
@@ -1,101 +0,0 @@
|
|||||||
Forge Beta: 10-01-2013 ver 1.5.1
|
|
||||||
|
|
||||||
|
|
||||||
13328 cards in total.
|
|
||||||
|
|
||||||
|
|
||||||
-------------
|
|
||||||
Release Notes
|
|
||||||
-------------
|
|
||||||
|
|
||||||
- Forge freezing during a match bug -
|
|
||||||
A number of people have reported this bug and we now feel that it may have been fixed in this version. Please play test this version and let us know.
|
|
||||||
|
|
||||||
|
|
||||||
- Skinned titlebar for main window -
|
|
||||||
Titlebar is now skinned instead of displaying using standard OS window titlebar
|
|
||||||
Maximizing window now displays full-screen
|
|
||||||
Can use Layout > View > Titlebar (F11) to toggle visibility of titlebar (will also open full-screen if hiding titlebar)
|
|
||||||
|
|
||||||
|
|
||||||
- Forge now requires Java 7 -
|
|
||||||
Please update your Java runtime environment. At this point Forge versions 1.4.2 and above will no longer run under Java 6. Those who are using Mac OS should install the JDK version rather than the JRE version.
|
|
||||||
|
|
||||||
|
|
||||||
- The Mac OS X application -
|
|
||||||
At this time Forge now requires Java 7 and will no longer run under Java 6.
|
|
||||||
|
|
||||||
Unfortunately, the Mac OS X builder that we were using does not support Java 7. We hope to find and to use a different Mac OS X builder in order to continue releasing a Mac OS bundled application like we have in the past.
|
|
||||||
|
|
||||||
Currently, the windows/unix release of Forge includes a launcher file named "forge.command". Double click on the "forge.command" launcher command file and this will in turn launch the Forge jar file via the terminal application while increasing the Java heap space. This should be a temporary inconvenience.
|
|
||||||
|
|
||||||
|
|
||||||
---------
|
|
||||||
New Cards
|
|
||||||
---------
|
|
||||||
|
|
||||||
Chaos Moon
|
|
||||||
Deep Water
|
|
||||||
Infernal Darkness
|
|
||||||
Mana Reflection
|
|
||||||
Mausoleum Turnkey
|
|
||||||
Naked Singularity
|
|
||||||
Pale Moon
|
|
||||||
Pulse of Llanowar
|
|
||||||
Reality Twist
|
|
||||||
Ritual of Subdual
|
|
||||||
|
|
||||||
|
|
||||||
-----------
|
|
||||||
New Schemes
|
|
||||||
-----------
|
|
||||||
|
|
||||||
Nature Demands an Offering
|
|
||||||
|
|
||||||
|
|
||||||
--------------------
|
|
||||||
New Vanguard Avatars
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Mirri
|
|
||||||
|
|
||||||
|
|
||||||
------------
|
|
||||||
Known Issues
|
|
||||||
------------
|
|
||||||
|
|
||||||
Several people have noticed that the cards displayed on the battlefield will fail to be displayed when the number of cards on the battlefield increases. Maximizing the human panel can help to re-display the cards.
|
|
||||||
|
|
||||||
Some time was spent turning the static ETB triggers into the proper ETB replacement effects they should be, mainly to interact correctly with each other. This work is not yet finished. As a result there is currently some inconsistencies with "Enters the battlefield with counters" (Not incredibly noticeable).
|
|
||||||
|
|
||||||
A recent contribution to the code base should fix some of the bugs that people noticed with cloning type abilities. At this time there is one remaining issue that we hope will be addressed in the near future:
|
|
||||||
Copies of cards that setup Zone Change triggers via addComesIntoPlayCommand and addLeavesPlayCommand will not function correctly.
|
|
||||||
|
|
||||||
The Forge archive includes a readme.txt file and we ask that you spend a few minutes reading this file as it contains some information that may prove useful. We do tend to update this file at times and you should quickly read this file and look for new information for each and every new release. Thank you.
|
|
||||||
|
|
||||||
The archive format used for the Forge distribution is ".tar.bz2". There are utilities for Windows, Mac OS and the various *nix's that can be used to extract/decompress these ".tar.bz2" archives. We recommend that you extract/decompress the Forge archive into a new and unused folder.
|
|
||||||
|
|
||||||
Some people use the Windows application 7zip. This utility can be found at http://www.7-zip.org/download.html. Mac users can double click on the archive and the application Archive Utility will launch and extract the archive. Mac users do not need to download a separate utility.
|
|
||||||
|
|
||||||
|
|
||||||
----------------------------
|
|
||||||
Contributors to This Release
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
DrDev
|
|
||||||
Dripton
|
|
||||||
Gos
|
|
||||||
Hellfish
|
|
||||||
Max
|
|
||||||
Sloth
|
|
||||||
spr
|
|
||||||
Swordshine
|
|
||||||
Chris H
|
|
||||||
|
|
||||||
|
|
||||||
(Quest icons used created by Teekatas, from his Legendora set http://raindropmemory.deviantart.com)
|
|
||||||
(Thanks to the MAGE team for permission to use their targeting arrows.)
|
|
||||||
(Thanks to http://www.freesound.org/browse/ for providing some sound files.)
|
|
||||||
|
|
||||||
|
|
||||||
end
|
|
||||||
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.7</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.7</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>forge-core</artifactId>
|
||||||
|
<name>Forge Core</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>15.0</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.
|
* Forge: Play Magic: the Gathering.
|
||||||
* Copyright (C) 2011 Forge Team
|
* Copyright (C) 2011 Forge Team
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package forge.card.cardfactory;
|
package forge;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Enumeration;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.Comparator;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.Enumeration;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.zip.ZipFile;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
import javax.swing.SwingUtilities;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
import org.apache.commons.lang.time.StopWatch;
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
import forge.FThreads;
|
import org.apache.commons.lang3.time.StopWatch;
|
||||||
import forge.card.CardRules;
|
|
||||||
import forge.card.CardRulesReader;
|
import forge.card.CardRules;
|
||||||
import forge.error.BugReporter;
|
import forge.util.FileUtil;
|
||||||
import forge.gui.toolbox.FProgressBar;
|
import forge.util.ThreadUtil;
|
||||||
import forge.util.FileUtil;
|
|
||||||
|
/**
|
||||||
/**
|
* <p>
|
||||||
* <p>
|
* CardReader class.
|
||||||
* CardReader class.
|
* </p>
|
||||||
* </p>
|
*
|
||||||
*
|
* @author Forge
|
||||||
* @author Forge
|
* @version $Id: CardStorageReader.java 23742 2013-11-22 16:32:56Z Max mtg $
|
||||||
* @version $Id$
|
*/
|
||||||
*/
|
|
||||||
public class CardStorageReader {
|
public class CardStorageReader {
|
||||||
|
public interface Observer {
|
||||||
private static final String CARD_FILE_DOT_EXTENSION = ".txt";
|
public void cardLoaded(CardRules rules, List<String> lines, File fileOnDisk);
|
||||||
|
}
|
||||||
/** Default charset when loading from files. */
|
|
||||||
public static final String DEFAULT_CHARSET_NAME = "US-ASCII";
|
public interface ProgressObserver{
|
||||||
|
void setOperationName(String name, boolean usePercents);
|
||||||
final private boolean useThreadPool = FThreads.isMultiCoreSystem();
|
void report(int current, int total);
|
||||||
final private int NUMBER_OF_PARTS = 25;
|
|
||||||
|
// does nothing, used when they pass null instead of an instance
|
||||||
final private CountDownLatch cdl = new CountDownLatch(NUMBER_OF_PARTS);
|
public final static ProgressObserver emptyObserver = new ProgressObserver() {
|
||||||
final private FProgressBar barProgress;
|
@Override public void setOperationName(String name, boolean usePercents) {}
|
||||||
|
@Override public void report(int current, int total) {}
|
||||||
private transient File cardsfolder;
|
};
|
||||||
|
}
|
||||||
private transient ZipFile zip;
|
|
||||||
private transient Charset charset;
|
private static final String CARD_FILE_DOT_EXTENSION = ".txt";
|
||||||
|
|
||||||
|
/** Default charset when loading from files. */
|
||||||
// 8/18/11 10:56 PM
|
public static final String DEFAULT_CHARSET_NAME = "US-ASCII";
|
||||||
|
|
||||||
|
private final boolean useThreadPool = ThreadUtil.isMultiCoreSystem();
|
||||||
/**
|
private final static int NUMBER_OF_PARTS = 25;
|
||||||
* <p>
|
|
||||||
* Constructor for CardReader.
|
private final ProgressObserver progressObserver;
|
||||||
* </p>
|
|
||||||
*
|
private transient File cardsfolder;
|
||||||
* @param theCardsFolder
|
|
||||||
* indicates location of the cardsFolder
|
private transient ZipFile zip;
|
||||||
* @param useZip
|
private final transient Charset charset;
|
||||||
* if true, attempts to load cards from a zip file, if one
|
|
||||||
* exists.
|
private final Observer observer;
|
||||||
*/
|
|
||||||
public CardStorageReader(String cardDataDir, final boolean useZip, FProgressBar barProgress) {
|
|
||||||
this.barProgress = barProgress;
|
// 8/18/11 10:56 PM
|
||||||
|
|
||||||
// These read data for lightweight classes.
|
|
||||||
File theCardsFolder = new File(cardDataDir);
|
/**
|
||||||
|
* <p>
|
||||||
if (!theCardsFolder.exists()) {
|
* Constructor for CardReader.
|
||||||
throw new RuntimeException("CardReader : constructor error -- file not found -- filename is "
|
* </p>
|
||||||
+ theCardsFolder.getAbsolutePath());
|
*
|
||||||
}
|
* @param theCardsFolder
|
||||||
|
* indicates location of the cardsFolder
|
||||||
if (!theCardsFolder.isDirectory()) {
|
* @param useZip
|
||||||
throw new RuntimeException("CardReader : constructor error -- not a directory -- "
|
* if true, attempts to load cards from a zip file, if one
|
||||||
+ theCardsFolder.getAbsolutePath());
|
* exists.
|
||||||
}
|
*/
|
||||||
|
public CardStorageReader(String cardDataDir, CardStorageReader.ProgressObserver progressObserver, Observer observer) {
|
||||||
this.cardsfolder = theCardsFolder;
|
this.progressObserver = progressObserver != null ? progressObserver : CardStorageReader.ProgressObserver.emptyObserver;
|
||||||
|
this.cardsfolder = new File(cardDataDir);
|
||||||
final File zipFile = new File(theCardsFolder, "cardsfolder.zip");
|
this.observer = observer;
|
||||||
|
|
||||||
if (useZip && zipFile.exists()) {
|
// These read data for lightweight classes.
|
||||||
try {
|
if (!cardsfolder.exists()) {
|
||||||
this.zip = new ZipFile(zipFile);
|
throw new RuntimeException("CardReader : constructor error -- " + cardsfolder.getAbsolutePath() + " file/folder not found.");
|
||||||
} 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());
|
|
||||||
}
|
if (!cardsfolder.isDirectory()) {
|
||||||
}
|
throw new RuntimeException("CardReader : constructor error -- not a directory -- " + cardsfolder.getAbsolutePath());
|
||||||
|
}
|
||||||
this.charset = Charset.forName(CardStorageReader.DEFAULT_CHARSET_NAME);
|
|
||||||
|
final File zipFile = new File(cardsfolder, "cardsfolder.zip");
|
||||||
} // CardReader()
|
|
||||||
|
if (zipFile.exists()) {
|
||||||
private final List<CardRules> loadCardsInRange(final List<File> files, int from, int to) {
|
try {
|
||||||
|
this.zip = new ZipFile(zipFile);
|
||||||
CardRulesReader rulesReader = new CardRulesReader();
|
} 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());
|
||||||
List<CardRules> result = new ArrayList<CardRules>();
|
}
|
||||||
for(int i = from; i < to; i++) {
|
}
|
||||||
File cardTxtFile = files.get(i);
|
|
||||||
result.add(this.loadCard(rulesReader, cardTxtFile));
|
this.charset = Charset.forName(CardStorageReader.DEFAULT_CHARSET_NAME);
|
||||||
}
|
|
||||||
return result;
|
} // CardReader()
|
||||||
}
|
|
||||||
|
private final List<CardRules> loadCardsInRange(final List<File> files, int from, int to) {
|
||||||
private final List<CardRules> loadCardsInRangeFromZip(final List<ZipEntry> files, int from, int to) {
|
CardRules.Reader rulesReader = new CardRules.Reader();
|
||||||
|
|
||||||
CardRulesReader rulesReader = new CardRulesReader();
|
List<CardRules> result = new ArrayList<CardRules>();
|
||||||
|
for(int i = from; i < to; i++) {
|
||||||
List<CardRules> result = new ArrayList<CardRules>();
|
File cardTxtFile = files.get(i);
|
||||||
for(int i = from; i < to; i++) {
|
result.add(this.loadCard(rulesReader, cardTxtFile));
|
||||||
ZipEntry ze = files.get(i);
|
}
|
||||||
// if (ze.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION)) // already filtered!
|
return result;
|
||||||
result.add(this.loadCard(rulesReader, ze));
|
}
|
||||||
}
|
|
||||||
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++) {
|
||||||
* Starts reading cards into memory until the given card is found.
|
ZipEntry ze = files.get(i);
|
||||||
*
|
// if (ze.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION)) // already filtered!
|
||||||
* After that, we save our place in the list of cards (on disk) in case we
|
result.add(this.loadCard(rulesReader, ze));
|
||||||
* need to load more.
|
}
|
||||||
*
|
return result;
|
||||||
* @return the Card or null if it was not found.
|
}
|
||||||
*/
|
|
||||||
public final List<CardRules> loadCards() {
|
/**
|
||||||
if (barProgress != null) {
|
* Starts reading cards into memory until the given card is found.
|
||||||
barProgress.setMaximum(NUMBER_OF_PARTS);
|
*
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
* After that, we save our place in the list of cards (on disk) in case we
|
||||||
@Override
|
* need to load more.
|
||||||
public void run() {
|
*
|
||||||
barProgress.setPercentMode(true);
|
* @return the Card or null if it was not found.
|
||||||
barProgress.setDescription("Loading card data: ");
|
*/
|
||||||
}
|
public final Iterable<CardRules> loadCards() {
|
||||||
});
|
progressObserver.setOperationName("Loading cards, examining folder", true);
|
||||||
}
|
|
||||||
|
// Iterate through txt files or zip archive.
|
||||||
final List<Callable<List<CardRules>>> tasks;
|
// Report relevant numbers to progress monitor model.
|
||||||
long estimatedFilesRemaining;
|
|
||||||
|
|
||||||
// Iterate through txt files or zip archive.
|
Set<CardRules> result = new TreeSet<CardRules>(new Comparator<CardRules>() {
|
||||||
// Report relevant numbers to progress monitor model.
|
@Override
|
||||||
if (this.zip == null) {
|
public int compare(CardRules o1, CardRules o2) {
|
||||||
final List<File> allFiles = new ArrayList<File>();
|
return String.CASE_INSENSITIVE_ORDER.compare(o1.getName(), o2.getName());
|
||||||
fillFilesArray(allFiles, this.cardsfolder);
|
}
|
||||||
estimatedFilesRemaining = allFiles.size();
|
});
|
||||||
tasks = makeTaskListForFiles(allFiles);
|
|
||||||
} else {
|
final List<File> allFiles = collectCardFiles(new ArrayList<File>(), this.cardsfolder);
|
||||||
|
if(!allFiles.isEmpty()) {
|
||||||
estimatedFilesRemaining = this.zip.size();
|
int fileParts = zip == null ? NUMBER_OF_PARTS : 1 + NUMBER_OF_PARTS / 3;
|
||||||
ZipEntry entry;
|
if( allFiles.size() < fileParts * 100)
|
||||||
List<ZipEntry> entries = new ArrayList<ZipEntry>();
|
fileParts = allFiles.size() / 100; // to avoid creation of many threads for a dozen of files
|
||||||
// zipEnum was initialized in the constructor.
|
final CountDownLatch cdlFiles = new CountDownLatch(fileParts);
|
||||||
Enumeration<? extends ZipEntry> zipEnum = this.zip.entries();
|
List<Callable<List<CardRules>>> taskFiles = makeTaskListForFiles(allFiles, cdlFiles);
|
||||||
while (zipEnum.hasMoreElements()) {
|
progressObserver.setOperationName("Loading cards from folders", true);
|
||||||
entry = zipEnum.nextElement();
|
progressObserver.report(0, taskFiles.size());
|
||||||
if (entry.isDirectory() || !entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION))
|
StopWatch sw = new StopWatch();
|
||||||
continue;
|
sw.start();
|
||||||
entries.add(entry);
|
executeLoadTask(result, taskFiles, cdlFiles);
|
||||||
}
|
sw.stop();
|
||||||
|
final long timeOnParse = sw.getTime();
|
||||||
tasks = makeTaskListForZip(entries);
|
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");
|
||||||
} // endif
|
}
|
||||||
|
|
||||||
StopWatch sw = new StopWatch();
|
if( this.zip != null ) {
|
||||||
sw.start();
|
final CountDownLatch cdlZip = new CountDownLatch(NUMBER_OF_PARTS);
|
||||||
|
List<Callable<List<CardRules>>> taskZip = new ArrayList<>();
|
||||||
List<CardRules> res = executeLoadTask(tasks);
|
|
||||||
|
ZipEntry entry;
|
||||||
sw.stop();
|
List<ZipEntry> entries = new ArrayList<ZipEntry>();
|
||||||
final long timeOnParse = sw.getTime();
|
// zipEnum was initialized in the constructor.
|
||||||
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");
|
Enumeration<? extends ZipEntry> zipEnum = this.zip.entries();
|
||||||
if ( null != barProgress )
|
while (zipEnum.hasMoreElements()) {
|
||||||
barProgress.setPercentMode(false);
|
entry = zipEnum.nextElement();
|
||||||
return res;
|
if (entry.isDirectory() || !entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION))
|
||||||
} // loadCardsUntilYouFind(String)
|
continue;
|
||||||
|
entries.add(entry);
|
||||||
private List<CardRules> executeLoadTask(final List<Callable<List<CardRules>>> tasks) {
|
}
|
||||||
List<CardRules> result = new ArrayList<CardRules>();
|
|
||||||
|
taskZip = makeTaskListForZip(entries, cdlZip);
|
||||||
try {
|
progressObserver.setOperationName("Loading cards from archive", true);
|
||||||
if ( useThreadPool ) {
|
progressObserver.report(0, taskZip.size());
|
||||||
final ExecutorService executor = FThreads.getComputingPool(0.5f);
|
StopWatch sw = new StopWatch();
|
||||||
final List<Future<List<CardRules>>> parts = executor.invokeAll(tasks);
|
sw.start();
|
||||||
executor.shutdown();
|
executeLoadTask(result, taskZip, cdlZip);
|
||||||
cdl.await();
|
sw.stop();
|
||||||
for(Future<List<CardRules>> pp : parts) {
|
final long timeOnParse = sw.getTime();
|
||||||
result.addAll(pp.get());
|
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");
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for(Callable<List<CardRules>> c : tasks) {
|
return result;
|
||||||
result.addAll(c.call());
|
} // loadCardsUntilYouFind(String)
|
||||||
}
|
|
||||||
}
|
private void executeLoadTask(Collection<CardRules> result, final List<Callable<List<CardRules>>> tasks, CountDownLatch cdl) {
|
||||||
} catch (InterruptedException e) {
|
try {
|
||||||
e.printStackTrace();
|
if ( useThreadPool ) {
|
||||||
} catch (ExecutionException e) {
|
final ExecutorService executor = ThreadUtil.getComputingPool(0.5f);
|
||||||
e.printStackTrace();
|
final List<Future<List<CardRules>>> parts = executor.invokeAll(tasks);
|
||||||
} catch (Exception e) { // this clause comes from non-threaded branch
|
executor.shutdown();
|
||||||
throw new RuntimeException(e);
|
cdl.await();
|
||||||
}
|
for(Future<List<CardRules>> pp : parts) {
|
||||||
|
result.addAll(pp.get());
|
||||||
return result;
|
}
|
||||||
}
|
} else {
|
||||||
|
for(Callable<List<CardRules>> c : tasks) {
|
||||||
private List<Callable<List<CardRules>>> makeTaskListForZip(final List<ZipEntry> entries) {
|
result.addAll(c.call());
|
||||||
int totalFiles = entries.size();
|
}
|
||||||
int filesPerPart = totalFiles / NUMBER_OF_PARTS;
|
}
|
||||||
final List<Callable<List<CardRules>>> tasks = new ArrayList<Callable<List<CardRules>>>();
|
} catch (InterruptedException e) {
|
||||||
for (int iPart = 0; iPart < NUMBER_OF_PARTS; iPart++) {
|
e.printStackTrace();
|
||||||
final int from = iPart * filesPerPart;
|
} catch (ExecutionException e) {
|
||||||
final int till = iPart == NUMBER_OF_PARTS - 1 ? totalFiles : from + filesPerPart;
|
e.printStackTrace();
|
||||||
tasks.add(new Callable<List<CardRules>>() {
|
} catch (Exception e) { // this clause comes from non-threaded branch
|
||||||
@Override
|
throw new RuntimeException(e);
|
||||||
public List<CardRules> call() throws Exception{
|
}
|
||||||
List<CardRules> res = loadCardsInRangeFromZip(entries, from, till);
|
}
|
||||||
if ( null != barProgress )
|
|
||||||
barProgress.increment();
|
private List<Callable<List<CardRules>>> makeTaskListForZip(final List<ZipEntry> entries, final CountDownLatch cdl) {
|
||||||
cdl.countDown();
|
int totalFiles = entries.size();
|
||||||
return res;
|
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++) {
|
||||||
return tasks;
|
final int from = iPart * filesPerPart;
|
||||||
}
|
final int till = iPart == maxParts - 1 ? totalFiles : from + filesPerPart;
|
||||||
|
tasks.add(new Callable<List<CardRules>>() {
|
||||||
private List<Callable<List<CardRules>>> makeTaskListForFiles(final List<File> allFiles) {
|
@Override
|
||||||
int totalFiles = allFiles.size();
|
public List<CardRules> call() throws Exception{
|
||||||
int filesPerPart = totalFiles / NUMBER_OF_PARTS;
|
List<CardRules> res = loadCardsInRangeFromZip(entries, from, till);
|
||||||
final List<Callable<List<CardRules>>> tasks = new ArrayList<Callable<List<CardRules>>>();
|
cdl.countDown();
|
||||||
for (int iPart = 0; iPart < NUMBER_OF_PARTS; iPart++) {
|
progressObserver.report(maxParts - (int)cdl.getCount(), maxParts);
|
||||||
final int from = iPart * filesPerPart;
|
return res;
|
||||||
final int till = iPart == NUMBER_OF_PARTS - 1 ? totalFiles : from + filesPerPart;
|
}
|
||||||
tasks.add(new Callable<List<CardRules>>() {
|
});
|
||||||
@Override
|
}
|
||||||
public List<CardRules> call() throws Exception{
|
return tasks;
|
||||||
List<CardRules> res = loadCardsInRange(allFiles, from, till);
|
}
|
||||||
if ( null != barProgress )
|
|
||||||
barProgress.increment();
|
private List<Callable<List<CardRules>>> makeTaskListForFiles(final List<File> allFiles, final CountDownLatch cdl) {
|
||||||
cdl.countDown();
|
int totalFiles = allFiles.size();
|
||||||
return res;
|
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++) {
|
||||||
return tasks;
|
final int from = iPart * filesPerPart;
|
||||||
}
|
final int till = iPart == maxParts - 1 ? totalFiles : from + filesPerPart;
|
||||||
|
tasks.add(new Callable<List<CardRules>>() {
|
||||||
/**
|
@Override
|
||||||
* TODO: Write javadoc for this method.
|
public List<CardRules> call() throws Exception{
|
||||||
* @param allFiles
|
List<CardRules> res = loadCardsInRange(allFiles, from, till);
|
||||||
* @param cardsfolder2
|
cdl.countDown();
|
||||||
*/
|
progressObserver.report(maxParts - (int)cdl.getCount(), maxParts);
|
||||||
private void fillFilesArray(List<File> allFiles, File startDir) {
|
return res;
|
||||||
String[] list = startDir.list();
|
}
|
||||||
for (String filename : list) {
|
});
|
||||||
File entry = new File(startDir, filename);
|
}
|
||||||
|
return tasks;
|
||||||
if (!entry.isDirectory()) {
|
}
|
||||||
if (entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION))
|
|
||||||
allFiles.add(entry);
|
public static List<File> collectCardFiles(List<File> accumulator, File startDir) {
|
||||||
continue;
|
String[] list = startDir.list();
|
||||||
}
|
for (String filename : list) {
|
||||||
if (filename.startsWith(".")) {
|
File entry = new File(startDir, filename);
|
||||||
continue;
|
|
||||||
}
|
if (!entry.isDirectory()) {
|
||||||
|
if (entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION))
|
||||||
fillFilesArray(allFiles, entry);
|
accumulator.add(entry);
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
|
if (filename.startsWith(".")) {
|
||||||
|
continue;
|
||||||
/**
|
}
|
||||||
* <p>
|
|
||||||
* load a card.
|
collectCardFiles(accumulator, entry);
|
||||||
* </p>
|
}
|
||||||
*
|
return accumulator;
|
||||||
* @param inputStream
|
}
|
||||||
* the stream from which to load the card's information
|
|
||||||
*
|
|
||||||
* @return the card loaded from the stream
|
private List<String> readScript(final InputStream inputStream) {
|
||||||
*/
|
return FileUtil.readAllLines(new InputStreamReader(inputStream, this.charset), true);
|
||||||
protected final CardRules loadCard(CardRulesReader reader, final InputStream inputStream) {
|
}
|
||||||
reader.reset();
|
|
||||||
|
/**
|
||||||
InputStreamReader isr = new InputStreamReader(inputStream, this.charset);
|
* Load a card from a txt file.
|
||||||
List<String> allLines = FileUtil.readAllLines(isr, true);
|
*
|
||||||
|
* @param pathToTxtFile
|
||||||
return reader.readCard(allLines);
|
* the full or relative path to the file to load
|
||||||
}
|
*
|
||||||
|
* @return a new Card instance
|
||||||
/**
|
*/
|
||||||
* Load a card from a txt file.
|
protected final CardRules loadCard(final CardRules.Reader reader, final File file) {
|
||||||
*
|
FileInputStream fileInputStream = null;
|
||||||
* @param pathToTxtFile
|
try {
|
||||||
* the full or relative path to the file to load
|
fileInputStream = new FileInputStream(file);
|
||||||
*
|
reader.reset();
|
||||||
* @return a new Card instance
|
List<String> lines = readScript(fileInputStream);
|
||||||
*/
|
CardRules rules = reader.readCard(lines);
|
||||||
protected final CardRules loadCard(final CardRulesReader reader, final File pathToTxtFile) {
|
if ( null != observer )
|
||||||
FileInputStream fileInputStream = null;
|
observer.cardLoaded(rules, lines, file);
|
||||||
try {
|
return rules;
|
||||||
fileInputStream = new FileInputStream(pathToTxtFile);
|
} catch (final FileNotFoundException ex) {
|
||||||
return this.loadCard(reader, fileInputStream);
|
throw new RuntimeException("CardReader : run error -- file not found: " + file.getPath(), ex);
|
||||||
} catch (final FileNotFoundException ex) {
|
} finally {
|
||||||
BugReporter.reportException(ex, "File \"%s\" exception", pathToTxtFile.getAbsolutePath());
|
try {
|
||||||
throw new RuntimeException("CardReader : run error -- file exception -- filename is "
|
fileInputStream.close();
|
||||||
+ pathToTxtFile.getPath(), ex);
|
} catch (final IOException ignored) {
|
||||||
} finally {
|
// 11:08
|
||||||
try {
|
// PM
|
||||||
fileInputStream.close();
|
}
|
||||||
} catch (final IOException ignored) {
|
}
|
||||||
// 11:08
|
}
|
||||||
// PM
|
|
||||||
}
|
/**
|
||||||
}
|
* Load a card from an entry in a zip file.
|
||||||
}
|
*
|
||||||
|
* @param entry
|
||||||
/**
|
* to load from
|
||||||
* Load a card from an entry in a zip file.
|
*
|
||||||
*
|
* @return a new Card instance
|
||||||
* @param entry
|
*/
|
||||||
* to load from
|
protected final CardRules loadCard(final CardRules.Reader rulesReader, final ZipEntry entry) {
|
||||||
*
|
InputStream zipInputStream = null;
|
||||||
* @return a new Card instance
|
try {
|
||||||
*/
|
zipInputStream = this.zip.getInputStream(entry);
|
||||||
protected final CardRules loadCard(final CardRulesReader rulesReader, final ZipEntry entry) {
|
rulesReader.reset();
|
||||||
InputStream zipInputStream = null;
|
CardRules rules = rulesReader.readCard(readScript(zipInputStream));
|
||||||
try {
|
|
||||||
zipInputStream = this.zip.getInputStream(entry);
|
return rules;
|
||||||
return this.loadCard(rulesReader, zipInputStream);
|
} catch (final IOException exn) {
|
||||||
} catch (final IOException exn) {
|
throw new RuntimeException(exn);
|
||||||
throw new RuntimeException(exn);
|
// PM
|
||||||
// PM
|
} finally {
|
||||||
} finally {
|
try {
|
||||||
try {
|
if (zipInputStream != null) {
|
||||||
if (zipInputStream != null) {
|
zipInputStream.close();
|
||||||
zipInputStream.close();
|
}
|
||||||
}
|
} catch (final IOException ignored) {
|
||||||
} catch (final IOException ignored) {
|
// 11:08
|
||||||
// 11:08
|
// PM
|
||||||
// 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.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.Singletons;
|
import forge.StaticData;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.item.IPaperCard;
|
import forge.item.IPaperCard;
|
||||||
import forge.item.PrintSheet;
|
import forge.item.SealedProduct;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,26 +50,15 @@ import forge.util.TextUtil;
|
|||||||
*/
|
*/
|
||||||
public class BoosterGenerator {
|
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 final static Map<String, PrintSheet> cachedSheets = new TreeMap<String, PrintSheet>(String.CASE_INSENSITIVE_ORDER);
|
||||||
private static final synchronized PrintSheet getPrintSheet(String key) {
|
private static final synchronized PrintSheet getPrintSheet(String key) {
|
||||||
if( !cachedSheets.containsKey(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);
|
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>();
|
List<PaperCard> result = new ArrayList<PaperCard>();
|
||||||
for(Pair<String, Integer> slot : booster.getSlots()) {
|
for(Pair<String, Integer> slot : booster.getSlots()) {
|
||||||
String slotType = slot.getLeft(); // add expansion symbol here?
|
String slotType = slot.getLeft(); // add expansion symbol here?
|
||||||
@@ -77,7 +66,7 @@ public class BoosterGenerator {
|
|||||||
|
|
||||||
String[] sType = TextUtil.splitWithParenthesis(slotType, ' ');
|
String[] sType = TextUtil.splitWithParenthesis(slotType, ' ');
|
||||||
String setCode = sType.length == 1 && booster.getEdition() != null ? booster.getEdition() : null;
|
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);
|
PrintSheet ps = getPrintSheet(sheetKey);
|
||||||
result.addAll(ps.random(numCards, true));
|
result.addAll(ps.random(numCards, true));
|
||||||
@@ -100,7 +89,7 @@ public class BoosterGenerator {
|
|||||||
String mainCode = itMod.next();
|
String mainCode = itMod.next();
|
||||||
if ( mainCode.regionMatches(true, 0, "fromSheet", 0, 9)) { // custom print sheet
|
if ( mainCode.regionMatches(true, 0, "fromSheet", 0, 9)) { // custom print sheet
|
||||||
String sheetName = StringUtils.strip(mainCode.substring(9), "()\" ");
|
String sheetName = StringUtils.strip(mainCode.substring(9), "()\" ");
|
||||||
src = Singletons.getModel().getPrintSheets().get(sheetName).toFlatList();
|
src = StaticData.instance().getPrintSheets().get(sheetName).toFlatList();
|
||||||
setPred = Predicates.alwaysTrue();
|
setPred = Predicates.alwaysTrue();
|
||||||
|
|
||||||
} else if (mainCode.startsWith("promo")) { // get exactly the named cards, that's a tiny inlined print sheet
|
} 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, ',', '"', '"');
|
String[] cardNames = TextUtil.splitWithParenthesis(list, ',', '"', '"');
|
||||||
List<PaperCard> srcList = new ArrayList<PaperCard>();
|
List<PaperCard> srcList = new ArrayList<PaperCard>();
|
||||||
for(String cardName: cardNames)
|
for(String cardName: cardNames)
|
||||||
srcList.add(CardDb.instance().getCard(cardName));
|
srcList.add(StaticData.instance().getCommonCards().getCard(cardName));
|
||||||
src = srcList;
|
src = srcList;
|
||||||
setPred = Predicates.alwaysTrue();
|
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
|
// 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();
|
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);
|
Predicate<PaperCard> predicate = Predicates.and(setPred, extraPred);
|
||||||
ps.addAll(Iterables.filter(src, predicate));
|
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);
|
Predicate<PaperCard> predicateRares = Predicates.and(setPred, IPaperCard.Predicates.Presets.IS_RARE, extraPred);
|
||||||
ps.addAll(Iterables.filter(src, predicateRares));
|
ps.addAll(Iterables.filter(src, predicateRares));
|
||||||
|
|
||||||
Predicate<PaperCard> predicateUncommon = Predicates.and( setPred, IPaperCard.Predicates.Presets.IS_UNCOMMON, extraPred);
|
Predicate<PaperCard> predicateUncommon = Predicates.and( setPred, IPaperCard.Predicates.Presets.IS_UNCOMMON, extraPred);
|
||||||
ps.addAll(Iterables.filter(src, predicateUncommon), 3);
|
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.
|
// 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.
|
// 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;
|
Predicate<PaperCard> toAdd = null;
|
||||||
if( operator.equalsIgnoreCase("dfc") ) { toAdd = Predicates.compose(CardRulesPredicates.splitType(CardSplitType.Transform), PaperCard.FN_GET_RULES);
|
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(BoosterSlots.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(BoosterSlots.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(BoosterSlots.TIME_SHIFTED)) { toAdd = IPaperCard.Predicates.Presets.IS_SPECIAL;
|
||||||
} else if ( operator.equalsIgnoreCase(MYTHIC)) { toAdd = IPaperCard.Predicates.Presets.IS_MYTHIC_RARE;
|
} else if ( operator.equalsIgnoreCase(BoosterSlots.MYTHIC)) { toAdd = IPaperCard.Predicates.Presets.IS_MYTHIC_RARE;
|
||||||
} else if ( operator.equalsIgnoreCase(RARE)) { toAdd = IPaperCard.Predicates.Presets.IS_RARE;
|
} else if ( operator.equalsIgnoreCase(BoosterSlots.RARE)) { toAdd = IPaperCard.Predicates.Presets.IS_RARE;
|
||||||
} else if ( operator.equalsIgnoreCase(UNCOMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_UNCOMMON;
|
} else if ( operator.equalsIgnoreCase(BoosterSlots.UNCOMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_UNCOMMON;
|
||||||
} else if ( operator.equalsIgnoreCase(COMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_COMMON;
|
} else if ( operator.equalsIgnoreCase(BoosterSlots.COMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_COMMON;
|
||||||
} else if ( operator.startsWith("name(") ) {
|
} else if ( operator.startsWith("name(") ) {
|
||||||
operator = StringUtils.strip(operator.substring(4), "() ");
|
operator = StringUtils.strip(operator.substring(4), "() ");
|
||||||
String[] cardNames = TextUtil.splitWithParenthesis(operator, ',', '"', '"');
|
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.
|
* TODO: Write javadoc for this type.
|
||||||
@@ -21,6 +21,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@@ -29,6 +30,7 @@ import java.util.TreeMap;
|
|||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
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.Multimap;
|
||||||
import com.google.common.collect.Multimaps;
|
import com.google.common.collect.Multimaps;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.card.CardEdition.CardInSet;
|
||||||
import forge.card.CardEdition.Type;
|
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
|
import forge.util.CollectionSuppliers;
|
||||||
import forge.util.Lang;
|
import forge.util.Lang;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
import forge.util.maps.CollectionSuppliers;
|
|
||||||
|
|
||||||
public final class CardDb implements ICardDatabase {
|
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 = "+";
|
public final static String foilSuffix = "+";
|
||||||
private final static int foilSuffixLength = foilSuffix.length();
|
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
|
// 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, PaperCard> uniqueCardsByName = new TreeMap<String, PaperCard>(String.CASE_INSENSITIVE_ORDER);
|
||||||
private final Map<String, CardRules> rulesByName;
|
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.rulesByName = rules;
|
||||||
this.editions = editions0;
|
this.editions = editions0;
|
||||||
List<String> missingCards = new ArrayList<String>();
|
List<String> missingCards = new ArrayList<String>();
|
||||||
for(CardEdition e : editions.getOrderedEditions()) {
|
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)
|
if(worthLogging)
|
||||||
System.out.print(e.getName() + " (" + e.getCards().length + " cards)");
|
System.out.print(e.getName() + " (" + e.getCards().length + " cards)");
|
||||||
String lastCardName = null;
|
String lastCardName = null;
|
||||||
int artIdx = 0;
|
int artIdx = 0;
|
||||||
for(CardEdition.CardInSet cis : e.getCards()) {
|
for(CardEdition.CardInSet cis : e.getCards()) {
|
||||||
if ( cis.name.equals(lastCardName) )
|
if ( cis.name.equals(lastCardName) )
|
||||||
artIdx++;
|
artIdx++;
|
||||||
else {
|
else {
|
||||||
artIdx = 0;
|
artIdx = 0;
|
||||||
lastCardName = cis.name;
|
lastCardName = cis.name;
|
||||||
}
|
}
|
||||||
CardRules cr = rulesByName.get(lastCardName);
|
CardRules cr = rulesByName.get(lastCardName);
|
||||||
if( cr != null )
|
if( cr != null )
|
||||||
addCard(new PaperCard(cr, e.getCode(), cis.rarity, artIdx));
|
addCard(new PaperCard(cr, e.getCode(), cis.rarity, artIdx));
|
||||||
else if (worthLogging)
|
else if (worthLogging)
|
||||||
missingCards.add(cis.name);
|
missingCards.add(cis.name);
|
||||||
@@ -121,7 +92,7 @@ public final class CardDb implements ICardDatabase {
|
|||||||
missingCards.clear();
|
missingCards.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(CardRules cr : rulesByName.values()) {
|
for(CardRules cr : rulesByName.values()) {
|
||||||
if( !allCardsByName.containsKey(cr.getName()) )
|
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));
|
addCard(new PaperCard(cr, CardEdition.UNKNOWN.getCode(), CardRarity.Special, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reIndex();
|
reIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +153,7 @@ public final class CardDb implements ICardDatabase {
|
|||||||
public PaperCard tryGetCard(final String cardName0) {
|
public PaperCard tryGetCard(final String cardName0) {
|
||||||
return tryGetCard(cardName0, true);
|
return tryGetCard(cardName0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PaperCard tryGetCard(final String cardName0, boolean fromLastSet) {
|
public PaperCard tryGetCard(final String cardName0, boolean fromLastSet) {
|
||||||
if (null == cardName0) {
|
if (null == cardName0) {
|
||||||
@@ -191,23 +162,23 @@ public final class CardDb implements ICardDatabase {
|
|||||||
|
|
||||||
final boolean isFoil = this.isFoil(cardName0);
|
final boolean isFoil = this.isFoil(cardName0);
|
||||||
final String cardName = isFoil ? this.removeFoilSuffix(cardName0) : cardName0;
|
final String cardName = isFoil ? this.removeFoilSuffix(cardName0) : cardName0;
|
||||||
|
|
||||||
final ImmutablePair<String, String> nameWithSet = CardDb.splitCardName(cardName);
|
final ImmutablePair<String, String> nameWithSet = CardDb.splitCardName(cardName);
|
||||||
|
|
||||||
final PaperCard res = nameWithSet.right == null
|
final PaperCard res = nameWithSet.right == null
|
||||||
? ( fromLastSet ? this.uniqueCardsByName.get(nameWithSet.left) : Aggregates.random(this.allCardsByName.get(nameWithSet.left)) )
|
? ( fromLastSet ? this.uniqueCardsByName.get(nameWithSet.left) : Aggregates.random(this.allCardsByName.get(nameWithSet.left)) )
|
||||||
: tryGetCard(nameWithSet.left, nameWithSet.right);
|
: tryGetCard(nameWithSet.left, nameWithSet.right);
|
||||||
return null != res && isFoil ? getFoiled(res) : res;
|
return null != res && isFoil ? getFoiled(res) : res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PaperCard tryGetCardPrintedByDate(final String name0, final boolean fromLatestSet, final Date printedBefore) {
|
public PaperCard tryGetCardPrintedByDate(final String name0, final boolean fromLatestSet, final Date printedBefore) {
|
||||||
final boolean isFoil = this.isFoil(name0);
|
final boolean isFoil = this.isFoil(name0);
|
||||||
final String cardName = isFoil ? this.removeFoilSuffix(name0) : name0;
|
final String cardName = isFoil ? this.removeFoilSuffix(name0) : name0;
|
||||||
final ImmutablePair<String, String> nameWithSet = CardDb.splitCardName(cardName);
|
final ImmutablePair<String, String> nameWithSet = CardDb.splitCardName(cardName);
|
||||||
|
|
||||||
PaperCard res = null;
|
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);
|
res = tryGetCard(nameWithSet.left, nameWithSet.right);
|
||||||
else {
|
else {
|
||||||
Collection<PaperCard> cards = this.allCardsByName.get(nameWithSet.left); // cards are sorted by datetime desc
|
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;
|
return null != res && isFoil ? getFoiled(res) : res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PaperCard tryGetCard(final String cardName, String setName) {
|
public PaperCard tryGetCard(final String cardName, String setName) {
|
||||||
return tryGetCard(cardName, setName, -1);
|
return tryGetCard(cardName, setName, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PaperCard tryGetCard(final String cardName0, String setName, int index) {
|
public PaperCard tryGetCard(final String cardName0, String setName, int index) {
|
||||||
final boolean isFoil = this.isFoil(cardName0);
|
final boolean isFoil = this.isFoil(cardName0);
|
||||||
@@ -239,7 +209,7 @@ public final class CardDb implements ICardDatabase {
|
|||||||
if ( null == cards ) return null;
|
if ( null == cards ) return null;
|
||||||
|
|
||||||
CardEdition edition = editions.get(setName);
|
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.
|
return tryGetCard(cardName, true); // set not found, try to get the same card from just any set.
|
||||||
String effectiveSet = edition.getCode();
|
String effectiveSet = edition.getCode();
|
||||||
|
|
||||||
@@ -254,7 +224,7 @@ public final class CardDb implements ICardDatabase {
|
|||||||
|
|
||||||
if (cnt == 0 ) return null;
|
if (cnt == 0 ) return null;
|
||||||
result = cnt == 1 ? candidates[0] : candidates[MyRandom.getRandom().nextInt(cnt)];
|
result = cnt == 1 ? candidates[0] : candidates[MyRandom.getRandom().nextInt(cnt)];
|
||||||
} else
|
} else
|
||||||
for( PaperCard pc : cards ) {
|
for( PaperCard pc : cards ) {
|
||||||
if( pc.getEdition().equalsIgnoreCase(effectiveSet) && index == pc.getArtIndex() ) {
|
if( pc.getEdition().equalsIgnoreCase(effectiveSet) && index == pc.getArtIndex() ) {
|
||||||
result = pc;
|
result = pc;
|
||||||
@@ -264,7 +234,7 @@ public final class CardDb implements ICardDatabase {
|
|||||||
if ( result == null ) return null;
|
if ( result == null ) return null;
|
||||||
return isFoil ? getFoiled(result) : result;
|
return isFoil ? getFoiled(result) : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PaperCard getFoiled(PaperCard card0) {
|
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
|
// 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);
|
return new PaperCard(card0.getRules(), card0.getEdition(), card0.getRarity(), card0.getArtIndex(), true);
|
||||||
@@ -279,17 +249,17 @@ public final class CardDb implements ICardDatabase {
|
|||||||
}
|
}
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxPrintCount(String cardName) {
|
public int getMaxPrintCount(String cardName) {
|
||||||
int max = -1;
|
int max = -1;
|
||||||
for( PaperCard pc : allCardsByName.get(cardName) ) {
|
for( PaperCard pc : allCardsByName.get(cardName) ) {
|
||||||
if ( max < pc.getArtIndex() )
|
if ( max < pc.getArtIndex() )
|
||||||
max = pc.getArtIndex();
|
max = pc.getArtIndex();
|
||||||
}
|
}
|
||||||
return max + 1;
|
return max + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single fetch
|
// Single fetch
|
||||||
@Override
|
@Override
|
||||||
public PaperCard getCard(final String name) {
|
public PaperCard getCard(final String name) {
|
||||||
@@ -306,8 +276,7 @@ public final class CardDb implements ICardDatabase {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PaperCard getCardPrintedByDate(final String name0, final boolean fromLatestSet, Date printedBefore ) {
|
public PaperCard getCardPrintedByDate(final String name0, final boolean fromLatestSet, Date printedBefore ) {
|
||||||
// Sometimes they read from decks things like "CardName|Set" - but we
|
// 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()));
|
throw new NoSuchElementException(String.format("Card '%s' released before %s not found in our database.", name0, printedBefore.toString()));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advanced fetch by name+set
|
// Advanced fetch by name+set
|
||||||
@Override
|
@Override
|
||||||
public PaperCard getCard(final String name, final String set) {
|
public PaperCard getCard(final String name, final String set) {
|
||||||
@@ -327,7 +296,6 @@ public final class CardDb implements ICardDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PaperCard getCard(final String name, final String set, final int artIndex) {
|
public PaperCard getCard(final String name, final String set, final int artIndex) {
|
||||||
|
|
||||||
final PaperCard result = tryGetCard(name, set, artIndex);
|
final PaperCard result = tryGetCard(name, set, artIndex);
|
||||||
if (null == result) {
|
if (null == result) {
|
||||||
final String message = String.format("Asked for '%s' from '%s' #%d: db didn't find that copy.", name, set, artIndex);
|
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;
|
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
|
// returns a list of all cards from their respective latest editions
|
||||||
@Override
|
@Override
|
||||||
public Collection<PaperCard> getUniqueCards() {
|
public Collection<PaperCard> getUniqueCards() {
|
||||||
@@ -368,29 +321,15 @@ public final class CardDb implements ICardDatabase {
|
|||||||
return Lists.newArrayList(Iterables.filter(this.roAllCards, predicate));
|
return Lists.newArrayList(Iterables.filter(this.roAllCards, predicate));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CardSorter{
|
@Override
|
||||||
// Here are refs, get them by name
|
public Iterator<PaperCard> iterator() {
|
||||||
public final Map<String, CardRules> regularCards = new TreeMap<String, CardRules>(String.CASE_INSENSITIVE_ORDER);
|
return this.roAllCards.iterator();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Predicate<? super PaperCard> wasPrintedInSets(List<String> setCodes) {
|
public Predicate<? super PaperCard> wasPrintedInSets(List<String> setCodes) {
|
||||||
return new PredicateExistsInSets(setCodes);
|
return new PredicateExistsInSets(setCodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PredicateExistsInSets implements Predicate<PaperCard> {
|
private class PredicateExistsInSets implements Predicate<PaperCard> {
|
||||||
private final List<String> sets;
|
private final List<String> sets;
|
||||||
|
|
||||||
@@ -401,9 +340,84 @@ public final class CardDb implements ICardDatabase {
|
|||||||
@Override
|
@Override
|
||||||
public boolean apply(final PaperCard subject) {
|
public boolean apply(final PaperCard subject) {
|
||||||
Collection<PaperCard> cc = allCardsByName.get(subject.getName());
|
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;
|
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.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.Constant;
|
import forge.StaticData;
|
||||||
import forge.Singletons;
|
import forge.item.SealedProduct;
|
||||||
import forge.game.GameFormat;
|
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
import forge.util.FileSection;
|
import forge.util.FileSection;
|
||||||
import forge.util.FileUtil;
|
import forge.util.FileUtil;
|
||||||
|
import forge.util.IItemReader;
|
||||||
|
import forge.util.storage.StorageBase;
|
||||||
|
import forge.util.storage.StorageReaderBase;
|
||||||
import forge.util.storage.StorageReaderFolder;
|
import forge.util.storage.StorageReaderFolder;
|
||||||
|
|
||||||
|
|
||||||
@@ -104,7 +110,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
|
|||||||
|
|
||||||
|
|
||||||
private int boosterArts = 1;
|
private int boosterArts = 1;
|
||||||
private SealedProductTemplate boosterTpl = null;
|
private SealedProduct.Template boosterTpl = null;
|
||||||
|
|
||||||
private CardEdition(CardInSet[] cards) {
|
private CardEdition(CardInSet[] cards) {
|
||||||
this.cards = cards;
|
this.cards = cards;
|
||||||
@@ -204,76 +210,20 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
|
|||||||
return whiteBorder;
|
return whiteBorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getCntBoosterPictures() {
|
||||||
/**
|
return boosterArts;
|
||||||
* 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 static class EditionReader extends StorageReaderFolder<CardEdition> {
|
public SealedProduct.Template getBoosterTemplate() {
|
||||||
public EditionReader(File path) {
|
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);
|
super(path, CardEdition.FN_GET_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +259,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
|
|||||||
|
|
||||||
res.boosterArts = section.getInt("BoosterCovers", 1);
|
res.boosterArts = section.getInt("BoosterCovers", 1);
|
||||||
String boosterDesc = section.get("Booster");
|
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.alias = section.get("alias");
|
||||||
res.whiteBorder = "white".equalsIgnoreCase(section.get("border"));
|
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() {
|
public static class Collection extends StorageBase<CardEdition> {
|
||||||
return boosterArts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SealedProductTemplate getBoosterTemplate() {
|
private final Map<String, CardEdition> aliasToEdition = new TreeMap<String, CardEdition>(String.CASE_INSENSITIVE_ORDER);
|
||||||
return boosterTpl;
|
|
||||||
|
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 {
|
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 List<String> emptyList = Collections.unmodifiableList(new ArrayList<String>());
|
||||||
private final static Map<String, String> emptyMap = Collections.unmodifiableMap(new TreeMap<String, String>());
|
private final static Map<String, String> emptyMap = Collections.unmodifiableMap(new TreeMap<String, String>());
|
||||||
|
|
||||||
@@ -74,13 +81,13 @@ final class CardFace implements ICardFace {
|
|||||||
throw new RuntimeException("Card name is empty");
|
throw new RuntimeException("Card name is empty");
|
||||||
}
|
}
|
||||||
// Here come setters to allow parser supply values
|
// Here come setters to allow parser supply values
|
||||||
public void setType(CardType type0) { this.type = type0; }
|
void setType(CardType type0) { this.type = type0; }
|
||||||
public void setManaCost(ManaCost manaCost0) { this.manaCost = manaCost0; }
|
void setManaCost(ManaCost manaCost0) { this.manaCost = manaCost0; }
|
||||||
public void setColor(ColorSet color0) { this.color = color0; }
|
void setColor(ColorSet color0) { this.color = color0; }
|
||||||
public void setOracleText(String text) { this.oracleText = text; }
|
void setOracleText(String text) { this.oracleText = text; }
|
||||||
public void setInitialLoyalty(int value) { this.initialLoyalty = value; }
|
void setInitialLoyalty(int value) { this.initialLoyalty = value; }
|
||||||
|
|
||||||
public void setPtText(String value) {
|
void setPtText(String value) {
|
||||||
final int slashPos = value.indexOf('/');
|
final int slashPos = value.indexOf('/');
|
||||||
if (slashPos == -1) {
|
if (slashPos == -1) {
|
||||||
throw new RuntimeException(String.format("Creature '%s' has bad p/t stats", this.getName()));
|
throw new RuntimeException(String.format("Creature '%s' has bad p/t stats", this.getName()));
|
||||||
@@ -92,16 +99,16 @@ final class CardFace implements ICardFace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Raw fields used for Card creation
|
// Raw fields used for Card creation
|
||||||
public void setNonAbilityText(String value) { this.nonAbilityText = value; }
|
void setNonAbilityText(String value) { this.nonAbilityText = value; }
|
||||||
public void addKeyword(String value) { if (null == this.keywords) { this.keywords = new ArrayList<String>(); } this.keywords.add(value); }
|
void addKeyword(String value) { if (null == this.keywords) { this.keywords = new ArrayList<String>(); } this.keywords.add(value); }
|
||||||
public void addAbility(String value) { if (null == this.abilities) { this.abilities = new ArrayList<String>(); } this.abilities.add(value);}
|
void addAbility(String value) { if (null == this.abilities) { this.abilities = new ArrayList<String>(); } this.abilities.add(value);}
|
||||||
public void addTrigger(String value) { if (null == this.triggers) { this.triggers = new ArrayList<String>(); } this.triggers.add(value);}
|
void addTrigger(String value) { if (null == this.triggers) { this.triggers = new ArrayList<String>(); } this.triggers.add(value);}
|
||||||
public void addStaticAbility(String value) { if (null == this.staticAbilities) { this.staticAbilities = new ArrayList<String>(); } this.staticAbilities.add(value);}
|
void addStaticAbility(String value) { if (null == this.staticAbilities) { this.staticAbilities = new ArrayList<String>(); } this.staticAbilities.add(value);}
|
||||||
public void addReplacementEffect(String value) { if (null == this.replacements) { this.replacements = new ArrayList<String>(); } this.replacements.add(value);}
|
void addReplacementEffect(String value) { if (null == this.replacements) { this.replacements = new ArrayList<String>(); } this.replacements.add(value);}
|
||||||
public void addSVar(String key, String value) { if (null == this.variables) { this.variables = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER); } this.variables.put(key, value); }
|
void addSVar(String key, String value) { if (null == this.variables) { this.variables = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER); } this.variables.put(key, value); }
|
||||||
|
|
||||||
|
|
||||||
public void assignMissingFields() { // Most scripts do not specify color explicitly
|
void assignMissingFields() { // Most scripts do not specify color explicitly
|
||||||
if ( null == oracleText ) { System.err.println(name + " has no Oracle text."); oracleText = ""; }
|
if ( null == oracleText ) { System.err.println(name + " has no Oracle text."); oracleText = ""; }
|
||||||
if ( manaCost == null && color == null ) System.err.println(name + " has neither ManaCost nor Color");
|
if ( manaCost == null && color == null ) System.err.println(name + " has neither ManaCost nor Color");
|
||||||
if ( color == null ) color = ColorSet.fromManaCost(manaCost);
|
if ( color == null ) color = ColorSet.fromManaCost(manaCost);
|
||||||
493
forge-core/src/main/java/forge/card/CardRules.java
Normal file
493
forge-core/src/main/java/forge/card/CardRules.java
Normal file
@@ -0,0 +1,493 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canCastFace(ICardFace face, byte colorCode) {
|
||||||
|
if (face.getManaCost().isNoCost()) {
|
||||||
|
//if card face has no cost, assume castable only by mana of its defined color
|
||||||
|
return face.getColor().hasNoColorsExcept(colorCode);
|
||||||
|
}
|
||||||
|
return face.getManaCost().canBePaidWithAvaliable(colorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canCastWithAvailable(byte colorCode) {
|
||||||
|
switch(splitType.getAggregationMethod()) {
|
||||||
|
case COMBINE:
|
||||||
|
return canCastFace(mainPart, colorCode) || canCastFace(otherPart, colorCode);
|
||||||
|
default:
|
||||||
|
return canCastFace(mainPart, colorCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import java.util.List;
|
|||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
import forge.util.ComparableOp;
|
import forge.util.ComparableOp;
|
||||||
import forge.util.PredicateString;
|
import forge.util.PredicateString;
|
||||||
|
|
||||||
@@ -170,7 +171,7 @@ public final class CardRulesPredicates {
|
|||||||
*/
|
*/
|
||||||
public static Predicate<CardRules> coreType(final boolean isEqual, final String what) {
|
public static Predicate<CardRules> coreType(final boolean isEqual, final String what) {
|
||||||
try {
|
try {
|
||||||
return CardRulesPredicates.coreType(isEqual, Enum.valueOf(CardCoreType.class, what));
|
return CardRulesPredicates.coreType(isEqual, Enum.valueOf(CardType.CoreType.class, what));
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
return com.google.common.base.Predicates.alwaysFalse();
|
return com.google.common.base.Predicates.alwaysFalse();
|
||||||
}
|
}
|
||||||
@@ -185,7 +186,7 @@ public final class CardRulesPredicates {
|
|||||||
* the type
|
* the type
|
||||||
* @return the predicate
|
* @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);
|
return new PredicateCoreType(type, isEqual);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +201,7 @@ public final class CardRulesPredicates {
|
|||||||
*/
|
*/
|
||||||
public static Predicate<CardRules> superType(final boolean isEqual, final String what) {
|
public static Predicate<CardRules> superType(final boolean isEqual, final String what) {
|
||||||
try {
|
try {
|
||||||
return CardRulesPredicates.superType(isEqual, Enum.valueOf(CardSuperType.class, what));
|
return CardRulesPredicates.superType(isEqual, Enum.valueOf(CardType.SuperType.class, what));
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
return com.google.common.base.Predicates.alwaysFalse();
|
return com.google.common.base.Predicates.alwaysFalse();
|
||||||
}
|
}
|
||||||
@@ -215,7 +216,7 @@ public final class CardRulesPredicates {
|
|||||||
* the type
|
* the type
|
||||||
* @return the predicate
|
* @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);
|
return new PredicateSuperType(type, isEqual);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +225,7 @@ public final class CardRulesPredicates {
|
|||||||
* Checks for color.
|
* Checks for color.
|
||||||
*
|
*
|
||||||
* @param thatColor
|
* @param thatColor
|
||||||
* the that color
|
* color to check
|
||||||
* @return the predicate
|
* @return the predicate
|
||||||
*/
|
*/
|
||||||
public static Predicate<CardRules> hasColor(final byte thatColor) {
|
public static Predicate<CardRules> hasColor(final byte thatColor) {
|
||||||
@@ -235,13 +236,24 @@ public final class CardRulesPredicates {
|
|||||||
* Checks if is color.
|
* Checks if is color.
|
||||||
*
|
*
|
||||||
* @param thatColor
|
* @param thatColor
|
||||||
* the that color
|
* color to check
|
||||||
* @return the predicate
|
* @return the predicate
|
||||||
*/
|
*/
|
||||||
public static Predicate<CardRules> isColor(final byte thatColor) {
|
public static Predicate<CardRules> isColor(final byte thatColor) {
|
||||||
return new LeafColor(LeafColor.ColorOperator.HasAnyOf, thatColor);
|
return new LeafColor(LeafColor.ColorOperator.HasAnyOf, thatColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if card can be cast with unlimited mana of given color set.
|
||||||
|
*
|
||||||
|
* @param thatColor
|
||||||
|
* color to check
|
||||||
|
* @return the predicate
|
||||||
|
*/
|
||||||
|
public static Predicate<CardRules> canCastWithAvailable(final byte thatColor) {
|
||||||
|
return new LeafColor(LeafColor.ColorOperator.CanCast, thatColor);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if is exactly that color.
|
* Checks if is exactly that color.
|
||||||
*
|
*
|
||||||
@@ -310,7 +322,7 @@ public final class CardRulesPredicates {
|
|||||||
|
|
||||||
private static class LeafColor implements Predicate<CardRules> {
|
private static class LeafColor implements Predicate<CardRules> {
|
||||||
public enum ColorOperator {
|
public enum ColorOperator {
|
||||||
CountColors, CountColorsGreaterOrEqual, HasAnyOf, HasAllOf, Equals
|
CountColors, CountColorsGreaterOrEqual, HasAnyOf, HasAllOf, Equals, CanCast
|
||||||
}
|
}
|
||||||
|
|
||||||
private final LeafColor.ColorOperator op;
|
private final LeafColor.ColorOperator op;
|
||||||
@@ -337,6 +349,8 @@ public final class CardRulesPredicates {
|
|||||||
return subject.getColor().hasAllColors(this.color);
|
return subject.getColor().hasAllColors(this.color);
|
||||||
case HasAnyOf:
|
case HasAnyOf:
|
||||||
return subject.getColor().hasAnyColor(this.color);
|
return subject.getColor().hasAnyColor(this.color);
|
||||||
|
case CanCast:
|
||||||
|
return subject.canCastWithAvailable(this.color);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -396,7 +410,7 @@ public final class CardRulesPredicates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class PredicateCoreType implements Predicate<CardRules> {
|
private static class PredicateCoreType implements Predicate<CardRules> {
|
||||||
private final CardCoreType operand;
|
private final CardType.CoreType operand;
|
||||||
private final boolean shouldBeEqual;
|
private final boolean shouldBeEqual;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -407,14 +421,14 @@ public final class CardRulesPredicates {
|
|||||||
return this.shouldBeEqual == card.getType().typeContains(this.operand);
|
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.operand = type;
|
||||||
this.shouldBeEqual = wantEqual;
|
this.shouldBeEqual = wantEqual;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class PredicateSuperType implements Predicate<CardRules> {
|
private static class PredicateSuperType implements Predicate<CardRules> {
|
||||||
private final CardSuperType operand;
|
private final CardType.SuperType operand;
|
||||||
private final boolean shouldBeEqual;
|
private final boolean shouldBeEqual;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -422,7 +436,7 @@ public final class CardRulesPredicates {
|
|||||||
return this.shouldBeEqual == card.getType().superTypeContains(this.operand);
|
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.operand = type;
|
||||||
this.shouldBeEqual = wantEqual;
|
this.shouldBeEqual = wantEqual;
|
||||||
}
|
}
|
||||||
@@ -448,21 +462,21 @@ public final class CardRulesPredicates {
|
|||||||
|
|
||||||
/** The Constant isCreature. */
|
/** The Constant isCreature. */
|
||||||
public static final Predicate<CardRules> IS_CREATURE = CardRulesPredicates
|
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
|
public static final Predicate<CardRules> IS_LEGENDARY = CardRulesPredicates
|
||||||
.superType(true, CardSuperType.Legendary);
|
.superType(true, CardType.SuperType.Legendary);
|
||||||
|
|
||||||
/** The Constant isArtifact. */
|
/** The Constant isArtifact. */
|
||||||
public static final Predicate<CardRules> IS_ARTIFACT = CardRulesPredicates
|
public static final Predicate<CardRules> IS_ARTIFACT = CardRulesPredicates
|
||||||
.coreType(true, CardCoreType.Artifact);
|
.coreType(true, CardType.CoreType.Artifact);
|
||||||
|
|
||||||
/** The Constant isEquipment. */
|
/** The Constant isEquipment. */
|
||||||
public static final Predicate<CardRules> IS_EQUIPMENT = CardRulesPredicates
|
public static final Predicate<CardRules> IS_EQUIPMENT = CardRulesPredicates
|
||||||
.subType("Equipment");
|
.subType("Equipment");
|
||||||
|
|
||||||
/** The Constant isLand. */
|
/** 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. */
|
/** The Constant isBasicLand. */
|
||||||
public static final Predicate<CardRules> IS_BASIC_LAND = new Predicate<CardRules>() {
|
public static final Predicate<CardRules> IS_BASIC_LAND = new Predicate<CardRules>() {
|
||||||
@@ -480,31 +494,17 @@ public final class CardRulesPredicates {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The Constant isPlaneswalker. */
|
public static final Predicate<CardRules> IS_PLANESWALKER = CardRulesPredicates.coreType(true, CardType.CoreType.Planeswalker);
|
||||||
public static final Predicate<CardRules> IS_PLANESWALKER = CardRulesPredicates.coreType(true,
|
public static final Predicate<CardRules> IS_INSTANT = CardRulesPredicates.coreType(true, CardType.CoreType.Instant);
|
||||||
CardCoreType.Planeswalker);
|
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);
|
||||||
/** The Constant isInstant. */
|
public static final Predicate<CardRules> IS_PLANE = CardRulesPredicates.coreType(true, CardType.CoreType.Plane);
|
||||||
public static final Predicate<CardRules> IS_INSTANT = CardRulesPredicates.coreType(true, CardCoreType.Instant);
|
public static final Predicate<CardRules> IS_PHENOMENON = CardRulesPredicates.coreType(true, CardType.CoreType.Phenomenon);
|
||||||
|
|
||||||
/** 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_PLANE_OR_PHENOMENON = Predicates.or(IS_PLANE, IS_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_SCHEME = CardRulesPredicates.coreType(true, CardType.CoreType.Scheme);
|
||||||
public static final Predicate<CardRules> IS_VANGUARD = CardRulesPredicates.coreType(true, CardCoreType.Vanguard);
|
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);
|
||||||
/** The Constant isNonLand. */
|
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_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));
|
|
||||||
|
|
||||||
/** The Constant IS_NONCREATURE_SPELL_FOR_GENERATOR. **/
|
/** The Constant IS_NONCREATURE_SPELL_FOR_GENERATOR. **/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -532,7 +532,8 @@ public final class CardRulesPredicates {
|
|||||||
|
|
||||||
/** The Constant isMulticolor. */
|
/** The Constant isMulticolor. */
|
||||||
public static final Predicate<CardRules> IS_MULTICOLOR = CardRulesPredicates.hasAtLeastCntColors((byte) 2);
|
public static final Predicate<CardRules> IS_MULTICOLOR = CardRulesPredicates.hasAtLeastCntColors((byte) 2);
|
||||||
|
|
||||||
|
/** The Constant isMonocolor. */
|
||||||
public static final Predicate<CardRules> IS_MONOCOLOR = CardRulesPredicates.hasCntColors((byte) 1);
|
public static final Predicate<CardRules> IS_MONOCOLOR = CardRulesPredicates.hasCntColors((byte) 1);
|
||||||
|
|
||||||
/** The Constant colors. */
|
/** The Constant colors. */
|
||||||
@@ -1,26 +1,26 @@
|
|||||||
package forge.card;
|
package forge.card;
|
||||||
|
|
||||||
import forge.CardCharacteristicName;
|
import forge.card.CardFace.FaceSelectionMethod;
|
||||||
|
|
||||||
public enum CardSplitType
|
public enum CardSplitType
|
||||||
{
|
{
|
||||||
None(AggregationMethod.USE_PRIMARY_FACE, null),
|
None(FaceSelectionMethod.USE_PRIMARY_FACE, null),
|
||||||
Transform(AggregationMethod.USE_ACTIVE_FACE, CardCharacteristicName.Transformed),
|
Transform(FaceSelectionMethod.USE_ACTIVE_FACE, CardCharacteristicName.Transformed),
|
||||||
Split(AggregationMethod.AGGREGATE, CardCharacteristicName.RightSplit),
|
Split(FaceSelectionMethod.COMBINE, CardCharacteristicName.RightSplit),
|
||||||
Flip(AggregationMethod.USE_PRIMARY_FACE, CardCharacteristicName.Flipped),
|
Flip(FaceSelectionMethod.USE_PRIMARY_FACE, CardCharacteristicName.Flipped),
|
||||||
// used by 12 licid creatures to switch type into enchantment aura
|
// 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;
|
method = calcMode;
|
||||||
this.changedStateName = stateName;
|
this.changedStateName = stateName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AggregationMethod getAggregationMethod() {
|
public FaceSelectionMethod getAggregationMethod() {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final AggregationMethod method;
|
private final FaceSelectionMethod method;
|
||||||
private final CardCharacteristicName changedStateName;
|
private final CardCharacteristicName changedStateName;
|
||||||
|
|
||||||
public static CardSplitType smartValueOf(String text) {
|
public static CardSplitType smartValueOf(String text) {
|
||||||
@@ -24,8 +24,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import forge.Constant;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Immutable Card type. Can be build only from parsing a string.
|
* 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 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 List<String> subType = new ArrayList<String>();
|
||||||
private final EnumSet<CardCoreType> coreType = EnumSet.noneOf(CardCoreType.class);
|
private final EnumSet<CardType.CoreType> coreType = EnumSet.noneOf(CardType.CoreType.class);
|
||||||
private final EnumSet<CardSuperType> superType = EnumSet.noneOf(CardSuperType.class);
|
private final EnumSet<CardType.SuperType> superType = EnumSet.noneOf(CardType.SuperType.class);
|
||||||
private String calculatedType = null; // since obj is immutable, this is
|
private String calculatedType = null; // since obj is immutable, this is
|
||||||
// calc'd once
|
// calc'd once
|
||||||
|
|
||||||
// This will be useful for faster parses
|
// This will be useful for faster parses
|
||||||
private static HashMap<String, CardCoreType> stringToCoreType = new HashMap<String, CardCoreType>();
|
private static HashMap<String, CardType.CoreType> stringToCoreType = new HashMap<String, CardType.CoreType>();
|
||||||
private static HashMap<String, CardSuperType> stringToSuperType = new HashMap<String, CardSuperType>();
|
private static HashMap<String, CardType.SuperType> stringToSuperType = new HashMap<String, CardType.SuperType>();
|
||||||
static {
|
static {
|
||||||
for (final CardSuperType st : CardSuperType.values()) {
|
for (final CardType.SuperType st : CardType.SuperType.values()) {
|
||||||
CardType.stringToSuperType.put(st.name(), st);
|
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);
|
CardType.stringToCoreType.put(ct.name(), ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,13 +148,13 @@ public final class CardType implements Comparable<CardType> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final CardCoreType ct = CardType.stringToCoreType.get(type);
|
final CardType.CoreType ct = CardType.stringToCoreType.get(type);
|
||||||
if (ct != null) {
|
if (ct != null) {
|
||||||
this.coreType.add(ct);
|
this.coreType.add(ct);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final CardSuperType st = CardType.stringToSuperType.get(type);
|
final CardType.SuperType st = CardType.stringToSuperType.get(type);
|
||||||
if (st != null) {
|
if (st != null) {
|
||||||
this.superType.add(st);
|
this.superType.add(st);
|
||||||
return;
|
return;
|
||||||
@@ -126,56 +168,56 @@ public final class CardType implements Comparable<CardType> {
|
|||||||
return this.subType.contains(operand);
|
return this.subType.contains(operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean typeContains(final CardCoreType operand) {
|
public boolean typeContains(final CardType.CoreType operand) {
|
||||||
return this.coreType.contains(operand);
|
return this.coreType.contains(operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean superTypeContains(final CardSuperType operand) {
|
public boolean superTypeContains(final CardType.SuperType operand) {
|
||||||
return this.superType.contains(operand);
|
return this.superType.contains(operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCreature() {
|
public boolean isCreature() {
|
||||||
return this.coreType.contains(CardCoreType.Creature);
|
return this.coreType.contains(CardType.CoreType.Creature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPlaneswalker() {
|
public boolean isPlaneswalker() {
|
||||||
return this.coreType.contains(CardCoreType.Planeswalker);
|
return this.coreType.contains(CardType.CoreType.Planeswalker);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLand() {
|
public boolean isLand() {
|
||||||
return this.coreType.contains(CardCoreType.Land);
|
return this.coreType.contains(CardType.CoreType.Land);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isArtifact() {
|
public boolean isArtifact() {
|
||||||
return this.coreType.contains(CardCoreType.Artifact);
|
return this.coreType.contains(CardType.CoreType.Artifact);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInstant() {
|
public boolean isInstant() {
|
||||||
return this.coreType.contains(CardCoreType.Instant);
|
return this.coreType.contains(CardType.CoreType.Instant);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSorcery() {
|
public boolean isSorcery() {
|
||||||
return this.coreType.contains(CardCoreType.Sorcery);
|
return this.coreType.contains(CardType.CoreType.Sorcery);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isVanguard() {
|
public boolean isVanguard() {
|
||||||
return this.coreType.contains(CardCoreType.Vanguard);
|
return this.coreType.contains(CardType.CoreType.Vanguard);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isScheme() {
|
public boolean isScheme() {
|
||||||
return this.coreType.contains(CardCoreType.Scheme);
|
return this.coreType.contains(CardType.CoreType.Scheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnchantment() {
|
public boolean isEnchantment() {
|
||||||
return this.coreType.contains(CardCoreType.Enchantment);
|
return this.coreType.contains(CardType.CoreType.Enchantment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBasic() {
|
public boolean isBasic() {
|
||||||
return this.superType.contains(CardSuperType.Basic);
|
return this.superType.contains(CardType.SuperType.Basic);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLegendary() {
|
public boolean isLegendary() {
|
||||||
return this.superType.contains(CardSuperType.Legendary);
|
return this.superType.contains(CardType.SuperType.Legendary);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBasicLand() {
|
public boolean isBasicLand() {
|
||||||
@@ -200,10 +242,10 @@ public final class CardType implements Comparable<CardType> {
|
|||||||
|
|
||||||
public List<String> getTypesBeforeDash() {
|
public List<String> getTypesBeforeDash() {
|
||||||
final ArrayList<String> types = new ArrayList<String>();
|
final ArrayList<String> types = new ArrayList<String>();
|
||||||
for (final CardSuperType st : this.superType) {
|
for (final CardType.SuperType st : this.superType) {
|
||||||
types.add(st.name());
|
types.add(st.name());
|
||||||
}
|
}
|
||||||
for (final CardCoreType ct : this.coreType) {
|
for (final CardType.CoreType ct : this.coreType) {
|
||||||
types.add(ct.name());
|
types.add(ct.name());
|
||||||
}
|
}
|
||||||
return types;
|
return types;
|
||||||
@@ -229,13 +271,54 @@ public final class CardType implements Comparable<CardType> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPlane() {
|
public boolean isPlane() {
|
||||||
return this.coreType.contains(CardCoreType.Plane);
|
return this.coreType.contains(CardType.CoreType.Plane);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPhenomenon() {
|
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
|
///////// Utility methods
|
||||||
public static boolean isACardType(final String cardType) {
|
public static boolean isACardType(final String cardType) {
|
||||||
return CardType.getAllCardTypes().contains(cardType);
|
return CardType.getAllCardTypes().contains(cardType);
|
||||||
@@ -245,7 +328,7 @@ public final class CardType implements Comparable<CardType> {
|
|||||||
final ArrayList<String> types = new ArrayList<String>();
|
final ArrayList<String> types = new ArrayList<String>();
|
||||||
|
|
||||||
// types.addAll(getCardTypes());
|
// types.addAll(getCardTypes());
|
||||||
types.addAll(Constant.CardTypes.CARD_TYPES);
|
types.addAll(Constant.CARD_TYPES);
|
||||||
|
|
||||||
// not currently used by Forge
|
// not currently used by Forge
|
||||||
types.add("Plane");
|
types.add("Plane");
|
||||||
@@ -258,7 +341,7 @@ public final class CardType implements Comparable<CardType> {
|
|||||||
public static ArrayList<String> getBasicTypes() {
|
public static ArrayList<String> getBasicTypes() {
|
||||||
final ArrayList<String> types = new ArrayList<String>();
|
final ArrayList<String> types = new ArrayList<String>();
|
||||||
|
|
||||||
types.addAll(Constant.CardTypes.BASIC_TYPES);
|
types.addAll(Constant.BASIC_TYPES);
|
||||||
|
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
@@ -266,8 +349,8 @@ public final class CardType implements Comparable<CardType> {
|
|||||||
public static ArrayList<String> getLandTypes() {
|
public static ArrayList<String> getLandTypes() {
|
||||||
final ArrayList<String> types = new ArrayList<String>();
|
final ArrayList<String> types = new ArrayList<String>();
|
||||||
|
|
||||||
types.addAll(Constant.CardTypes.BASIC_TYPES);
|
types.addAll(Constant.BASIC_TYPES);
|
||||||
types.addAll(Constant.CardTypes.LAND_TYPES);
|
types.addAll(Constant.LAND_TYPES);
|
||||||
|
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
@@ -275,13 +358,13 @@ public final class CardType implements Comparable<CardType> {
|
|||||||
public static ArrayList<String> getCreatureTypes() {
|
public static ArrayList<String> getCreatureTypes() {
|
||||||
final ArrayList<String> types = new ArrayList<String>();
|
final ArrayList<String> types = new ArrayList<String>();
|
||||||
|
|
||||||
types.addAll(Constant.CardTypes.CREATURE_TYPES);
|
types.addAll(Constant.CREATURE_TYPES);
|
||||||
|
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isASuperType(final String cardType) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
public static boolean isABasicLandType(final String cardType) {
|
||||||
return (Constant.CardTypes.BASIC_TYPES.contains(cardType));
|
return (Constant.BASIC_TYPES.contains(cardType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,11 @@
|
|||||||
*/
|
*/
|
||||||
package forge.card;
|
package forge.card;
|
||||||
|
|
||||||
import forge.Constant;
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import com.google.common.collect.UnmodifiableIterator;
|
||||||
|
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.util.BinaryUtil;
|
import forge.util.BinaryUtil;
|
||||||
|
|
||||||
@@ -31,7 +35,7 @@ import forge.util.BinaryUtil;
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final class ColorSet implements Comparable<ColorSet> {
|
public final class ColorSet implements Comparable<ColorSet>, Iterable<Byte> {
|
||||||
|
|
||||||
private final byte myColor;
|
private final byte myColor;
|
||||||
private final int orderWeight;
|
private final int orderWeight;
|
||||||
@@ -55,7 +59,6 @@ public final class ColorSet implements Comparable<ColorSet> {
|
|||||||
private ColorSet(final byte mask) {
|
private ColorSet(final byte mask) {
|
||||||
this.myColor = mask;
|
this.myColor = mask;
|
||||||
this.orderWeight = this.getOrderWeight();
|
this.orderWeight = this.getOrderWeight();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ColorSet fromMask(final int mask) {
|
public static ColorSet fromMask(final int mask) {
|
||||||
@@ -253,7 +256,7 @@ public final class ColorSet implements Comparable<ColorSet> {
|
|||||||
return "n/a";
|
return "n/a";
|
||||||
}
|
}
|
||||||
String toReturn = MagicColor.toLongString(myColor);
|
String toReturn = MagicColor.toLongString(myColor);
|
||||||
if (toReturn == Constant.Color.COLORLESS && myColor != 0) {
|
if (toReturn == MagicColor.Constant.COLORLESS && myColor != 0) {
|
||||||
return "multi";
|
return "multi";
|
||||||
}
|
}
|
||||||
return toReturn;
|
return toReturn;
|
||||||
@@ -281,4 +284,37 @@ public final class ColorSet implements Comparable<ColorSet> {
|
|||||||
public ColorSet getOffColors(ColorSet ccOther) {
|
public ColorSet getOffColors(ColorSet ccOther) {
|
||||||
return ColorSet.fromMask(~this.myColor & ccOther.myColor);
|
return ColorSet.fromMask(~this.myColor & ccOther.myColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Byte> iterator() {
|
||||||
|
return new ColorIterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ColorIterator extends UnmodifiableIterator<Byte> {
|
||||||
|
int currentBit = -1;
|
||||||
|
|
||||||
|
private int getIndexOfNextColor(){
|
||||||
|
int nextBit = currentBit + 1;
|
||||||
|
while(nextBit < MagicColor.NUMBER_OR_COLORS) {
|
||||||
|
if((myColor & MagicColor.WUBRG[nextBit]) != 0)
|
||||||
|
break;
|
||||||
|
nextBit++;
|
||||||
|
}
|
||||||
|
return nextBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return getIndexOfNextColor() < MagicColor.NUMBER_OR_COLORS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Byte next() {
|
||||||
|
currentBit = getIndexOfNextColor();
|
||||||
|
if (currentBit >= MagicColor.NUMBER_OR_COLORS)
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
|
||||||
|
return MagicColor.WUBRG[currentBit];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ import com.google.common.base.Predicate;
|
|||||||
|
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
|
|
||||||
public interface ICardDatabase {
|
public interface ICardDatabase extends Iterable<PaperCard> {
|
||||||
PaperCard tryGetCard(String cardName);
|
PaperCard tryGetCard(String cardName);
|
||||||
PaperCard tryGetCard(String cardName, boolean fromLastSet);
|
PaperCard tryGetCard(String cardName, boolean fromLastSet);
|
||||||
PaperCard tryGetCard(String cardName, String edition);
|
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.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -7,7 +8,9 @@ import java.util.Collection;
|
|||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
import forge.util.ItemPool;
|
||||||
import forge.deck.CardPool;
|
import forge.deck.CardPool;
|
||||||
|
import forge.item.PaperCard;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
import forge.util.storage.StorageReaderFileSections;
|
import forge.util.storage.StorageReaderFileSections;
|
||||||
|
|
||||||
@@ -30,7 +33,7 @@ public class PrintSheet {
|
|||||||
this(name0, null);
|
this(name0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PrintSheet(String name0, ItemPool<PaperCard> pool) {
|
public PrintSheet(String name0, ItemPool<PaperCard> pool) {
|
||||||
name = name0;
|
name = name0;
|
||||||
cardsWithWeights = pool != null ? pool : new ItemPool<PaperCard>(PaperCard.class);
|
cardsWithWeights = pool != null ? pool : new ItemPool<PaperCard>(PaperCard.class);
|
||||||
}
|
}
|
||||||
@@ -105,18 +108,6 @@ public class PrintSheet {
|
|||||||
return result;
|
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() {
|
public boolean isEmpty() {
|
||||||
return cardsWithWeights.isEmpty();
|
return cardsWithWeights.isEmpty();
|
||||||
}
|
}
|
||||||
@@ -125,5 +116,16 @@ public class PrintSheet {
|
|||||||
return cardsWithWeights.toFlatList();
|
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.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
import forge.StaticData;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.item.ItemPoolView;
|
import forge.item.SealedProduct;
|
||||||
import forge.item.PrintSheet;
|
import forge.util.ItemPoolView;
|
||||||
|
|
||||||
|
|
||||||
public class UnOpenedProduct implements IUnOpenedProduct {
|
public class UnOpenedProduct implements IUnOpenedProduct {
|
||||||
|
|
||||||
private final SealedProductTemplate tpl;
|
private final SealedProduct.Template tpl;
|
||||||
private final Map<String, PrintSheet> sheets;
|
private final Map<String, PrintSheet> sheets;
|
||||||
private boolean poolLimited = false; // if true after successful generation cards are removed from printsheets.
|
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)
|
// 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;
|
tpl = template;
|
||||||
sheets = null;
|
sheets = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoke this constructor only if you are sure that the pool is not equal to deafult carddb
|
// 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());
|
this(template, pool.toFlatList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnOpenedProduct(SealedProductTemplate template, Iterable<PaperCard> cards) {
|
public UnOpenedProduct(SealedProduct.Template template, Iterable<PaperCard> cards) {
|
||||||
tpl = template;
|
tpl = template;
|
||||||
sheets = new TreeMap<String, PrintSheet>();
|
sheets = new TreeMap<String, PrintSheet>();
|
||||||
prebuildSheets(cards);
|
prebuildSheets(cards);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnOpenedProduct(SealedProductTemplate sealedProductTemplate, Predicate<PaperCard> filterPrinted) {
|
public UnOpenedProduct(SealedProduct.Template sealedProductTemplate, Predicate<PaperCard> filterPrinted) {
|
||||||
this(sealedProductTemplate, Iterables.filter(CardDb.instance().getAllCards(), filterPrinted));
|
this(sealedProductTemplate, Iterables.filter(StaticData.instance().getCommonCards().getAllCards(), filterPrinted));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prebuildSheets(Iterable<PaperCard> sourceList) {
|
private void prebuildSheets(Iterable<PaperCard> sourceList) {
|
||||||
@@ -19,10 +19,9 @@ package forge.card.mana;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import forge.card.ColorSet;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* CardManaCost class.
|
* CardManaCost class.
|
||||||
@@ -32,7 +31,7 @@ import forge.card.ColorSet;
|
|||||||
* @version $Id: CardManaCost.java 9708 2011-08-09 19:34:12Z jendave $
|
* @version $Id: CardManaCost.java 9708 2011-08-09 19:34:12Z jendave $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final class ManaCost implements Comparable<ManaCost> {
|
public final class ManaCost implements Comparable<ManaCost>, Iterable<ManaCostShard> {
|
||||||
private List<ManaCostShard> shards;
|
private List<ManaCostShard> shards;
|
||||||
private final int genericCost;
|
private final int genericCost;
|
||||||
private final boolean hasNoCost; // lands cost
|
private final boolean hasNoCost; // lands cost
|
||||||
@@ -49,7 +48,7 @@ public final class ManaCost implements Comparable<ManaCost> {
|
|||||||
public static final ManaCost FOUR = new ManaCost(4);
|
public static final ManaCost FOUR = new ManaCost(4);
|
||||||
|
|
||||||
public static ManaCost get(int cntColorless) {
|
public static ManaCost get(int cntColorless) {
|
||||||
switch (cntColorless) {
|
switch (cntColorless) {
|
||||||
case 0: return ZERO;
|
case 0: return ZERO;
|
||||||
case 1: return ONE;
|
case 1: return ONE;
|
||||||
case 2: return TWO;
|
case 2: return TWO;
|
||||||
@@ -58,14 +57,14 @@ public final class ManaCost implements Comparable<ManaCost> {
|
|||||||
}
|
}
|
||||||
return cntColorless > 0 ? new ManaCost(cntColorless) : NO_COST;
|
return cntColorless > 0 ? new ManaCost(cntColorless) : NO_COST;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pass mana cost parser here
|
// pass mana cost parser here
|
||||||
private ManaCost(int cmc) {
|
private ManaCost(int cmc) {
|
||||||
this.hasNoCost = cmc < 0;
|
this.hasNoCost = cmc < 0;
|
||||||
this.genericCost = cmc < 0 ? 0 : cmc;
|
this.genericCost = cmc < 0 ? 0 : cmc;
|
||||||
sealClass(new ArrayList<ManaCostShard>());
|
sealClass(new ArrayList<ManaCostShard>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sealClass(List<ManaCostShard> shards0) {
|
private void sealClass(List<ManaCostShard> shards0) {
|
||||||
this.shards = Collections.unmodifiableList(shards0);
|
this.shards = Collections.unmodifiableList(shards0);
|
||||||
this.stringValue = this.getSimpleString();
|
this.stringValue = this.getSimpleString();
|
||||||
@@ -97,22 +96,19 @@ public final class ManaCost implements Comparable<ManaCost> {
|
|||||||
return "no cost";
|
return "no cost";
|
||||||
}
|
}
|
||||||
if (this.shards.isEmpty()) {
|
if (this.shards.isEmpty()) {
|
||||||
return Integer.toString(this.genericCost);
|
return "{" + this.genericCost + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
boolean isFirst = true;
|
|
||||||
if (this.genericCost > 0) {
|
if (this.genericCost > 0) {
|
||||||
sb.append(this.genericCost);
|
sb.append("{" + this.genericCost + "}");
|
||||||
isFirst = false;
|
|
||||||
}
|
}
|
||||||
for (final ManaCostShard s : this.shards) {
|
for (final ManaCostShard s : this.shards) {
|
||||||
if (!isFirst) {
|
if (s == ManaCostShard.X) {
|
||||||
sb.append(' ');
|
sb.insert(0, s.toString());
|
||||||
} else {
|
} else {
|
||||||
isFirst = false;
|
sb.append(s.toString());
|
||||||
}
|
}
|
||||||
sb.append(s.toString());
|
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
@@ -143,15 +139,6 @@ public final class ManaCost implements Comparable<ManaCost> {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the shards.
|
|
||||||
*
|
|
||||||
* @return the shards
|
|
||||||
*/
|
|
||||||
public List<ManaCostShard> getShards() {
|
|
||||||
return this.shards;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getShardCount(ManaCostShard which) {
|
public int getShardCount(ManaCostShard which) {
|
||||||
if (which == ManaCostShard.COLORLESS) {
|
if (which == ManaCostShard.COLORLESS) {
|
||||||
return genericCost;
|
return genericCost;
|
||||||
@@ -196,7 +183,7 @@ public final class ManaCost implements Comparable<ManaCost> {
|
|||||||
public boolean isZero() {
|
public boolean isZero() {
|
||||||
return genericCost == 0 && isPureGeneric();
|
return genericCost == 0 && isPureGeneric();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
@@ -260,13 +247,12 @@ public final class ManaCost implements Comparable<ManaCost> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Can this mana cost be paid with unlimited mana of given color set.
|
* Can this mana cost be paid with unlimited mana of given color set.
|
||||||
* @param color
|
* @param colorCode
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
public boolean canBePaidWithAvaliable(byte colorCode) {
|
||||||
public boolean canBePaidWithAvaliable(ColorSet color) {
|
|
||||||
for (ManaCostShard shard : shards) {
|
for (ManaCostShard shard : shards) {
|
||||||
if (!shard.isPhyrexian() && !shard.canBePaidWithManaOfColor(color.getColor())) {
|
if (!shard.isPhyrexian() && !shard.canBePaidWithManaOfColor(colorCode)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -288,4 +274,16 @@ public final class ManaCost implements Comparable<ManaCost> {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<ManaCostShard> iterator() {
|
||||||
|
return this.shards.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGlyphCount() { // counts all colored shards or 1 for {0} costs
|
||||||
|
int width = shards.size();
|
||||||
|
if (genericCost > 0 || (genericCost == 0 && width == 0)) {
|
||||||
|
width++;
|
||||||
|
}
|
||||||
|
return width;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,17 @@ public class ManaCostParser implements IParserManaCost {
|
|||||||
private int nextToken;
|
private int nextToken;
|
||||||
private int colorlessCost;
|
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.
|
* Instantiates a new parser cardname txt mana cost.
|
||||||
*
|
*
|
||||||
@@ -54,7 +65,6 @@ public class ManaCostParser implements IParserManaCost {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final ManaCostShard next() {
|
public final ManaCostShard next() {
|
||||||
|
|
||||||
final String unparsed = this.cost[this.nextToken++];
|
final String unparsed = this.cost[this.nextToken++];
|
||||||
// System.out.println(unparsed);
|
// System.out.println(unparsed);
|
||||||
if (StringUtils.isNumeric(unparsed)) {
|
if (StringUtils.isNumeric(unparsed)) {
|
||||||
@@ -23,7 +23,7 @@ import forge.util.BinaryUtil;
|
|||||||
* The Class CardManaCostShard.
|
* The Class CardManaCostShard.
|
||||||
*/
|
*/
|
||||||
public enum ManaCostShard implements Comparable<ManaCostShard> {
|
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 */
|
/* Pure colors */
|
||||||
WHITE(ManaAtom.WHITE, "W"),
|
WHITE(ManaAtom.WHITE, "W"),
|
||||||
@@ -35,14 +35,14 @@ public enum ManaCostShard implements Comparable<ManaCostShard> {
|
|||||||
/* Hybrid */
|
/* Hybrid */
|
||||||
WU(ManaAtom.WHITE | ManaAtom.BLUE, "W/U", "WU"),
|
WU(ManaAtom.WHITE | ManaAtom.BLUE, "W/U", "WU"),
|
||||||
WB(ManaAtom.WHITE | ManaAtom.BLACK, "W/B", "WB"),
|
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"),
|
UB(ManaAtom.BLUE | ManaAtom.BLACK, "U/B", "UB"),
|
||||||
UR(ManaAtom.BLUE | ManaAtom.RED, "U/R", "UR"),
|
UR(ManaAtom.BLUE | ManaAtom.RED, "U/R", "UR"),
|
||||||
UG(ManaAtom.BLUE | ManaAtom.GREEN, "U/G", "GU"),
|
|
||||||
BR(ManaAtom.BLACK | ManaAtom.RED, "B/R", "BR"),
|
BR(ManaAtom.BLACK | ManaAtom.RED, "B/R", "BR"),
|
||||||
BG(ManaAtom.BLACK | ManaAtom.GREEN, "B/G", "BG"),
|
BG(ManaAtom.BLACK | ManaAtom.GREEN, "B/G", "BG"),
|
||||||
|
RW(ManaAtom.RED | ManaAtom.WHITE, "R/W", "RW"),
|
||||||
RG(ManaAtom.RED | ManaAtom.GREEN, "R/G", "RG"),
|
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 */
|
/* Or 2 colorless */
|
||||||
W2(ManaAtom.WHITE | ManaAtom.OR_2_COLORLESS, "2/W", "2W"),
|
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"),
|
S(ManaAtom.IS_SNOW, "S"),
|
||||||
COLORLESS(ManaAtom.COLORLESS, "1"),
|
COLORLESS(ManaAtom.COLORLESS, "1"),
|
||||||
|
|
||||||
/* Phyrexian */
|
/* Phyrexian */
|
||||||
PW(ManaAtom.WHITE | ManaAtom.OR_2_LIFE, "W/P", "PW"),
|
PW(ManaAtom.WHITE | ManaAtom.OR_2_LIFE, "W/P", "PW"),
|
||||||
PU(ManaAtom.BLUE | ManaAtom.OR_2_LIFE, "U/P", "PU"),
|
PU(ManaAtom.BLUE | ManaAtom.OR_2_LIFE, "U/P", "PU"),
|
||||||
PB(ManaAtom.BLACK | ManaAtom.OR_2_LIFE, "B/P", "PB"),
|
PB(ManaAtom.BLACK | ManaAtom.OR_2_LIFE, "B/P", "PB"),
|
||||||
@@ -102,15 +102,12 @@ public enum ManaCostShard implements Comparable<ManaCostShard> {
|
|||||||
this.shard = value;
|
this.shard = value;
|
||||||
this.cmc = this.getCMC();
|
this.cmc = this.getCMC();
|
||||||
this.cmpc = this.getCmpCost();
|
this.cmpc = this.getCmpCost();
|
||||||
this.stringValue = sValue;
|
this.stringValue = "{" + sValue + "}";
|
||||||
this.imageKey = imgKey;
|
this.imageKey = imgKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static final int COLORS_SUPERPOSITION = ManaAtom.WHITE | ManaAtom.BLUE | ManaAtom.BLACK | ManaAtom.RED | ManaAtom.GREEN;
|
public static final int COLORS_SUPERPOSITION = ManaAtom.WHITE | ManaAtom.BLUE | ManaAtom.BLACK | ManaAtom.RED | ManaAtom.GREEN;
|
||||||
|
|
||||||
|
|
||||||
private int getCMC() {
|
private int getCMC() {
|
||||||
if (0 != (this.shard & ManaAtom.IS_X)) {
|
if (0 != (this.shard & ManaAtom.IS_X)) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -267,7 +264,6 @@ public enum ManaCostShard implements Comparable<ManaCostShard> {
|
|||||||
|
|
||||||
public boolean isMonoColor() {
|
public boolean isMonoColor() {
|
||||||
return BinaryUtil.bitCount(this.shard & COLORS_SUPERPOSITION) == 1;
|
return BinaryUtil.bitCount(this.shard & COLORS_SUPERPOSITION) == 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOr2Colorless() {
|
public boolean isOr2Colorless() {
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
package forge.deck;
|
package forge.deck;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@@ -26,10 +25,9 @@ import java.util.NoSuchElementException;
|
|||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.StaticData;
|
||||||
import forge.card.CardDb;
|
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.item.ItemPool;
|
import forge.util.ItemPool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deck section.
|
* Deck section.
|
||||||
@@ -54,15 +52,6 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
this.addAll(cards);
|
this.addAll(cards);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the.
|
|
||||||
*
|
|
||||||
* @param card
|
|
||||||
* the card
|
|
||||||
*/
|
|
||||||
public void add(final Card card) {
|
|
||||||
this.add(CardDb.getCard(card));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the.
|
* Adds the.
|
||||||
@@ -84,9 +73,9 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
* @param amount the amount
|
* @param amount the amount
|
||||||
*/
|
*/
|
||||||
public void add(final String cardName, final String setCode, final int 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 )
|
if ( cp == null )
|
||||||
cp = CardDb.variants().tryGetCard(cardName, setCode);
|
cp = StaticData.instance().getVariantCards().tryGetCard(cardName, setCode);
|
||||||
|
|
||||||
if ( cp != null)
|
if ( cp != null)
|
||||||
this.add(cp, amount);
|
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 ));
|
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.
|
* Add all from a List of CardPrinted.
|
||||||
*
|
*
|
||||||
@@ -124,9 +101,9 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
* @param cardName the card name
|
* @param cardName the card name
|
||||||
*/
|
*/
|
||||||
public void add(final String cardName, int cnt) {
|
public void add(final String cardName, int cnt) {
|
||||||
PaperCard cp = CardDb.instance().tryGetCard(cardName);
|
PaperCard cp = StaticData.instance().getCommonCards().tryGetCard(cardName);
|
||||||
if ( cp == null )
|
if ( cp == null )
|
||||||
cp = CardDb.variants().tryGetCard(cardName);
|
cp = StaticData.instance().getVariantCards().tryGetCard(cardName);
|
||||||
|
|
||||||
if ( cp != null)
|
if ( cp != null)
|
||||||
this.add(cp, cnt);
|
this.add(cp, cnt);
|
||||||
@@ -35,12 +35,12 @@ import com.google.common.base.Function;
|
|||||||
import forge.card.CardDb;
|
import forge.card.CardDb;
|
||||||
import forge.deck.io.DeckFileHeader;
|
import forge.deck.io.DeckFileHeader;
|
||||||
import forge.deck.io.DeckSerializer;
|
import forge.deck.io.DeckSerializer;
|
||||||
import forge.item.ItemPoolSorter;
|
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.item.IPaperCard;
|
import forge.item.IPaperCard;
|
||||||
import forge.item.ItemPoolView;
|
|
||||||
import forge.util.FileSection;
|
import forge.util.FileSection;
|
||||||
import forge.util.FileUtil;
|
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} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object o) {
|
public boolean equals(final Object o) {
|
||||||
if (o instanceof Deck) {
|
if (o instanceof DeckBase) {
|
||||||
final Deck d = (Deck) o;
|
final DeckBase d = (DeckBase) o;
|
||||||
return this.getName().equals(d.getName());
|
return this.getName().equals(d.getName());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -22,43 +22,37 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.apache.commons.lang.math.IntRange;
|
|
||||||
|
|
||||||
import forge.Singletons;
|
import org.apache.commons.lang3.Range;
|
||||||
import forge.card.CardCoreType;
|
|
||||||
import forge.card.CardDb;
|
import forge.StaticData;
|
||||||
|
import forge.card.CardType;
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.item.IPaperCard;
|
import forge.item.IPaperCard;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GameType is an enum to determine the type of current game. :)
|
* GameType is an enum to determine the type of current game. :)
|
||||||
*/
|
*/
|
||||||
public enum DeckFormat {
|
public enum DeckFormat {
|
||||||
|
|
||||||
// Main board: allowed size SB: restriction Max distinct non basic cards
|
// Main board: allowed size SB: restriction Max distinct non basic cards
|
||||||
Constructed ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0, 15), 4),
|
Constructed ( Range.between(60, Integer.MAX_VALUE), Range.between(0, 15), 4),
|
||||||
QuestDeck ( new IntRange(40, Integer.MAX_VALUE), new IntRange(0, 15), 4),
|
QuestDeck ( Range.between(40, Integer.MAX_VALUE), Range.between(0, 15), 4),
|
||||||
Limited ( new IntRange(40, Integer.MAX_VALUE), null, Integer.MAX_VALUE),
|
Limited ( Range.between(40, Integer.MAX_VALUE), null, Integer.MAX_VALUE),
|
||||||
Commander ( new IntRange(99), new IntRange(0, 10), 1),
|
Commander ( Range.is(99), Range.between(0, 10), 1),
|
||||||
Vanguard ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4),
|
Vanguard ( Range.between(60, Integer.MAX_VALUE), Range.is(0), 4),
|
||||||
Planechase ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4),
|
Planechase ( Range.between(60, Integer.MAX_VALUE), Range.is(0), 4),
|
||||||
Archenemy ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4);
|
Archenemy ( Range.between(60, Integer.MAX_VALUE), Range.is(0), 4);
|
||||||
|
|
||||||
private final IntRange mainRange;
|
private final Range<Integer> mainRange;
|
||||||
private final IntRange sideRange; // null => no check
|
private final Range<Integer> sideRange; // null => no check
|
||||||
private final int maxCardCopies;
|
private final int maxCardCopies;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiates a new game type.
|
DeckFormat(Range<Integer> main, Range<Integer> side, int maxCopies) {
|
||||||
*
|
|
||||||
* @param isLimited
|
|
||||||
* the is limited
|
|
||||||
*/
|
|
||||||
DeckFormat(IntRange main, IntRange side, int maxCopies) {
|
|
||||||
mainRange = main;
|
mainRange = main;
|
||||||
sideRange = side;
|
sideRange = side;
|
||||||
maxCardCopies = maxCopies;
|
maxCardCopies = maxCopies;
|
||||||
@@ -90,7 +84,7 @@ public enum DeckFormat {
|
|||||||
/**
|
/**
|
||||||
* @return the sideRange
|
* @return the sideRange
|
||||||
*/
|
*/
|
||||||
public IntRange getSideRange() {
|
public Range<Integer> getSideRange() {
|
||||||
return sideRange;
|
return sideRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +92,7 @@ public enum DeckFormat {
|
|||||||
/**
|
/**
|
||||||
* @return the mainRange
|
* @return the mainRange
|
||||||
*/
|
*/
|
||||||
public IntRange getMainRange() {
|
public Range<Integer> getMainRange() {
|
||||||
return mainRange;
|
return mainRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,15 +112,10 @@ public enum DeckFormat {
|
|||||||
return "is not selected";
|
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 deckSize = deck.getMain().countAll();
|
||||||
|
|
||||||
int min = getMainRange().getMinimumInteger();
|
int min = getMainRange().getMinimum();
|
||||||
int max = getMainRange().getMaximumInteger();
|
int max = getMainRange().getMaximum();
|
||||||
|
|
||||||
if (deckSize < min) {
|
if (deckSize < min) {
|
||||||
return String.format("should have a minimum of %d cards", min);
|
return String.format("should have a minimum of %d cards", min);
|
||||||
@@ -189,7 +178,7 @@ public enum DeckFormat {
|
|||||||
int phenoms = 0;
|
int phenoms = 0;
|
||||||
for (Entry<PaperCard, Integer> cp : planes) {
|
for (Entry<PaperCard, Integer> cp : planes) {
|
||||||
|
|
||||||
if (cp.getKey().getRules().getType().typeContains(CardCoreType.Phenomenon)) {
|
if (cp.getKey().getRules().getType().typeContains(CardType.CoreType.Phenomenon)) {
|
||||||
phenoms++;
|
phenoms++;
|
||||||
}
|
}
|
||||||
if (cp.getValue() > 1) {
|
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
|
// 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)) {
|
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());
|
boolean canHaveMultiple = simpleCard.getRules().getType().isBasicLand() || limitExceptions.contains(cp.getKey());
|
||||||
|
|
||||||
if (!canHaveMultiple && cp.getValue() > maxCopies) {
|
if (!canHaveMultiple && cp.getValue() > maxCopies) {
|
||||||
@@ -244,11 +233,11 @@ public enum DeckFormat {
|
|||||||
|
|
||||||
// The sideboard must contain either 0 or 15 cards
|
// The sideboard must contain either 0 or 15 cards
|
||||||
int sideboardSize = deck.has(DeckSection.Sideboard) ? deck.get(DeckSection.Sideboard).countAll() : 0;
|
int sideboardSize = deck.has(DeckSection.Sideboard) ? deck.get(DeckSection.Sideboard).countAll() : 0;
|
||||||
IntRange sbRange = getSideRange();
|
Range<Integer> sbRange = getSideRange();
|
||||||
if (sbRange != null && sideboardSize > 0 && !sbRange.containsInteger(sideboardSize)) {
|
if (sbRange != null && sideboardSize > 0 && !sbRange.contains(sideboardSize)) {
|
||||||
return sbRange.getMinimumInteger() == sbRange.getMaximumInteger()
|
return sbRange.getMinimum() == sbRange.getMaximum()
|
||||||
? String.format("must have a sideboard of %d cards or no sideboard at all", sbRange.getMaximumInteger())
|
? 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.getMinimumInteger(), sbRange.getMaximumInteger());
|
: String.format("must have a sideboard of %d to %d cards or no sideboard at all", sbRange.getMinimum(), sbRange.getMaximum());
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -167,9 +167,9 @@ public class DeckRecognizer {
|
|||||||
private final ICardDatabase db;
|
private final ICardDatabase db;
|
||||||
private Date recognizeCardsPrintedBefore = null;
|
private Date recognizeCardsPrintedBefore = null;
|
||||||
|
|
||||||
public DeckRecognizer(boolean fromLatestSet) {
|
public DeckRecognizer(boolean fromLatestSet, CardDb db) {
|
||||||
useLastSet = fromLatestSet;
|
useLastSet = fromLatestSet;
|
||||||
db = CardDb.instance();
|
this.db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Token recognizeLine(final String rawLine) {
|
public Token recognizeLine(final String rawLine) {
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -24,10 +24,10 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
|
import forge.card.ICardDatabase;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.item.ItemPoolView;
|
import forge.util.ItemPoolView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -37,17 +37,17 @@ import forge.item.ItemPoolView;
|
|||||||
* @author Forge
|
* @author Forge
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class Generate2ColorDeck extends GenerateColoredDeckBase {
|
public class DeckGenerator2Color extends DeckGeneratorBase {
|
||||||
@Override protected final float getLandsPercentage() { return 0.39f; }
|
@Override protected final float getLandsPercentage() { return 0.39f; }
|
||||||
@Override protected final float getCreatPercentage() { return 0.36f; }
|
@Override protected final float getCreatPercentage() { return 0.36f; }
|
||||||
@Override protected final float getSpellPercentage() { return 0.25f; }
|
@Override protected final float getSpellPercentage() { return 0.25f; }
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final List<ImmutablePair<FilterCMC, Integer>> cmcRelativeWeights = Lists.newArrayList(
|
final List<ImmutablePair<FilterCMC, Integer>> cmcRelativeWeights = Lists.newArrayList(
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(0, 2), 6),
|
ImmutablePair.of(new FilterCMC(0, 2), 6),
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(3, 4), 4),
|
ImmutablePair.of(new FilterCMC(3, 4), 4),
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(5, 6), 2),
|
ImmutablePair.of(new FilterCMC(5, 6), 2),
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(7, 20), 1)
|
ImmutablePair.of(new FilterCMC(7, 20), 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
// mana curve of the card pool
|
// mana curve of the card pool
|
||||||
@@ -67,7 +67,8 @@ public class Generate2ColorDeck extends GenerateColoredDeckBase {
|
|||||||
* @param clr2
|
* @param clr2
|
||||||
* a {@link java.lang.String} object.
|
* 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 c1 = MagicColor.fromName(clr1);
|
||||||
int c2 = MagicColor.fromName(clr2);
|
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));
|
tmpDeck.append(String.format("Adjusted deck size to: %d, should add %d land(s)%n", size - numLands, numLands));
|
||||||
|
|
||||||
// Add dual lands
|
// Add dual lands
|
||||||
List<String> duals = GenerateDeckUtil.getDualLandList(colors);
|
List<String> duals = getDualLandList();
|
||||||
for (String s : duals) {
|
for (String s : duals) {
|
||||||
this.cardCounts.put(s, 0);
|
this.cardCounts.put(s, 0);
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package forge.deck.generate;
|
package forge.deck.generation;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -24,10 +24,10 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
|
import forge.card.ICardDatabase;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.item.ItemPoolView;
|
import forge.util.ItemPoolView;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,12 +38,12 @@ import forge.util.MyRandom;
|
|||||||
* @author Forge
|
* @author Forge
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class Generate3ColorDeck extends GenerateColoredDeckBase {
|
public class DeckGenerator3Color extends DeckGeneratorBase {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
|
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(0, 2), 12),
|
ImmutablePair.of(new FilterCMC(0, 2), 12),
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(3, 5), 9),
|
ImmutablePair.of(new FilterCMC(3, 5), 9),
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(6, 20), 3)
|
ImmutablePair.of(new FilterCMC(6, 20), 3)
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,7 +58,8 @@ public class Generate3ColorDeck extends GenerateColoredDeckBase {
|
|||||||
* @param clr3
|
* @param clr3
|
||||||
* a {@link java.lang.String} object.
|
* 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 c1 = MagicColor.fromName(clr1);
|
||||||
int c2 = MagicColor.fromName(clr2);
|
int c2 = MagicColor.fromName(clr2);
|
||||||
int c3 = MagicColor.fromName(clr3);
|
int c3 = MagicColor.fromName(clr3);
|
||||||
@@ -105,7 +106,7 @@ public class Generate3ColorDeck extends GenerateColoredDeckBase {
|
|||||||
tmpDeck.append("numLands:").append(numLands).append("\n");
|
tmpDeck.append("numLands:").append(numLands).append("\n");
|
||||||
|
|
||||||
// Add dual lands
|
// Add dual lands
|
||||||
List<String> duals = GenerateDeckUtil.getDualLandList(colors);
|
List<String> duals = getDualLandList();
|
||||||
for (String s : duals) {
|
for (String s : duals) {
|
||||||
this.cardCounts.put(s, 0);
|
this.cardCounts.put(s, 0);
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package forge.deck.generate;
|
package forge.deck.generation;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -24,9 +24,9 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
import forge.card.ICardDatabase;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.item.ItemPoolView;
|
import forge.util.ItemPoolView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -36,12 +36,12 @@ import forge.item.ItemPoolView;
|
|||||||
* @author Forge
|
* @author Forge
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class Generate5ColorDeck extends GenerateColoredDeckBase {
|
public class DeckGenerator5Color extends DeckGeneratorBase {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
|
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(0, 2), 3),
|
ImmutablePair.of(new FilterCMC(0, 2), 3),
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(3, 5), 2),
|
ImmutablePair.of(new FilterCMC(3, 5), 2),
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(6, 20), 1)
|
ImmutablePair.of(new FilterCMC(6, 20), 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
// resulting mana curve of the card pool
|
// resulting mana curve of the card pool
|
||||||
@@ -53,7 +53,8 @@ public class Generate5ColorDeck extends GenerateColoredDeckBase {
|
|||||||
/**
|
/**
|
||||||
* Instantiates a new generate5 color deck.
|
* Instantiates a new generate5 color deck.
|
||||||
*/
|
*/
|
||||||
public Generate5ColorDeck() {
|
public DeckGenerator5Color(ICardDatabase cardDb) {
|
||||||
|
super(cardDb);
|
||||||
colors = ColorSet.fromMask(0).inverse();
|
colors = ColorSet.fromMask(0).inverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +69,7 @@ public class Generate5ColorDeck extends GenerateColoredDeckBase {
|
|||||||
tmpDeck.append("numLands:").append(numLands).append("\n");
|
tmpDeck.append("numLands:").append(numLands).append("\n");
|
||||||
|
|
||||||
// Add dual lands
|
// Add dual lands
|
||||||
List<String> duals = GenerateDeckUtil.getDualLandList(colors);
|
List<String> duals = getDualLandList();
|
||||||
for (String s : duals) {
|
for (String s : duals) {
|
||||||
this.cardCounts.put(s, 0);
|
this.cardCounts.put(s, 0);
|
||||||
}
|
}
|
||||||
@@ -15,8 +15,9 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.Constant;
|
|
||||||
import forge.Singletons;
|
|
||||||
import forge.card.CardDb;
|
|
||||||
import forge.card.CardRules;
|
import forge.card.CardRules;
|
||||||
import forge.card.CardRulesPredicates;
|
import forge.card.CardRulesPredicates;
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
|
import forge.card.ICardDatabase;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.item.ItemPool;
|
|
||||||
import forge.item.ItemPoolView;
|
|
||||||
import forge.properties.ForgePreferences.FPref;
|
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
|
import forge.util.ItemPool;
|
||||||
|
import forge.util.ItemPoolView;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,13 +52,15 @@ import forge.util.MyRandom;
|
|||||||
* @author Forge
|
* @author Forge
|
||||||
* @version $Id: Generate2ColorDeck.java 14959 2012-03-28 14:03:43Z Chris H. $
|
* @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 Random r = MyRandom.getRandom();
|
||||||
protected final Map<String, Integer> cardCounts = new HashMap<String, Integer>();
|
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 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
|
// 2-colored deck generator has its own constants. The rest works fine with these ones
|
||||||
protected float getLandsPercentage() { return 0.44f; }
|
protected float getLandsPercentage() { return 0.44f; }
|
||||||
@@ -69,9 +69,15 @@ public abstract class GenerateColoredDeckBase {
|
|||||||
|
|
||||||
StringBuilder tmpDeck = new StringBuilder();
|
StringBuilder tmpDeck = new StringBuilder();
|
||||||
|
|
||||||
public GenerateColoredDeckBase() {
|
public DeckGeneratorBase(ICardDatabase cardDb) {
|
||||||
this.maxDuplicates = Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_SINGLETONS) ? 1 : 4;
|
this.cardDb = cardDb;
|
||||||
tDeck = new ItemPool<PaperCard>(PaperCard.class);
|
}
|
||||||
|
|
||||||
|
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) {
|
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));
|
} 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.
|
// 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.getCard(s, false));
|
||||||
tDeck.add(CardDb.instance().getCard(cp.getName(), false));
|
|
||||||
|
|
||||||
final int n = this.cardCounts.get(s);
|
final int n = this.cardCounts.get(s);
|
||||||
this.cardCounts.put(s, n + 1);
|
this.cardCounts.put(s, n + 1);
|
||||||
@@ -159,20 +164,20 @@ public abstract class GenerateColoredDeckBase {
|
|||||||
|
|
||||||
int landsLeft = cnt;
|
int landsLeft = cnt;
|
||||||
for (Entry<String, Integer> c : clrCnts.entrySet()) {
|
for (Entry<String, Integer> c : clrCnts.entrySet()) {
|
||||||
String color = c.getKey();
|
String basicLandName = c.getKey();
|
||||||
|
|
||||||
|
|
||||||
// calculate number of lands for each color
|
// calculate number of lands for each color
|
||||||
final int nLand = Math.min(landsLeft, Math.round(cnt * c.getValue() / totalColor));
|
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
|
// 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();
|
String basicLandSet = cp.getEdition();
|
||||||
|
|
||||||
tDeck.add(CardDb.instance().getCard(cp.getName(), basicLandSet), nLand);
|
tDeck.add(cardDb.getCard(cp.getName(), basicLandSet), nLand);
|
||||||
landsLeft -= nLand;
|
landsLeft -= nLand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,7 +227,7 @@ public abstract class GenerateColoredDeckBase {
|
|||||||
final List<PaperCard> curvedRandomized = Lists.newArrayList();
|
final List<PaperCard> curvedRandomized = Lists.newArrayList();
|
||||||
for (PaperCard c : curved) {
|
for (PaperCard c : curved) {
|
||||||
this.cardCounts.put(c.getName(), 0);
|
this.cardCounts.put(c.getName(), 0);
|
||||||
curvedRandomized.add(CardDb.instance().getCard(c.getName(), false));
|
curvedRandomized.add(cardDb.getCard(c.getName(), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
addSome(addOfThisCmc, curvedRandomized);
|
addSome(addOfThisCmc, curvedRandomized);
|
||||||
@@ -233,13 +238,13 @@ public abstract class GenerateColoredDeckBase {
|
|||||||
|
|
||||||
// start with all cards
|
// start with all cards
|
||||||
// remove cards that generated decks don't like
|
// remove cards that generated decks don't like
|
||||||
Predicate<CardRules> canPlay = forAi ? GenerateDeckUtil.AI_CAN_PLAY : GenerateDeckUtil.HUMAN_CAN_PLAY;
|
Predicate<CardRules> canPlay = forAi ? AI_CAN_PLAY : HUMAN_CAN_PLAY;
|
||||||
Predicate<CardRules> hasColor = new GenerateDeckUtil.MatchColorIdentity(colors);
|
Predicate<CardRules> hasColor = new MatchColorIdentity(colors);
|
||||||
|
|
||||||
if (!Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS)) {
|
if (useArtifacts) {
|
||||||
hasColor = Predicates.or(hasColor, GenerateDeckUtil.COLORLESS_CARDS);
|
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) {
|
protected static Map<String, Integer> countLands(ItemPool<PaperCard> outList) {
|
||||||
@@ -254,15 +259,15 @@ public abstract class GenerateColoredDeckBase {
|
|||||||
int profile = cpe.getKey().getRules().getManaCost().getColorProfile();
|
int profile = cpe.getKey().getRules().getManaCost().getColorProfile();
|
||||||
|
|
||||||
if ((profile & MagicColor.WHITE) != 0) {
|
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) {
|
} 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) {
|
} 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) {
|
} 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) {
|
} 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);
|
final Integer boxed = map.get(key);
|
||||||
map.put(key, boxed == null ? delta : boxed.intValue() + delta);
|
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
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package forge.deck.generate;
|
package forge.deck.generation;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -24,10 +24,10 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
|
import forge.card.ICardDatabase;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.item.ItemPoolView;
|
import forge.util.ItemPoolView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -37,17 +37,17 @@ import forge.item.ItemPoolView;
|
|||||||
* @author Forge
|
* @author Forge
|
||||||
* @version $Id: Generate2ColorDeck.java 19765 2013-02-20 03:01:37Z myk $
|
* @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 getLandsPercentage() { return 0.39f; }
|
||||||
@Override protected final float getCreatPercentage() { return 0.36f; }
|
@Override protected final float getCreatPercentage() { return 0.36f; }
|
||||||
@Override protected final float getSpellPercentage() { return 0.25f; }
|
@Override protected final float getSpellPercentage() { return 0.25f; }
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
|
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(0, 2), 10),
|
ImmutablePair.of(new FilterCMC(0, 2), 10),
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(3, 4), 8),
|
ImmutablePair.of(new FilterCMC(3, 4), 8),
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(5, 6), 5),
|
ImmutablePair.of(new FilterCMC(5, 6), 5),
|
||||||
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(7, 20), 3)
|
ImmutablePair.of(new FilterCMC(7, 20), 3)
|
||||||
);
|
);
|
||||||
|
|
||||||
// mana curve of the card pool
|
// mana curve of the card pool
|
||||||
@@ -67,7 +67,8 @@ public class GenerateMonoColorDeck extends GenerateColoredDeckBase {
|
|||||||
* @param clr2
|
* @param clr2
|
||||||
* a {@link java.lang.String} object.
|
* 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) {
|
if (MagicColor.fromName(clr1) == 0) {
|
||||||
int color1 = r.nextInt(5);
|
int color1 = r.nextInt(5);
|
||||||
colors = ColorSet.fromMask(MagicColor.WHITE << color1);
|
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 org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import forge.deck.DeckFormat;
|
import forge.deck.DeckFormat;
|
||||||
import forge.game.player.PlayerType;
|
|
||||||
import forge.util.FileSection;
|
import forge.util.FileSection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,7 +47,6 @@ public class DeckFileHeader {
|
|||||||
private static final String PLAYER_TYPE = "PlayerType";
|
private static final String PLAYER_TYPE = "PlayerType";
|
||||||
|
|
||||||
private final DeckFormat deckType;
|
private final DeckFormat deckType;
|
||||||
private final PlayerType playerType;
|
|
||||||
private final boolean customPool;
|
private final boolean customPool;
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
@@ -56,6 +54,15 @@ public class DeckFileHeader {
|
|||||||
|
|
||||||
private final Set<String> tags;
|
private final Set<String> tags;
|
||||||
|
|
||||||
|
private final boolean intendedForAi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the intendedForAi
|
||||||
|
*/
|
||||||
|
public boolean isIntendedForAi() {
|
||||||
|
return intendedForAi;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Write javadoc for Constructor.
|
* TODO: Write javadoc for Constructor.
|
||||||
*
|
*
|
||||||
@@ -67,8 +74,7 @@ public class DeckFileHeader {
|
|||||||
this.comment = kvPairs.get(DeckFileHeader.COMMENT);
|
this.comment = kvPairs.get(DeckFileHeader.COMMENT);
|
||||||
this.deckType = DeckFormat.smartValueOf(kvPairs.get(DeckFileHeader.DECK_TYPE), DeckFormat.Constructed);
|
this.deckType = DeckFormat.smartValueOf(kvPairs.get(DeckFileHeader.DECK_TYPE), DeckFormat.Constructed);
|
||||||
this.customPool = kvPairs.getBoolean(DeckFileHeader.CSTM_POOL);
|
this.customPool = kvPairs.getBoolean(DeckFileHeader.CSTM_POOL);
|
||||||
boolean isForAi = "computer".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER)) || "ai".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER_TYPE));
|
this.intendedForAi = "computer".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER)) || "ai".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER_TYPE));
|
||||||
this.playerType = isForAi ? PlayerType.COMPUTER : PlayerType.HUMAN;
|
|
||||||
this.tags = new TreeSet<String>();
|
this.tags = new TreeSet<String>();
|
||||||
|
|
||||||
String rawTags = kvPairs.get(DeckFileHeader.TAGS);
|
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.
|
* 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 com.google.common.base.Function;
|
||||||
|
|
||||||
import forge.Singletons;
|
import forge.StaticData;
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
import forge.card.SealedProductTemplate;
|
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
public class BoosterPack extends OpenablePack {
|
public class BoosterPack extends SealedProduct {
|
||||||
private final int artIndex;
|
private final int artIndex;
|
||||||
private final int hash;
|
private final int hash;
|
||||||
|
|
||||||
public static final Function<CardEdition, BoosterPack> FN_FROM_SET = new Function<CardEdition, BoosterPack>() {
|
public static final Function<CardEdition, BoosterPack> FN_FROM_SET = new Function<CardEdition, BoosterPack>() {
|
||||||
@Override
|
@Override
|
||||||
public BoosterPack apply(final CardEdition arg1) {
|
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);
|
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);
|
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;
|
artIndex = MyRandom.getRandom().nextInt(maxIdx) + 1;
|
||||||
hash = super.hashCode() ^ artIndex;
|
hash = super.hashCode() ^ artIndex;
|
||||||
}
|
}
|
||||||
@@ -58,7 +57,7 @@ public class BoosterPack extends OpenablePack {
|
|||||||
return new BoosterPack(name, contents);
|
return new BoosterPack(name, contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SealedProductTemplate getBoosterData() {
|
public Template getBoosterData() {
|
||||||
return contents;
|
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.base.Predicate;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.Card;
|
//import forge.Card;
|
||||||
import forge.card.CardRarity;
|
import forge.card.CardRarity;
|
||||||
import forge.card.CardRules;
|
import forge.card.CardRules;
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.util.PredicateString;
|
import forge.util.PredicateString;
|
||||||
|
|
||||||
public interface IPaperCard extends InventoryItem {
|
public interface IPaperCard extends InventoryItem {
|
||||||
@@ -161,7 +160,4 @@ public interface IPaperCard extends InventoryItem {
|
|||||||
|
|
||||||
public abstract String getItemType();
|
public abstract String getItemType();
|
||||||
|
|
||||||
public abstract Card getMatchingForgeCard();
|
|
||||||
public abstract Card toForgeCard(Player owner);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -17,16 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
package forge.item;
|
package forge.item;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
import forge.Card;
|
|
||||||
import forge.card.CardRarity;
|
import forge.card.CardRarity;
|
||||||
import forge.card.CardRules;
|
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 {
|
public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet, IPaperCard {
|
||||||
// Reference to rules
|
// Reference to rules
|
||||||
private final transient CardRules card;
|
private final transient CardRules rules;
|
||||||
|
|
||||||
// These fields are kinda PK for PrintedCard
|
// These fields are kinda PK for PrintedCard
|
||||||
public final String name;
|
public final String name;
|
||||||
@@ -55,7 +49,7 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
|||||||
public String getName() {
|
public String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getEdition() {
|
public String getEdition() {
|
||||||
return this.edition;
|
return this.edition;
|
||||||
@@ -78,7 +72,7 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CardRules getRules() {
|
public CardRules getRules() {
|
||||||
return this.card;
|
return this.rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,15 +80,11 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
|||||||
return this.rarity;
|
return this.rarity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
// public String getImageKey() {
|
// public String getImageKey() {
|
||||||
// return getImageLocator(getImageName(), getArtIndex(), true, false);
|
// return getImageLocator(getImageName(), getArtIndex(), true, false);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getItemType() {
|
public String getItemType() {
|
||||||
return "Card";
|
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>() {
|
public static final Function<PaperCard, CardRules> FN_GET_RULES = new Function<PaperCard, CardRules>() {
|
||||||
@Override
|
@Override
|
||||||
public CardRules apply(final PaperCard from) {
|
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>() {
|
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) {
|
public String apply(final PaperCard from) {
|
||||||
return from.getName();
|
return from.getName();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public PaperCard(final CardRules c, final String edition0, final CardRarity rare, final int index) {
|
public PaperCard(final CardRules c, final String edition0, final CardRarity rare, final int index) {
|
||||||
this(c, edition0, rare, index, false);
|
this(c, edition0, rare, index, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PaperCard(final CardRules c, final String edition0, final CardRarity rare, final int index, final boolean foil) {
|
public PaperCard(final CardRules c, final String edition0, final CardRarity rare, final int index, final boolean foil) {
|
||||||
if ( edition0 == null || c == null || rare == null )
|
if ( edition0 == null || c == null || rare == null )
|
||||||
throw new IllegalArgumentException("Cannot create card without rules, edition or rarity");
|
throw new IllegalArgumentException("Cannot create card without rules, edition or rarity");
|
||||||
this.card = c;
|
this.rules = c;
|
||||||
this.name = c.getName();
|
this.name = c.getName();
|
||||||
this.edition = edition0;
|
this.edition = edition0;
|
||||||
this.artIndex = index;
|
this.artIndex = index;
|
||||||
@@ -184,34 +174,6 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
|||||||
// return String.format("%s|%s", name, cardSet);
|
// 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)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
@@ -2,12 +2,10 @@ package forge.item;
|
|||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import forge.Card;
|
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
import forge.card.CardRarity;
|
import forge.card.CardRarity;
|
||||||
import forge.card.CardRules;
|
import forge.card.CardRules;
|
||||||
import forge.card.cardfactory.CardFactory;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
|
|
||||||
public class PaperToken implements InventoryItemFromSet, IPaperCard {
|
public class PaperToken implements InventoryItemFromSet, IPaperCard {
|
||||||
private String name;
|
private String name;
|
||||||
@@ -61,13 +59,6 @@ public class PaperToken implements InventoryItemFromSet, IPaperCard {
|
|||||||
public String getImageFilename() { return imageFileName; }
|
public String getImageFilename() { return imageFileName; }
|
||||||
|
|
||||||
@Override public String getItemType() { return "Token"; }
|
@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; }
|
@Override public boolean isToken() { return true; }
|
||||||
}
|
}
|
||||||
@@ -18,16 +18,18 @@
|
|||||||
package forge.item;
|
package forge.item;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FilenameFilter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
import forge.Singletons;
|
import forge.StaticData;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.quest.SellRules;
|
import forge.deck.io.DeckSerializer;
|
||||||
import forge.util.FileSection;
|
import forge.util.FileSection;
|
||||||
import forge.util.FileUtil;
|
import forge.util.FileUtil;
|
||||||
|
import forge.util.storage.StorageReaderFolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Write javadoc for this type.
|
* TODO: Write javadoc for this type.
|
||||||
@@ -36,11 +38,11 @@ import forge.util.FileUtil;
|
|||||||
public class PreconDeck implements InventoryItemFromSet {
|
public class PreconDeck implements InventoryItemFromSet {
|
||||||
|
|
||||||
private final Deck deck;
|
private final Deck deck;
|
||||||
private final String imageFilename;
|
|
||||||
private final String set;
|
private final String set;
|
||||||
private final String description;
|
private final String description;
|
||||||
|
private String imageFilename;
|
||||||
private final SellRules recommendedDeals;
|
|
||||||
|
// private final SellRules recommendedDeals;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
@@ -62,34 +64,12 @@ public class PreconDeck implements InventoryItemFromSet {
|
|||||||
return "Prebuilt Deck";
|
return "Prebuilt Deck";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public PreconDeck(final Deck d, String set, String description) {
|
||||||
* Instantiates a new precon deck.
|
deck = d;
|
||||||
*
|
this.set = set;
|
||||||
* @param f
|
this.description = description;
|
||||||
* 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"));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the deck.
|
|
||||||
*
|
|
||||||
* @return the deck
|
|
||||||
*/
|
|
||||||
public final Deck getDeck() {
|
public final Deck getDeck() {
|
||||||
return this.deck;
|
return this.deck;
|
||||||
}
|
}
|
||||||
@@ -99,9 +79,9 @@ public class PreconDeck implements InventoryItemFromSet {
|
|||||||
*
|
*
|
||||||
* @return the recommended deals
|
* @return the recommended deals
|
||||||
*/
|
*/
|
||||||
public final SellRules getRecommendedDeals() {
|
// public final SellRules getRecommendedDeals() {
|
||||||
return this.recommendedDeals;
|
// return this.recommendedDeals;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public final String getImageFilename() {
|
public final String getImageFilename() {
|
||||||
return imageFilename;
|
return imageFilename;
|
||||||
@@ -132,5 +112,38 @@ public class PreconDeck implements InventoryItemFromSet {
|
|||||||
return arg1.getName();
|
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 com.google.common.base.Function;
|
||||||
|
|
||||||
import forge.Singletons;
|
import forge.StaticData;
|
||||||
import forge.card.BoosterGenerator;
|
import forge.card.BoosterGenerator;
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
import forge.card.SealedProductTemplate;
|
|
||||||
|
|
||||||
public class TournamentPack extends OpenablePack {
|
public class TournamentPack extends SealedProduct {
|
||||||
|
|
||||||
/** The Constant fnFromSet. */
|
/** The Constant fnFromSet. */
|
||||||
public static final Function<CardEdition, TournamentPack> FN_FROM_SET = new Function<CardEdition, TournamentPack>() {
|
public static final Function<CardEdition, TournamentPack> FN_FROM_SET = new Function<CardEdition, TournamentPack>() {
|
||||||
@Override
|
@Override
|
||||||
public TournamentPack apply(final CardEdition arg1) {
|
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);
|
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);
|
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.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -31,8 +31,6 @@ import java.util.regex.Pattern;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import forge.error.BugReporter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* FileUtil class.
|
* FileUtil class.
|
||||||
@@ -109,17 +107,12 @@ public final class FileUtil {
|
|||||||
}
|
}
|
||||||
p.close();
|
p.close();
|
||||||
} catch (final Exception ex) {
|
} catch (final Exception ex) {
|
||||||
BugReporter.reportException(ex);
|
|
||||||
throw new RuntimeException("FileUtil : writeFile() error, problem writing file - " + file + " : " + ex);
|
throw new RuntimeException("FileUtil : writeFile() error, problem writing file - " + file + " : " + ex);
|
||||||
}
|
}
|
||||||
} // writeAllDecks()
|
} // writeAllDecks()
|
||||||
|
|
||||||
public static String readFileToString(String filename) {
|
public static String readFileToString(String filename) {
|
||||||
StringBuilder s = new StringBuilder();
|
return TextUtil.join(readFile(filename), "\n");
|
||||||
for (String line : readFile(filename)) {
|
|
||||||
s.append(line).append('\n');
|
|
||||||
}
|
|
||||||
return s.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> readFile(final String filename) {
|
public static List<String> readFile(final String filename) {
|
||||||
@@ -145,7 +138,6 @@ public final class FileUtil {
|
|||||||
}
|
}
|
||||||
return FileUtil.readAllLines(new FileReader(file), false);
|
return FileUtil.readAllLines(new FileReader(file), false);
|
||||||
} catch (final Exception ex) {
|
} catch (final Exception ex) {
|
||||||
BugReporter.reportException(ex);
|
|
||||||
throw new RuntimeException("FileUtil : readFile() error, " + ex);
|
throw new RuntimeException("FileUtil : readFile() error, " + ex);
|
||||||
}
|
}
|
||||||
} // readFile()
|
} // readFile()
|
||||||
@@ -180,7 +172,6 @@ public final class FileUtil {
|
|||||||
}
|
}
|
||||||
in.close();
|
in.close();
|
||||||
} catch (final IOException ex) {
|
} catch (final IOException ex) {
|
||||||
BugReporter.reportException(ex);
|
|
||||||
throw new RuntimeException("FileUtil : readAllLines() error, " + ex);
|
throw new RuntimeException("FileUtil : readAllLines() error, " + ex);
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
@@ -15,11 +15,13 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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.Collections;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import forge.item.InventoryItem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* ItemPool class.
|
* ItemPool class.
|
||||||
@@ -111,12 +113,12 @@ public class ItemPool<T extends InventoryItem> extends ItemPoolView<T> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.getItems().put(item, Integer.valueOf(this.count(item) + amount));
|
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) {
|
private void put(final T item, final int amount) {
|
||||||
this.getItems().put(item, 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.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.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 {
|
} else {
|
||||||
this.getItems().put(item, count - amount);
|
this.getItems().put(item, count - amount);
|
||||||
}
|
}
|
||||||
this.setListInSync(false);
|
this.isListInSync = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +224,6 @@ public class ItemPool<T extends InventoryItem> extends ItemPoolView<T> {
|
|||||||
*/
|
*/
|
||||||
public void clear() {
|
public void clear() {
|
||||||
this.getItems().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
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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.Comparator;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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.ArrayList;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
@@ -27,6 +27,8 @@ import java.util.Map.Entry;
|
|||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
|
import forge.item.InventoryItem;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <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>>();
|
private final transient List<Entry<T, Integer>> itemsOrdered = new ArrayList<Map.Entry<T, Integer>>();
|
||||||
|
|
||||||
/** Whether list is in sync. */
|
/** Whether list is in sync. */
|
||||||
private transient boolean isListInSync = false;
|
protected transient boolean isListInSync = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iterator.
|
* iterator.
|
||||||
@@ -188,7 +190,7 @@ public class ItemPoolView<T extends InventoryItem> implements Iterable<Entry<T,
|
|||||||
* @return List<Entry<T, Integer>>
|
* @return List<Entry<T, Integer>>
|
||||||
*/
|
*/
|
||||||
public final List<Entry<T, Integer>> getOrderedList() {
|
public final List<Entry<T, Integer>> getOrderedList() {
|
||||||
if (!this.isListInSync()) {
|
if (!this.isListInSync) {
|
||||||
this.rebuildOrderedList();
|
this.rebuildOrderedList();
|
||||||
}
|
}
|
||||||
return this.itemsOrdered;
|
return this.itemsOrdered;
|
||||||
@@ -201,7 +203,7 @@ public class ItemPoolView<T extends InventoryItem> implements Iterable<Entry<T,
|
|||||||
this.itemsOrdered.add(e);
|
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;
|
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.
|
* To item list string.
|
||||||
@@ -31,13 +31,13 @@ public class Lang {
|
|||||||
return position + sufixes[position % 10];
|
return position + sufixes[position % 10];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> String joinHomogenous(String s1, String s2) {
|
public static <T> String joinHomogenous(String s1, String s2) {
|
||||||
boolean has1 = StringUtils.isNotBlank(s1);
|
boolean has1 = StringUtils.isNotBlank(s1);
|
||||||
boolean has2 = StringUtils.isNotBlank(s2);
|
boolean has2 = StringUtils.isNotBlank(s2);
|
||||||
return has1 ? (has2 ? s1 + " and " + s2 : s1) : (has2 ? s2 : "");
|
return has1 ? (has2 ? s1 + " and " + s2 : s1) : (has2 ? s2 : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> String joinHomogenous(Iterable<T> objects) { return joinHomogenous(Lists.newArrayList(objects)); }
|
public static <T> String joinHomogenous(Iterable<T> objects) { return joinHomogenous(Lists.newArrayList(objects)); }
|
||||||
public static <T> String joinHomogenous(Collection<T> objects) { return joinHomogenous(objects, null, "and"); }
|
public static <T> String joinHomogenous(Collection<T> objects) { return joinHomogenous(objects, null, "and"); }
|
||||||
public static <T> String joinHomogenous(Collection<T> objects, Function<T, String> accessor) {
|
public static <T> String joinHomogenous(Collection<T> objects, Function<T, String> accessor) {
|
||||||
@@ -46,85 +46,92 @@ public class Lang {
|
|||||||
public static <T> String joinHomogenous(Collection<T> objects, Function<T, String> accessor, String lastUnion) {
|
public static <T> String joinHomogenous(Collection<T> objects, Function<T, String> accessor, String lastUnion) {
|
||||||
int remaining = objects.size();
|
int remaining = objects.size();
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for(T obj : objects) {
|
for (T obj : objects) {
|
||||||
remaining--;
|
remaining--;
|
||||||
if( accessor != null )
|
if (accessor != null) {
|
||||||
sb.append(accessor.apply(obj));
|
sb.append(accessor.apply(obj));
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
sb.append(obj);
|
sb.append(obj);
|
||||||
if( remaining > 1 ) sb.append(", ");
|
}
|
||||||
if( remaining == 1 ) sb.append(" ").append(lastUnion).append(" ");
|
if (remaining > 1) {
|
||||||
|
sb.append(", ");
|
||||||
|
}
|
||||||
|
else if (remaining == 1) {
|
||||||
|
sb.append(" ").append(lastUnion).append(" ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static <T> String joinVerb(List<T> subjects, String verb) {
|
public static <T> String joinVerb(List<T> subjects, String verb) {
|
||||||
return subjects.size() > 1 || !subjectIsSingle3rdPerson(Iterables.getFirst(subjects, "it").toString()) ? verb : verbs3rdPersonSingular(verb);
|
return subjects.size() > 1 || !subjectIsSingle3rdPerson(Iterables.getFirst(subjects, "it").toString()) ? verb : verbs3rdPersonSingular(verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String joinVerb(String subject, String verb) {
|
public static String joinVerb(String subject, String verb) {
|
||||||
return !Lang.subjectIsSingle3rdPerson(subject) ? verb : verbs3rdPersonSingular(verb);
|
return !Lang.subjectIsSingle3rdPerson(subject) ? verb : verbs3rdPersonSingular(verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean subjectIsSingle3rdPerson(String subject) {
|
public static boolean subjectIsSingle3rdPerson(String subject) {
|
||||||
// Will be most simple
|
// Will be most simple
|
||||||
return !"You".equalsIgnoreCase(subject);
|
return !"You".equalsIgnoreCase(subject);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String verbs3rdPersonSingular(String verb) {
|
public static String verbs3rdPersonSingular(String verb) {
|
||||||
// English is simple - just add (s) for multiple objects.
|
// English is simple - just add (s) for multiple objects.
|
||||||
return verb + "s";
|
return verb + "s";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getPlural(String noun) {
|
public static String getPlural(String noun) {
|
||||||
return noun + ( noun.endsWith("s") || noun.endsWith("x") ? "es" : "s");
|
return noun + (noun.endsWith("s") || noun.endsWith("x") ? "es" : "s");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> String nounWithAmount(int cnt, String noun) {
|
public static <T> String nounWithAmount(int cnt, String noun) {
|
||||||
String countedForm = cnt <= 1 ? noun : getPlural(noun);
|
String countedForm = cnt == 1 ? noun : getPlural(noun);
|
||||||
final String strCount;
|
final String strCount;
|
||||||
if( cnt == 1 )
|
if (cnt == 1) {
|
||||||
strCount = startsWithVowel(noun) ? "an " : "a ";
|
strCount = startsWithVowel(noun) ? "an " : "a ";
|
||||||
else
|
}
|
||||||
strCount = String.valueOf(cnt) + " ";
|
else {
|
||||||
|
strCount = String.valueOf(cnt) + " ";
|
||||||
|
}
|
||||||
return strCount + countedForm;
|
return strCount + countedForm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> String nounWithNumeral(int cnt, String noun) {
|
public static <T> String nounWithNumeral(int cnt, String noun) {
|
||||||
String countedForm = cnt <= 1 ? noun : getPlural(noun);
|
String countedForm = cnt <= 1 ? noun : getPlural(noun);
|
||||||
return getNumeral(cnt) + " " + countedForm;
|
return getNumeral(cnt) + " " + countedForm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getPossesive(String name) {
|
public static String getPossesive(String name) {
|
||||||
if ("You".equalsIgnoreCase(name)) return name + "r"; // to get "your"
|
if ("You".equalsIgnoreCase(name)) return name + "r"; // to get "your"
|
||||||
return name.endsWith("s") ? name + "'" : name + "'s";
|
return name.endsWith("s") ? name + "'" : name + "'s";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean startsWithVowel(String word) {
|
public static boolean startsWithVowel(String word) {
|
||||||
return isVowel(word.trim().charAt(0));
|
return isVowel(word.trim().charAt(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final char[] vowels = { 'a', 'i', 'e', 'o', 'u' };
|
private static final char[] vowels = { 'a', 'i', 'e', 'o', 'u' };
|
||||||
public static boolean isVowel(char letter) {
|
public static boolean isVowel(char letter) {
|
||||||
char l = Character.toLowerCase(letter);
|
char l = Character.toLowerCase(letter);
|
||||||
for(char c : vowels)
|
for (char c : vowels) {
|
||||||
if ( c == l ) return true;
|
if (c == l) return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static String[] numbers0 = new String[] {
|
public final static String[] numbers0 = new String[] {
|
||||||
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
||||||
"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eightteen", "nineteen" };
|
"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eightteen", "nineteen" };
|
||||||
public final static String[] numbers20 = new String[] {"twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety" };
|
public final static String[] numbers20 = new String[] {"twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety" };
|
||||||
|
|
||||||
public static String getNumeral(int n) {
|
public static String getNumeral(int n) {
|
||||||
String prefix = n < 0 ? "minus " : "";
|
String prefix = n < 0 ? "minus " : "";
|
||||||
n = Math.abs(n);
|
n = Math.abs(n);
|
||||||
if ( n >= 0 && n < 20 )
|
if (n >= 0 && n < 20)
|
||||||
return prefix + numbers0[n];
|
return prefix + numbers0[n];
|
||||||
if ( n < 100 ) {
|
if (n < 100) {
|
||||||
int n1 = n % 10;
|
int n1 = n % 10;
|
||||||
String ones = n1 == 0 ? "" : numbers0[n1];
|
String ones = n1 == 0 ? "" : numbers0[n1];
|
||||||
return prefix + numbers20[(n / 10) - 2] + " " + ones;
|
return prefix + numbers20[(n / 10) - 2] + " " + ones;
|
||||||
@@ -43,7 +43,7 @@ public class TextUtil {
|
|||||||
return mapAsString.toString();
|
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);
|
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
|
* 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) {
|
public static String[] splitWithParenthesis(CharSequence input, char delimiter, int maxEntries, char openPar, char closePar, boolean skipEmpty) {
|
||||||
List<String> result = new ArrayList<String>();
|
List<String> result = new ArrayList<String>();
|
||||||
@@ -98,7 +98,18 @@ public class TextUtil {
|
|||||||
String[] toReturn = result.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
|
String[] toReturn = result.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
|
||||||
return trimParenthesis ? StringUtils.stripAll(toReturn, String.valueOf(openPar)) : toReturn;
|
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
|
* Converts an enum value to a printable label but upcasing the first letter
|
||||||
* and lcasing all subsequent letters
|
* and lcasing all subsequent letters
|
||||||
52
forge-core/src/main/java/forge/util/ThreadUtil.java
Normal file
52
forge-core/src/main/java/forge/util/ThreadUtil.java
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
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