Compare commits

..

1620 Commits

Author SHA1 Message Date
Chris
312c15d824 [maven-release-plugin] prepare release forge-1.5.6 2013-11-29 15:06:32 +00:00
Chris
3f0cdc9b19 - Preparing the changes.txt file for the next beta build and release. 2013-11-29 14:52:38 +00:00
drdev
5d5c42c843 Mention Compact Prompt in CHANGES.txt 2013-11-29 06:57:36 +00:00
drdev
1a8fe19c88 Fix so multi-color cards containing a filtered color no longer show up in catalogs 2013-11-29 06:52:51 +00:00
drdev
7e37495b49 Hide checkbox to enable "Stack Card View" setting which isn't ready yet 2013-11-29 06:23:29 +00:00
drdev
3210f06931 Revert so command zone shown for all game types 2013-11-29 05:08:25 +00:00
drdev
a457ff539d Convert hide prompt header setting into compact prompt setting that also controls font size 2013-11-29 04:51:51 +00:00
drdev
afbcd90ffc Don't switch to Combat pane unless an attacker is declared 2013-11-29 04:37:35 +00:00
Maxmtg
8acdc6c458 fix name card effect 2013-11-29 04:37:23 +00:00
drdev
4ed8f69da1 If switched to Combat pane when combat begins, switch back to previous pane when combat ends 2013-11-29 04:28:05 +00:00
Maxmtg
90fe657da6 refactor: move isCommandZoneNeeded to gameType (java enums are far better than c#'s ones :) 2013-11-29 04:03:20 +00:00
drdev
91fe7b516c Show turn number in prompt message 2013-11-29 03:54:04 +00:00
drdev
e3851e3f1d Reduce padding around Prompt buttons 2013-11-29 03:39:34 +00:00
drdev
301014285f Reduce font size of prompt
Add setting to hide prompt header
2013-11-29 03:33:09 +00:00
drdev
e467f44bf2 Fix so Save and Open dialogs appear over main window 2013-11-29 02:59:22 +00:00
drdev
e8e5ac2ca7 Don't show command zone if game type doesn't need it 2013-11-29 02:51:55 +00:00
drdev
ebb0a4b2bc Mention change to show tabs if multiple on pane in CHANGES.txt 2013-11-28 18:01:50 +00:00
drdev
d21e2666ec Don't hide drag tabs if drag cell has multiple tabs 2013-11-28 17:58:46 +00:00
moomarc
43140b2db3 - Small fix for multiplayer tab labels 2013-11-28 09:02:39 +00:00
Maxmtg
c898e1321f cardreader fix 2013-11-27 07:46:21 +00:00
Maxmtg
4f04cbbcc8 fix hangs when both textfiles and zip are present in cardsfolder 2013-11-26 17:40:30 +00:00
asepetci
f17e857710 updated rankings.txt 2013-11-26 09:01:22 +00:00
drdev
2401b9b1ff Fix display issue with switching away from Game screen then back 2013-11-26 03:31:03 +00:00
drdev
e646ff1d1f Add checkbox to control whether list view or card view for Stack 2013-11-26 01:55:46 +00:00
drdev
9bb800ce43 Start adding card view to Stack, with preference to use current list view 2013-11-26 01:36:42 +00:00
ptx
6859ad2ad9 Some initial game simulation tests 2013-11-25 21:33:24 +00:00
drdev
19152790b2 Prevent dividing by zero when laying out cards 2013-11-24 23:03:51 +00:00
drdev
05751dbe1b Break up files in nonsingleton folder into existing controller and view folders 2013-11-24 21:16:23 +00:00
drdev
f35f6b3edd Cleanup whitespace 2013-11-24 20:56:11 +00:00
Maxmtg
8af7fadbf6 another 2 calls to gui removed 2013-11-24 19:21:30 +00:00
Maxmtg
9190ce038f remove imports of forge.gui from where they are not supposed to be (part 2 of many) 2013-11-24 11:14:51 +00:00
Maxmtg
bda47748f2 remove imports of forge.gui from where they are not supposed to be (part 1 of many) 2013-11-24 10:53:58 +00:00
Maxmtg
96084d7b26 disband forge.card package in gui module 2013-11-24 10:34:45 +00:00
Maxmtg
e96ff73b50 modified spells' canPlayAi, doTrigger and playFromEffect methods used by AI to include aiPlayer as 1st parameter 2013-11-24 10:02:58 +00:00
Hellfish
fcb8c4bdd6 *Fixed Charm of Vigor not having to be bought to be available 2013-11-24 09:44:28 +00:00
Maxmtg
c7c1d2d302 arrange Predicates for CardEdition 2013-11-24 09:35:43 +00:00
Maxmtg
21ea8e377c move card/CardCharacteristics.java to forge.game.card 2013-11-24 09:24:50 +00:00
Maxmtg
e9409d01a6 merged cardfactory into forge.game.card package 2013-11-24 07:17:43 +00:00
Maxmtg
a8c70a903f arrange packages 2013-11-24 07:09:23 +00:00
Maxmtg
c66ca97dfc move game Card class to forge.game.card package to ease further translation to game module 2013-11-24 06:59:42 +00:00
Maxmtg
5b5517ad29 replace TreeMapOfLists with Guava Multimap 2013-11-24 06:45:30 +00:00
drdev
c8de886967 Fix Flash of Insight reminder text 2013-11-23 23:13:54 +00:00
drdev
2ef19583a6 Fix displayed equip cost for M13 ring cycle 2013-11-23 23:06:01 +00:00
drdev
9e0ff5e635 Fix Civic Saber descriptions 2013-11-23 22:54:07 +00:00
drdev
427cef758f Fix Card Detail for Equip and Fortify cards 2013-11-23 22:49:54 +00:00
drdev
1cc1516feb Mention preference to hide reminder text in CHANGES.txt 2013-11-23 21:56:11 +00:00
drdev
daafa3f5c2 Add preference to Hide Reminder Text 2013-11-23 21:55:12 +00:00
drdev
9e20af7603 Cleanup whitespace 2013-11-23 21:37:37 +00:00
Chris
306a160df0 - Added a fluff piece to the changes.txt file. 2013-11-23 14:57:58 +00:00
Hellfish
b5686bcd2f *Removed first attempt code Charm of Vigor code. 2013-11-23 09:43:57 +00:00
Maxmtg
33dd245131 commit empty folders (otherwise eclipse refuses to move files) 2013-11-23 08:46:17 +00:00
Maxmtg
25334c27f1 (minor) remove IZone, rename gameAge to gameStage, remove unused imports 2013-11-23 08:34:14 +00:00
Maxmtg
3f20ebb15b prevent NPE for cases when new card is added 2013-11-23 08:21:49 +00:00
Maxmtg
37849b88e2 clean up core classes 2013-11-23 08:12:40 +00:00
drdev
800b3f8272 Tweak logic for formatting reminder text in italics 2013-11-23 06:39:42 +00:00
drdev
b2ecb3cb52 Mention reminder text formatting in CHANGES.txt 2013-11-23 06:25:27 +00:00
drdev
8a794f2e02 Display reminder text in italics 2013-11-23 06:21:26 +00:00
drdev
3c05e1674f Only show Workshop tab if running in Developer mode (for now) 2013-11-23 06:06:19 +00:00
drdev
a15b3c2a69 More card format fixes 2013-11-23 05:54:25 +00:00
drdev
10c138d64e Format mana batteries and a few other cards 2013-11-23 05:39:42 +00:00
drdev
99d1718498 Tweak formatting on Musician 2013-11-23 05:25:00 +00:00
drdev
515985dead Fix formatting of Volvers and Planar cards 2013-11-23 05:12:53 +00:00
drdev
e30c4532b8 Show regular and variant cards in Workshop 2013-11-23 05:03:07 +00:00
drdev
2ab5f19f79 Fix formatting of a couple cumulative upkeep cards 2013-11-23 04:55:17 +00:00
drdev
f5054558c2 Fix formating of Forecast and other cards 2013-11-23 04:50:31 +00:00
drdev
b726053164 Auto-select first card after doing search if no card otherwise selected 2013-11-23 04:38:34 +00:00
drdev
cc433b6708 Fix so PaperCard for card name doesn't change unless card renamed 2013-11-23 04:19:05 +00:00
drdev
e95e251161 Format mana costs for card scripts 2013-11-23 04:15:06 +00:00
drdev
75edc751f3 Format bestow costs 2013-11-23 03:45:47 +00:00
drdev
b4ba84a0d1 Fix Flash of Insight cost formatting and display {X} before generic cost 2013-11-23 03:29:14 +00:00
drdev
38074a1660 Fix so Card Detail updated when card script saved 2013-11-23 03:11:11 +00:00
drdev
ca5e20b1a9 Fix so rules not replaced when updated 2013-11-23 03:05:28 +00:00
drdev
c4db463338 Support saving script changes again 2013-11-23 02:54:52 +00:00
Maxmtg
34c2cb604f carddb editor will detect cases when rules are changed without rename 2013-11-23 00:11:07 +00:00
Maxmtg
f058e38004 CardRules.reinitializeFromScript 2013-11-23 00:03:51 +00:00
drdev
b38a8b5830 Format flashback cost on Firecat Blitz 2013-11-22 23:46:30 +00:00
drdev
8e76829a27 Format mana costs for Madness, Recover, and Miracle on instants/sorceries 2013-11-22 23:42:38 +00:00
Hellfish
f3bf092898 *Added Quest Item - Charm of Vigor: Let's you play best of 5 games rather than 3. 2013-11-22 23:03:49 +00:00
drdev
4dd2b87538 Rename allScripts hash map 2013-11-22 22:47:24 +00:00
Maxmtg
4d6930e903 prioritize text files over whatever found in zip 2013-11-22 18:10:06 +00:00
Maxmtg
3fecd16efd Have cardStorageReader read both zip and the files folder. There remains a task to replace duplicate cards 2013-11-22 17:09:07 +00:00
Maxmtg
29a535c71a moved CardStorageReader to core project 2013-11-22 16:51:38 +00:00
Maxmtg
3fd72f35df use concurrent map 2013-11-22 16:36:07 +00:00
Maxmtg
bb3d637738 adjust dependencies for CardScriptInfo 2013-11-22 16:32:56 +00:00
jendave
02fe620360 update guava 2013-11-22 09:25:24 +00:00
Hellfish
ebe0e350ff *Constructed defaults to 2 players to match previous behaviour 2013-11-22 05:41:52 +00:00
Sol
6dbe638a59 - Merfolk Seer wasn't displaying mana symbols in trigger cost 2013-11-22 04:42:22 +00:00
drdev
31b5f4181a Support displaying scripts in Workshop again 2013-11-22 03:21:37 +00:00
drdev
72d0cfdbbc Whitespace cleanup 2013-11-22 02:23:53 +00:00
drdev
f934764290 Prevent forge.profile.properties being accidentally committed to SVN 2013-11-22 01:38:33 +00:00
drdev
e28f809a58 Remove forge.profile.properties from SVN 2013-11-22 01:34:41 +00:00
Maxmtg
a88dd00a0d interface to edit cards 2013-11-21 23:37:34 +00:00
Hellfish
5d9de47fd5 *Expanded Constructed to up to 8 players, any amount AI or Human, to match up with the Variant update. 2013-11-21 22:54:30 +00:00
Maxmtg
7add28ad7d propper delete 2013-11-21 22:54:15 +00:00
Maxmtg
17b97aca28 hide some readers, collections and simple enums as nested classes, 2013-11-21 22:53:20 +00:00
Maxmtg
86b422230e added module 'game' 2013-11-21 21:32:49 +00:00
Hellfish
0193671453 *Fixed extra Field/Command/Hand views sticking around when for instance playing a game with 2 players after playing a game with 8 players. 2013-11-21 21:27:27 +00:00
Maxmtg
c4be1b8697 inlined type casts 2013-11-21 21:27:27 +00:00
Maxmtg
52f8880627 minor rearrangements in util package 2013-11-21 21:23:04 +00:00
Hellfish
f537e8cf78 *Prettyfied my previous addition. 2013-11-21 21:10:41 +00:00
Maxmtg
482af12b67 deck generation moved to core 2013-11-21 20:59:18 +00:00
Hellfish
2f85d50778 *Added the ability to specify multiple human (hotseat, of course) players or all AI for all variants 2013-11-21 20:25:14 +00:00
Hellfish
b51663c130 *Undoing Subclipse's mess 2013-11-21 19:46:05 +00:00
Hellfish
7ebc54352e Initial import. 2013-11-21 19:40:06 +00:00
jendave
6703e62823 minor doc fixes 2013-11-21 16:54:34 +00:00
Hellfish
e860e9e1af *"Remove All Counters" in a way that interacts other systems. Fixes Chronozoa + AEther Snap 2013-11-21 07:04:22 +00:00
Sloth
de3303abc9 - More use of activateForCost function. 2013-11-20 22:51:22 +00:00
Hellfish
a0695c08cc *Remove Inbound Tokens at appropriate places if the etb of the same token was replaced. Fixes Chronozoa. 2013-11-20 20:05:02 +00:00
Chris
c5aeb0785e - Cleared out the changes.txt file, now ready for new material.
- Added new card names to changes.txt.
2013-11-20 15:05:11 +00:00
Sloth
21b376848f - More use of activateForCost function. 2013-11-20 14:55:33 +00:00
swordshine
f8fe7e41b4 - Added Liar's Pendulum 2013-11-20 13:00:06 +00:00
Maxmtg
22caa0a408 updated references to org.apache.commons.lang version 2.6 to use version 3 ('cause forge used to import both 2.6 and 3.x versions of the named artifact) 2013-11-20 08:47:06 +00:00
Maxmtg
4d3945f5a4 moved all items to core, decks were included too. 2013-11-20 08:34:37 +00:00
Maxmtg
0786012ed8 rm ColorChanger.java (unused)
mv2core BoosterGenerator and UnOpenedProduct
2013-11-19 22:54:04 +00:00
Maxmtg
6e9a316460 remove UI references from CardStorageReader 2013-11-19 21:53:01 +00:00
Maxmtg
fd7d0e1d99 cleaned CardStorageReader of experimental code 2013-11-19 20:56:59 +00:00
Maxmtg
65199c7a81 moved cardFace and rules reader to core 2013-11-19 20:38:51 +00:00
Sloth
851094c523 - Added a doTriggerAINoCost function to RepeatAI. 2013-11-19 13:15:01 +00:00
Maxmtg
9b31032016 Moved cardDb and most of static data to core project. Had to rollback some incompatible changes. Sorry, drdev! 2013-11-19 07:40:58 +00:00
Sloth
a7fa173e52 - Content downloader will now show the number of item skipped. 2013-11-18 22:11:42 +00:00
Sloth
de4d83372c - Added 2 precons by Erazmus. 2013-11-18 20:59:32 +00:00
Sloth
c7f24490f3 - Some more work on the activateForCost function. 2013-11-18 20:57:25 +00:00
drdev
fabc7a3a27 Support updating card rules and display when saving script changes 2013-11-18 14:35:19 +00:00
swordshine
e830527f74 - Fixed other cards with optional decisions in ChangeZone effect 2013-11-18 12:48:02 +00:00
swordshine
5fc5feb636 - Fixed Cloudstone Curio 2013-11-18 12:41:19 +00:00
drdev
384af0001c Fix cursor positioning after undoing delete 2013-11-17 21:44:02 +00:00
drdev
2abc9b3f7c Create FUndoManager to encapsulate making undo/redo logic smarter and lumping typing changes together 2013-11-17 21:38:27 +00:00
drdev
9242f3439c Create FTextEditor to encapsulate a plain text editor with undo/redo support 2013-11-17 21:17:14 +00:00
drdev
b1ba8f0aa2 Add File menu and support Ctrl+S to save card in Workshop 2013-11-17 20:36:44 +00:00
drdev
20b3775280 Prompt to save card when switching to another card or another screen 2013-11-17 17:57:55 +00:00
drdev
c2bb321e17 Optimize determination of card script text being dirty 2013-11-17 08:33:00 +00:00
drdev
b0160287ba Add Workshop screen 2013-11-17 08:02:40 +00:00
drdev
284e2257f3 Fix Cascade 2013-11-16 21:43:57 +00:00
drdev
ec06d07f35 Breakup PrecostDesc$ of certain Entwine cards so mana cost part in CostDesc$
Make "Choose one" syntax consistent
2013-11-16 20:11:41 +00:00
drdev
5eca8807d8 Format mana costs for Echo, Cumulative Upkeep, and Unearth 2013-11-16 19:25:43 +00:00
drdev
5b3ee63299 Ignore forge-*/target directories for SVN 2013-11-16 19:22:41 +00:00
drdev
a6ffa3ae36 Update card scripts with CostDesc$ so its formatted 2013-11-16 19:17:44 +00:00
Sol
e021e66387 - Fixed Spell Description of MorphDown 2013-11-16 16:02:23 +00:00
Sol
eb70985551 - Fix Viridian Joiner description 2013-11-16 01:23:00 +00:00
Chris
cd6dc5158e [maven-release-plugin] prepare for next development iteration 2013-11-15 14:14:27 +00:00
Chris
942f30557c [maven-release-plugin] prepare release forge-1.5.5 2013-11-15 14:14:16 +00:00
Chris
1486d61e65 - Preparing the changes.txt file for the next beta build and release. 2013-11-15 13:57:23 +00:00
drdev
eb082d2f49 Fix abilities that used "tap" 2013-11-15 12:57:47 +00:00
drdev
7e6e691771 Ensure top of card text visible when first viewed in Card Detail 2013-11-15 12:14:03 +00:00
drdev
8e4962ceb1 Eliminate Card Detail flicker 2013-11-15 12:11:31 +00:00
drdev
414d82bd37 Fix The Tabernacle at Pendrell Vale mana format 2013-11-15 11:38:31 +00:00
drdev
4091f1d1d9 Fix Fleshwriter reminder cost format 2013-11-15 11:36:58 +00:00
drdev
fe0f4ddf99 Format Ninjutsu mana cost in reminder text 2013-11-15 11:34:27 +00:00
drdev
b0845c5795 Commit commented out imperfect code used for parsing ability in quotes 2013-11-15 11:24:44 +00:00
drdev
aeddb37d9d Format ability costs in quotes 2013-11-15 11:22:51 +00:00
drdev
1ff1c35486 Remove bullet in CHANGES.txt that no longer applies 2013-11-15 09:48:11 +00:00
drdev
6e585a7afa For now, if card only has 1 activated ability, don't show menu even if cost is automatic and undoable 2013-11-15 09:47:24 +00:00
Sloth
e0df16ee17 - Fixed AI using Exhume. 2013-11-15 09:42:15 +00:00
drdev
ae5cb7a17a Make ability menu items consistent regardless of containing mana symbol icons and make them respect menu item height 2013-11-15 09:40:47 +00:00
Sloth
8d79ed527f - Fixed a bug in ChooseCardEffect. 2013-11-15 09:37:08 +00:00
Sloth
d4bc84c6bd - Fixed Stormfront Riders. 2013-11-15 09:11:52 +00:00
drdev
9743a7d1b7 Mention fixing WUBRG order in CHANGES.txt 2013-11-15 09:03:48 +00:00
drdev
e5cffc623a Support updating colored mana order, phyrexian and hybrid mana format, and mana production abilities with multiple choices 2013-11-15 06:59:23 +00:00
drdev
9c0a559bce Update hybrid costs in abilities 2013-11-15 06:56:52 +00:00
drdev
b794bc5ee0 Update card ability descriptions containing choice of dual mana production 2013-11-15 06:26:33 +00:00
drdev
55c71d77e1 Fix colored mana order for card scripts 2013-11-15 06:04:12 +00:00
drdev
6914e30443 Fix colored mana order for card scripts 2013-11-15 05:48:47 +00:00
drdev
1c52e8e38a Update card ability descriptions containing choice of mana production 2013-11-15 03:00:09 +00:00
drdev
c38f169d1d Add space between ability description mana cost and reminder text 2013-11-15 00:58:24 +00:00
drdev
8f4b8dbf88 Prevent trimming spaces 2013-11-15 00:51:34 +00:00
drdev
b68f28b621 Update earwig_squad.txt prowl cost 2013-11-15 00:51:01 +00:00
drdev
a23eb2f869 Support outputting results from parse utility 2013-11-15 00:45:49 +00:00
drdev
8dfbf2b3b6 Update more card ability descriptions 2013-11-15 00:14:31 +00:00
drdev
70b0fab66a Use try/catch block to avoid crash from bad pattern 2013-11-14 23:27:08 +00:00
drdev
082e2ff2cd Add parse command line argument to allow performing function on all parsed cards 2013-11-14 23:16:28 +00:00
Sloth
12af50d473 - Update more card ability descriptions. 2013-11-14 22:54:50 +00:00
Sloth
b1cde02dd4 - Update more card ability descriptions with {T} symbol. 2013-11-14 22:22:19 +00:00
jendave
2d737ab092 a little progress on the Mac app bundle 2013-11-14 21:59:44 +00:00
jendave
8cd9220f36 update release plugin. Update site urls for new maven structure. 2013-11-14 17:08:54 +00:00
swordshine
838d4a98aa - Update more scripts 2013-11-14 13:50:40 +00:00
swordshine
d32bfea94e - Fixed Braid of Fire 2013-11-14 13:25:28 +00:00
swordshine
181a7f5b9c - Updated basic land abilities to display mana symbol icons 2013-11-14 10:57:51 +00:00
drdev
ee00b544f7 Support displaying Chaos icon in details 2013-11-14 09:20:29 +00:00
drdev
5548c71bda Update more card ability descriptions 2013-11-14 08:46:01 +00:00
drdev
ae7a6b79b7 Update more card ability descriptions 2013-11-14 08:27:50 +00:00
drdev
96d2338bea Update card ability descriptions so mana symbols are displayed as icons 2013-11-14 07:48:31 +00:00
drdev
21217e030b Code cleanup 2013-11-14 04:42:59 +00:00
drdev
1d63f4b4a1 Update CHANGES.txt 2013-11-14 04:19:34 +00:00
drdev
8843e5bfe7 Properly translate only mana costs to icons
Make snow and certain hybrid mana symbols display correctly
Show mana symbols in game prompt
2013-11-14 04:08:24 +00:00
Sloth
48b97f8632 - Fixed Balduvian Frostwaker. 2013-11-13 22:51:29 +00:00
jendave
20184fb4c0 ignore IntelliJ files 2013-11-12 08:46:35 +00:00
drdev
76000a90fb Update CHANGES.txt 2013-11-12 07:08:52 +00:00
drdev
4aebd350ee Support showing mana symbols in ability menu and card detail pane 2013-11-12 07:06:09 +00:00
Sol
13f4a0abb4 - Adding Enchant opponent line to Psychic Posssesion 2013-11-12 02:19:51 +00:00
drdev
35ea297090 Make target arrows appear in correct place in window mode 2013-11-12 02:15:55 +00:00
drdev
f11909d6da Prevent repeating shortcuts for abilities 2013-11-12 01:57:24 +00:00
jendave
5df82652b6 clean ups 2013-11-11 16:07:37 +00:00
Chris
8fde8ebe5f - Added new card names to changes.txt. 2013-11-11 13:43:52 +00:00
drdev
6bc20a8830 Update CHANGES.txt 2013-11-11 12:48:18 +00:00
drdev
0bbd9c103a Make menu items easier to click
Mention context menu ability select in CHANGES.txt
2013-11-11 12:39:18 +00:00
jendave
0b68e2ade6 re-org 2013-11-11 08:27:14 +00:00
jendave
1ca79539b6 update deps and re-org a few things 2013-11-11 08:27:00 +00:00
drdev
1c2c3d6d51 Ensure first ability selected in menu by default 2013-11-11 02:55:18 +00:00
drdev
bdb1243409 Prevent showing menu if no ability can be played 2013-11-11 02:36:44 +00:00
drdev
812d4ca519 Prevent returning ability that can't be played 2013-11-11 02:22:27 +00:00
swordshine
4e7e14cbf3 - Added Invasion Plans 2013-11-11 00:29:43 +00:00
swordshine
2064b6517e - Temporarily removed Arboria
- Fixed Quicksilver Dragon
2013-11-11 00:22:11 +00:00
drdev
c9f491a483 Show unplayable activated abilities disabled unless activator or zone restriction
Prompt for single activated ability unless mana ability
Show mana abilities before other abilities to match card order
2013-11-10 21:48:55 +00:00
Maxmtg
be2ec80f0c redirect dependency between Card and IPaperCard 2013-11-10 21:37:07 +00:00
drdev
1c13e8dc10 Show context menu to select ability instead of dialog 2013-11-10 20:25:25 +00:00
drdev
4748aa2262 Fix typo in function name 2013-11-10 18:56:41 +00:00
swordshine
a3376b0502 - Added Arboria, Premature Burial, and Sacred Ground 2013-11-10 05:14:26 +00:00
swordshine
c073d39cd6 - Updated scripts 2013-11-10 04:51:16 +00:00
Chris
b508f78f04 Moved the CHANGES.txt, LICENSE.txt, forge.profile.properties.example and README.txt files to forge-gui folder. 2013-11-09 15:33:38 +00:00
Chris
8424da8311 - Added new card names to changes.txt. 2013-11-09 15:17:05 +00:00
swordshine
cfd9d55668 - Added Quicksilver Dragon 2013-11-09 10:01:48 +00:00
swordshine
417e3bb104 - Added Reflecting Mirror 2013-11-09 09:36:45 +00:00
swordshine
320d4f62d9 2013-11-09 08:24:47 +00:00
Maxmtg
6c712d86fb moved a few classes to core module 2013-11-09 02:27:38 +00:00
jendave
a0479f9610 Test run of moving files to modules. 2013-11-08 23:21:11 +00:00
Maxmtg
374a744a44 added java nature to forge-gui project, set up classpath (copied it from former project) 2013-11-08 21:57:20 +00:00
Maxmtg
81416d49de added reference from core to guava, set runtime version of ai and core to 1.7 2013-11-08 21:35:14 +00:00
Sloth
31ebd62c83 - Added more precons by Erazmus. 2013-11-08 20:18:39 +00:00
jendave
93dd4af6ed fix eclipse issues 2013-11-08 18:39:59 +00:00
jendave
9f0308dd66 Start of re-org into modules 2013-11-08 10:05:52 +00:00
Sloth
f9298703d4 - Added some precons by Erazmus. 2013-11-08 08:52:31 +00:00
Sloth
3992032e8e - Added Rebound. 2013-11-07 23:08:44 +00:00
Sloth
58dacc0789 - Added Silver Wyvern. 2013-11-07 22:54:17 +00:00
Chris
b3280923d9 - Added new card names to changes.txt. 2013-11-07 14:49:02 +00:00
Sloth
e83da9ff9c - Some safety fixes for Muck Drubb. 2013-11-07 09:17:48 +00:00
Sloth
8b1d0fc759 - Added Muck Drubb. 2013-11-06 22:45:35 +00:00
Sloth
ff869933be - Cleanup. 2013-11-06 22:15:51 +00:00
Sloth
fb0af4dc18 - Start of using isValid function for SpellAbilities. 2013-11-06 19:39:34 +00:00
Sloth
6f5551d78d - Fixed Razia's Purification. 2013-11-05 22:32:40 +00:00
swordshine
a90efe4939 - Fixed Mirror Strike 2013-11-05 02:37:33 +00:00
Sloth
46c37b9d82 - Updated mtg-data.txt.
- Added Oracle texts to C13 cards.
2013-11-04 21:10:55 +00:00
drdev
3e23eb517b Use FMouseAdapter to make catalog and deck tables more responsive 2013-11-04 03:17:28 +00:00
Sloth
9cf75ea844 - Script fixes and updates. 2013-11-03 22:02:28 +00:00
drdev
5565b4a4d0 Retain column sort direction between sessions 2013-11-03 18:44:14 +00:00
drdev
bde5967ef4 Remember column order in Deck Editor 2013-11-03 17:47:57 +00:00
Chris
f3560238fe - Added new card names to changes.txt. 2013-11-03 13:52:06 +00:00
swordshine
f97f489aba - Added Juxtapose 2013-11-03 13:28:12 +00:00
swordshine
454b7715c0 - Added Scheme: Your Inescapable Doom 2013-11-03 11:46:46 +00:00
swordshine
ac1e279235 - Fixed LibraryPosition 2013-11-03 07:50:02 +00:00
swordshine
5950162663 - Added Johan
- Updated mtgdata
2013-11-03 07:32:08 +00:00
Chris
6a52b46192 - Added a fluff piece to the changes.txt file. 2013-11-02 12:42:27 +00:00
Sloth
f5558eec7f - Updated and fixed some C13 cards. 2013-11-02 07:37:33 +00:00
Chris
0c39f596a3 - Cleared out the changes.txt file, now ready for new material. 2013-11-01 23:09:20 +00:00
Sloth
ba3c544484 - Fixed Saltskitter. 2013-11-01 19:42:54 +00:00
jendave
e0063727a9 update to latest deps and plugins. Did not update to latest jetty and guava since they may cause issues 2013-11-01 16:27:50 +00:00
swordshine
7b68821a8c - Merged C13 Branch
- Fixed Curse of Chaos, Curse of the Forsaken, Fell Shepherd
2013-11-01 14:19:28 +00:00
Chris
4a84b408d4 [maven-release-plugin] prepare for next development iteration 2013-11-01 13:06:01 +00:00
Chris
b9aec4ffb8 [maven-release-plugin] prepare release forge-1.5.4 2013-11-01 13:05:50 +00:00
Chris
1a958e758f - Preparing the changes.txt file for the next beta build and release. 2013-11-01 12:55:46 +00:00
RumbleBBU
74527319aa Relabeled the starting pool color distribution options to make them more intuitive. Merged the randomization option to the pulldown menu. 2013-10-31 09:48:35 +00:00
drdev
a66e7ad14f Add click effect to opague and selectable FLabels to make them feel more like buttons 2013-10-30 14:40:36 +00:00
drdev
e4b91416dd Update DeckLister to use FMouseAdapter 2013-10-30 14:00:37 +00:00
drdev
7735c705c0 Fix so right-clicking stat label that's the only selected one in group will re-select all other labels in group 2013-10-30 13:15:56 +00:00
drdev
31ab48d0d4 Let FMouseAdapter raise click if mouse moved outside component then back inside before releasing mouse 2013-10-30 13:02:44 +00:00
drdev
e5cf9da31d Update FLabel to use new FMouseAdapter 2013-10-30 12:39:10 +00:00
drdev
9eac64ab7b Create FMouseAdapter to facilitate more reliable and responsive click handling
Improve responsiveness of table sorting in ItemManagers
Prevent events on editor tables being duplicated, resulting in poor performance and inverting sort sometimes not working
2013-10-30 12:29:30 +00:00
swordshine
7131cebf7d - Fixed last commit 2013-10-30 04:49:55 +00:00
swordshine
bfb4a5ee57 - Commander 2013 edition file 2013-10-30 03:04:38 +00:00
drdev
21e250bf36 Prevent auto-inverting sort direction when switching away from editor and back 2013-10-28 14:04:31 +00:00
swordshine
f5b1ac970b - Fixed Scroll Thief and Stealer of Secrets 2013-10-28 03:04:36 +00:00
drdev
c85f14f27c Fix crash when taking over another player's turn 2013-10-27 19:14:00 +00:00
drdev
c0cf6198a4 Mention addition of concede confirmation in CHANGES.txt 2013-10-27 06:53:39 +00:00
drdev
4d3012fee7 Ensure Match screen active before showing concede prompt 2013-10-27 06:52:17 +00:00
drdev
75726dc272 Make user confirm that they want to concede the current game 2013-10-27 06:47:20 +00:00
drdev
260724af80 Fix so Match screen uses the correct controller (so correct menus built for example) 2013-10-27 06:33:26 +00:00
drdev
2b37cf217f Updated CHANGES.txt for combo box visual tweaks 2013-10-27 06:23:03 +00:00
drdev
669ff579c5 Fix so combo boxes on Constructed home screen update when skin switched 2013-10-27 06:17:23 +00:00
drdev
d0e65fe1bc Use FComboBox in place of JComboBox 2013-10-27 05:54:22 +00:00
drdev
4485e46801 Remove unused FComboBox properties 2013-10-27 05:27:51 +00:00
drdev
2265687c75 Make combo box be all one piece 2013-10-27 05:12:57 +00:00
drdev
f70523bf14 Update CHANGES.txt for Draft fixes 2013-10-27 03:56:13 +00:00
drdev
48013b9339 Fix a couple more issues with drafting 2013-10-27 03:46:20 +00:00
drdev
e9e1caf9d1 Prevent losing draft picks when switching away and back
Prevent canceling naming draft pool which caused a crash
2013-10-27 03:29:20 +00:00
drdev
5b17e2beda Make it so Draft screen closes when draft process finished and Draft Deck Editor immediately opens 2013-10-27 03:17:45 +00:00
drdev
19bc74f88d Fix a few remaining places that would show prompts outside main window 2013-10-27 02:52:14 +00:00
drdev
ae0069652a Fix switching between Editors 2013-10-26 21:49:26 +00:00
Sloth
5ec7f01b7a - Added the new quest deck Robot Santa 3. 2013-10-26 20:55:39 +00:00
Sloth
691f798f90 - Replaced the interface ITargetable with the class GameObject (which reflects the term used in the rules for players, cards and spell/abilities).
- Preparations for extending isValid and hasProperty functions for spell/abilities.
2013-10-25 21:41:38 +00:00
Chris
d5bef0861b - Added new card names to changes.txt. 2013-10-24 13:27:07 +00:00
swordshine
87dd938cde - Added Graxiplon 2013-10-24 08:54:27 +00:00
Sloth
c4e0d3e7ce - Added Glarecaster. 2013-10-23 21:52:06 +00:00
Sloth
c705722bdc - Updated some AI SVars. 2013-10-23 15:53:08 +00:00
Sloth
6424fa151a - Added a hard version of the Leela quest deck. 2013-10-23 14:04:44 +00:00
swordshine
0646e49359 - Added Scheme: Only Blood Ends Your Nightmares
- Added Cyclopean Tomb
2013-10-23 00:24:38 +00:00
Sloth
6ddae9e9da - Updated some Shandalar world quest decks. 2013-10-22 20:34:41 +00:00
Sloth
efc7be1637 - Fixed face-down cards moving to Hand or Library not being turned face up. 2013-10-22 13:41:16 +00:00
Chris
1de80be872 - Added new card names to changes.txt. 2013-10-22 13:02:54 +00:00
swordshine
f8740f1268 - Updated scripts (Psychogenic Probe should trigger only once for these cards) 2013-10-22 12:19:08 +00:00
swordshine
d6f30c9220 - Added Dichotomancy 2013-10-22 12:02:28 +00:00
swordshine
f2d7004b02 - C13: Added From the Ashes 2013-10-22 11:08:14 +00:00
swordshine
6ecf800bab - Added Seeds of Innocence 2013-10-22 10:23:24 +00:00
Sloth
6f92a834da - Some deck updates. 2013-10-21 21:06:56 +00:00
Sloth
a7a85d22d5 - Added some card specific AI for Serene Master and Shape Stealer. 2013-10-21 20:18:05 +00:00
Sloth
178024e248 - Fixed AI freeze caused by Fireball. 2013-10-21 19:53:04 +00:00
swordshine
798e93af46 - Fixed Opal Palace (using an etbCounter replacement now) 2013-10-21 13:40:36 +00:00
swordshine
3cb125ae4a - C13: Added Opal Palace 2013-10-21 12:12:01 +00:00
swordshine
30aed49e87 - C13: Added Serene Master (please improve AiAttackController.declareAttackers and AiBlockController for this card) 2013-10-21 06:27:48 +00:00
swordshine
d0173a2341 - Fixed r23523 LibraryPosition 2013-10-21 02:56:07 +00:00
drdev
fb7a61ab30 Fix crash when purchasing items in the Bazaar 2013-10-20 23:07:37 +00:00
Sloth
13e09c73bc - Fixed text of Force of Nature. 2013-10-20 07:34:25 +00:00
swordshine
6fdaf4fda4 - C13: Added Tempt with Glory, Tempt with Reflections and Unexpectedly Absent 2013-10-20 05:24:56 +00:00
Chris
ba79089bed - Cleared out the changes.txt file, now ready for new material.
- Added new card names to changes.txt.
2013-10-19 16:22:03 +00:00
Sloth
a8670467be - Fixed Tangle Wire. 2013-10-19 11:26:31 +00:00
swordshine
4dd84cdb2e - C13: Added Naya Soulbeast and Tempt with Discovery 2013-10-19 04:09:38 +00:00
Sol
028d6c0a1f - Using CARDNAME instead of Seasinger for ability stealing cards 2013-10-19 03:36:39 +00:00
swordshine
ca2584f598 - C13: Added Sudden Demise, Tempt with Vengeance, Terra Ravager, Toxic Deluge, Widespread Panic and Witch Hunt 2013-10-19 00:49:33 +00:00
Sol
17e96250f7 - Fix issue with a few Avatars that spawn cards outside of the game not knowing what game they are apart of 2013-10-18 21:48:38 +00:00
Chris
79fdd21817 [maven-release-plugin] prepare for next development iteration 2013-10-18 14:33:15 +00:00
Chris
a0daa7c4be [maven-release-plugin] prepare release forge-1.5.3 2013-10-18 14:33:05 +00:00
Chris
000d0d3119 - Preparing the changes.txt file for the next beta build and release. 2013-10-18 14:21:49 +00:00
Chris
3b01b4f3dd - Added new card names to changes.txt. 2013-10-18 12:54:11 +00:00
swordshine
f0613e9660 - C13: Added Act of Authority and Angel of Finality 2013-10-18 05:43:51 +00:00
Sloth
1c51ed37c2 - Fixed an issue with the "May be played by your opponent" keyword. 2013-10-17 21:18:24 +00:00
Chris
2bfcd92da9 - Added new card names to changes.txt. 2013-10-17 12:50:02 +00:00
RumbleBBU
0bf676448b Fixed a bug that caused the Quest starting pool reduction incorrectly affect randomized starting pools. 2013-10-17 12:43:46 +00:00
RumbleBBU
5bceff414e Bias steepness now reduces the total amount of cards in your Quest starting pool. Effect of steepness slightly increased to compensate for this in your chosen color.
Slightly tweaked and relabeled the UI components for color preference selection, to make them slightly more intuitive.
2013-10-17 10:11:31 +00:00
swordshine
1b65231e30 - C13: Added Illusionist's Gambit and True-Name Nemesis 2013-10-17 05:23:38 +00:00
drdev
8b39b69bb7 Move/rename FControl.Screens to FScreen and make that define the Navigation tab data instead of INavigationTabData
Make it so each Deck Editor type appears in its own tab
Make Bazaar screen act more like other screens
2013-10-17 04:23:48 +00:00
Chris
4dfab45544 - Added new card names to changes.txt. 2013-10-16 12:53:43 +00:00
swordshine
f046dbf3cc - C13: Added Surveyor's Scope 2013-10-16 06:34:58 +00:00
swordshine
2e5f9350eb - Replicate is a trigger now 2013-10-16 00:35:36 +00:00
Sloth
938784d6e8 - Fixed Kiki-Jiki, Mirror Breaker not granting haste to transformed cards. 2013-10-15 13:59:43 +00:00
Chris
02c582a695 - Added new card names to changes.txt. 2013-10-15 13:05:01 +00:00
swordshine
2851d49c3b - C13: Added Eye of Doom 2013-10-15 12:15:33 +00:00
swordshine
e88af1f6ba - Converted Madness 2013-10-15 10:48:32 +00:00
swordshine
da3b6bf19e - Converted Persist/Undying to script (these triggers can be stifled and copied now) 2013-10-15 00:21:23 +00:00
Chris
da28e10ac7 - Added new card names to changes.txt. 2013-10-14 13:42:37 +00:00
swordshine
e6b260cc60 - C13: Added Curse of Chaos 2013-10-14 04:12:40 +00:00
Sloth
2cea9debcf - Added Carom. 2013-10-13 19:26:17 +00:00
swordshine
768a26a5d4 - Converted Tangle Wire to script 2013-10-13 08:33:38 +00:00
swordshine
0e251ffb6a - Converted Drop of Honey and Porphyry Nodes to script 2013-10-13 08:00:44 +00:00
swordshine
74c04ea561 - Cleanup 2013-10-13 07:20:08 +00:00
swordshine
e92cc2735b - Converted Braid of Fire to script 2013-10-13 07:15:59 +00:00
swordshine
6a94535b78 - Converted Intruder Alarm, Smoke and Stoic Angel to script 2013-10-13 05:24:17 +00:00
swordshine
17ad490f97 - Converted Damping Field and Imi Statue to script 2013-10-13 05:07:07 +00:00
swordshine
704e4c4ef7 - Converted Winter Orb and Mungha Wurm to script 2013-10-13 04:57:08 +00:00
Chris
36a301275e - Added new card names to changes.txt. 2013-10-12 20:20:15 +00:00
drdev
bb2a01512e Make disabled close buttons appear disabled
Fix contrast skin colors
2013-10-12 20:17:52 +00:00
Sloth
ad73c9391d - Added the WU Heroic deck Bilbo Baggins 2 with help from Nordos. 2013-10-12 17:13:07 +00:00
swordshine
ce33d146d0 - Converted Land Equilibrium to script 2013-10-12 13:06:37 +00:00
Sloth
055695890e - Cleanup. 2013-10-12 13:02:12 +00:00
swordshine
028579eed4 - Added Protective Sphere 2013-10-12 11:20:54 +00:00
swordshine
5c836228f7 - Added Spellweaver Volute 2013-10-12 05:48:07 +00:00
swordshine
0663eee49a - Added Takklemaggot 2013-10-12 02:38:30 +00:00
dripton
4d9205699b Fix typo in comment 2013-10-11 15:12:52 +00:00
drdev
d8a5993a28 Ensure close buttons disabled along with navigation tabs 2013-10-11 06:11:31 +00:00
drdev
6e7e19fd34 Disable navigation tabs while overlay open 2013-10-11 05:56:22 +00:00
drdev
9e55ee9be1 Improve animation of navigation bar reveal and prevent it being stuck open with auto-hiding 2013-10-11 05:41:06 +00:00
drdev
ae93665645 Fix so remaining dialogs show up on top of Forge, such as sideboard 2013-10-11 01:52:50 +00:00
drdev
7eb84bb6a3 Update tooltip for X button based on current screen and close action 2013-10-11 01:18:39 +00:00
drdev
3006cc9431 Ensure previous game ended when continuing Guantlet 2013-10-11 00:32:22 +00:00
Sloth
480629953b - Fixed Ghoulcaller's Chant. 2013-10-10 21:59:30 +00:00
dripton
c54ed09d38 Add try/catch to hiddenOriginCanPlayAi
If a SpellAbility's origin is something like "Graveyard,Library",
ZoneType.smartValueOf throws an IllegalArgumentException.  Catch
this exception and return false.  This prevents the crash, but
means that the AI still can't play cards like Doomsday.

Fixes bug 745
2013-10-10 14:29:53 +00:00
drdev
a098b56339 Fix typos 2013-10-10 03:19:28 +00:00
drdev
7a9f8d9788 Add setting to control behavior of X button in upper right (Close Screen vs. Exit Forge) 2013-10-10 03:06:05 +00:00
Sloth
7bd822b96a - Fixed human player not being able to activate mana abilities as a spell/ability is played when Mana produced replacement effects are around. 2013-10-09 13:57:59 +00:00
swordshine
d20e9d5629 - Fixed Dark Betrayal 2013-10-09 10:34:20 +00:00
RumbleBBU
9b61a99dc3 Added a preference to adjust color bias steepness when using color-biased Quest starting pools. 2013-10-09 09:49:38 +00:00
drdev
4c1f670147 Set dialog default to Yes when exiting Forge without game active
Ensure Deck Editor visible if and when "Save Changes?" dialog would appear
2013-10-09 05:10:59 +00:00
drdev
c05d299fe4 Always prompt user before exiting or restarting Forge 2013-10-09 04:45:44 +00:00
drdev
0ba8b530fe Fix so quitting Quest games works with tabs
Prevent adding multiple game tabs
2013-10-09 04:33:45 +00:00
drdev
0a6f7afeff Add navigation tab for Bazaar
Prevent arrow button remaining visible when switching to Bazaar from Home screen
2013-10-09 01:56:03 +00:00
Sloth
483f274bac - Fixed my commit r23388. 2013-10-08 21:15:03 +00:00
Chris
1fd36a4623 - Added new card names to changes.txt. 2013-10-08 13:55:52 +00:00
drdev
3b1ab80c1c Add navigation tabs for switching between Home, Deck Editor, and Match screens
Remove Deck Editor and Exit Forge buttons home screen
Exit Forge when X button in upper right clicked
Add safety checks before exit or restart
Show warning if you try to Start a game while one is already active (at least for now)
2013-10-08 13:07:33 +00:00
RumbleBBU
abe0cec346 - Added an experimental UI that allows you to choose a preferred color in new Quest games. Also added a "Balanced color distribution" checkbox that can be unchecked to completely randomize the color distribution in new Quest games.
- Minor checkstyle fixes to old issues in VSubmenuQuestData and CSubmenuQuestData.
2013-10-08 12:32:42 +00:00
spr
6e1e22d6cb - Refactor GamePlayerUtil. 2013-10-08 10:04:32 +00:00
drdev
7650ec9323 Minimize if switching from Full Screen Forge to outside application window 2013-10-08 09:20:47 +00:00
spr
fe3fedaf64 - Renamed "Themed ComboBox" setting to "Enable Themes" to better reflect its purpose. 2013-10-08 07:16:52 +00:00
spr
f21f187890 - Removed redundant Visual Themes section from Game Settings -> Preferences. 2013-10-08 07:10:59 +00:00
spr
41e164d131 - Removed redundant Card Overlay Options section from Game Settings -> Preferences. 2013-10-08 07:04:28 +00:00
drdev
adb6a0b7f0 Fix so Deck Importer and other JDialogs display centered over main Forge window 2013-10-08 02:11:50 +00:00
drdev
31618c1611 Mention dialog fix in CHANGES.txt 2013-10-08 01:25:28 +00:00
drdev
6eba60638b Prevent Full Screen Forge being minimized when deactivated (such as by opening JOptionPane dialog) 2013-10-08 01:15:29 +00:00
drdev
e4040d4a47 Fix so JOptionPane dialogs always display at center of main window by default 2013-10-08 00:43:34 +00:00
drdev
c53cd32291 Fix so, when maximized, Forge doesn't extend below top of taskbar if screen has a top inset 2013-10-07 23:07:42 +00:00
drdev
172ca340ae Disable Forge button and Forge menu shortcut keys while overlay open 2013-10-07 22:53:14 +00:00
drdev
a8451abea4 Delay hiding titlebar a half second after becoming full-screen 2013-10-07 22:26:02 +00:00
drdev
cdf67a3865 Mention fix to Mac minimize crash 2013-10-07 22:05:31 +00:00
Sloth
e2f2fc4804 - Added a medium version of the Hugo Drax deck. 2013-10-07 20:41:08 +00:00
spr
db9a451e32 - Added option to replace default "Human" with custom name during gameplay. (http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=11553). 2013-10-07 19:56:00 +00:00
spr
a8cf682f71 - Added very simple About box to display Forge version. 2013-10-07 19:46:05 +00:00
spr
0c721f1776 - FNavBar tweak - Revealspeed = 200, revealDelay = 100. 2013-10-07 19:39:48 +00:00
Chris
f8194aac7a - Added new card names to changes.txt. 2013-10-07 13:14:57 +00:00
swordshine
15dd60ff3e - Update the script for Chained to the Rocks 2013-10-07 12:45:55 +00:00
drdev
d54441a9b2 Update CHANGES.txt for Full Screen support 2013-10-07 06:59:19 +00:00
drdev
4e75bfb4d0 Remove status bar, instead using tooltips for menu hints
Prevent overlays showing on top of titlebar
2013-10-07 06:52:41 +00:00
drdev
3e350d03c6 If titlebar unlocked or window made full-screen, delay hiding titlebar until mouse moves away 2013-10-07 05:42:10 +00:00
drdev
2fa44e1ae2 Always show Full Screen button right of Minimize button 2013-10-07 05:23:43 +00:00
drdev
1e5244cee0 Only allow titlebar being hidden when in Full Screen mode
Ensure Full Screen window appears on correct monitor
Add buttons to toggle Full Screen and lock/unlock titlebar
Make clock appear in titlebar when Full Screen and hiding status bar
Prevent moving window or double-click restore down when Full Screen
2013-10-07 05:17:27 +00:00
swordshine
6043c2738d - Added Snowblind 2013-10-07 05:09:55 +00:00
drdev
013cf5eb13 Disable Direct3D to improve rendering performance 2013-10-07 02:37:03 +00:00
drdev
a413fe2dc1 Ensure full-screen still works after using Set Window Size when in in Full Screen mode 2013-10-06 16:14:02 +00:00
drdev
a2bf02eb82 Support toggling Full Screen with F11 on all platforms
Fix way window state is updated (minimized/normal/maximized/full screen)
2013-10-06 16:08:29 +00:00
swordshine
229485494a - Update scripts 2013-10-06 11:40:05 +00:00
Hellfish
4ea3439667 *Updated Kederekt Parasite for multiplayer 2013-10-06 09:07:17 +00:00
Sloth
4154d31143 - Fixed possible NPE caused by Haunt. 2013-10-06 08:44:18 +00:00
Hellfish
30b660f802 *Missed a vital piece of the AI commander pay fail fix. 2013-10-06 08:08:39 +00:00
drdev
b79cf45778 Prevent Forge covering up taskbar when maximized 2013-10-05 22:53:47 +00:00
drdev
c6e9cbd69b Skin tooltips 2013-10-05 22:12:51 +00:00
drdev
7e493ed129 Change constants to static 2013-10-05 21:53:40 +00:00
drdev
c3ed6ebe79 Make reveal speed easier to tweak 2013-10-05 21:47:32 +00:00
Hellfish
27e33ec1b1 *Fixed AI failing to pay for recasting commander. 2013-10-05 18:02:42 +00:00
Chris
7601d5a2bd - Cleared out the changes.txt file, now ready for new material.
- Added new card names to changes.txt.
2013-10-05 13:24:12 +00:00
swordshine
a9fb42eb15 - Added Excavator 2013-10-05 11:38:53 +00:00
Sloth
cd9cdbf1be - Added AEtherplasm. 2013-10-05 11:38:33 +00:00
swordshine
e68a716587 - Added Elemental Resonance 2013-10-05 06:49:09 +00:00
swordshine
bab5672669 - Added Charmed Pendant 2013-10-05 06:31:54 +00:00
drdev
80f083e141 Increase speed and responsiveness of titlebar reveal 2013-10-05 00:23:08 +00:00
Sloth
91d37b38cc - Fixed Ghazban Ogre. 2013-10-04 19:55:21 +00:00
Chris
9349fa9217 [maven-release-plugin] prepare for next development iteration 2013-10-04 16:25:23 +00:00
Chris
748523f9cf [maven-release-plugin] prepare release forge-1.5.2 2013-10-04 16:25:13 +00:00
Chris
e64336abe9 - Preparing the changes.txt file for the next beta build and release. 2013-10-04 16:14:56 +00:00
RumbleBBU
15450a7fba - Added supporting infrastructure for manipulating the initial card distribution in new Quest games. The user interface components that actually enable this feature will be added after the next beta.
- Lots of checkstyle fixes to old issues.
2013-10-04 11:52:56 +00:00
drdev
ad2f63cd8f Fix so Forge menu items update from skin change properly 2013-10-04 06:43:41 +00:00
drdev
dbd3d956fb Avoid losing hidden title bar setting when switching to window mode and back to full screen 2013-10-04 06:12:15 +00:00
drdev
aabb4399ed Support temporarily revealing hidden title bar by moving mouse to top of screen 2013-10-04 05:27:18 +00:00
drdev
a99386ac1d Show clock in titlebar if maximized and status bar hidden 2013-10-04 02:43:14 +00:00
Sloth
b400f22d15 - Fixed description of Nest Invader. 2013-10-03 18:12:03 +00:00
moomarc
8843054b89 - New skin added 2013-10-03 16:34:14 +00:00
Sloth
8c8bde0799 - Fixed cost lists not using LKI's (once again). 2013-10-03 11:23:21 +00:00
drdev
109a990b28 Dim status bar text color and fix padding right of clock 2013-10-03 09:26:31 +00:00
drdev
8e9ac2e3e7 Make status bar text look better aligned 2013-10-03 09:05:44 +00:00
drdev
c0ad9b1b71 Update CHANGES.txt for Forge button changes 2013-10-03 08:37:11 +00:00
Maxmtg
01609a1f29 adjusted visibility of listInSync, removed unused import, removed test that does not test draft rankings anyway 2013-10-03 08:26:30 +00:00
drdev
2f5219615d Create Forge button which, when clicked, displays popup menu containing items from old menu bar
Support hiding status bar (F12) and saving title bar and status bar visibility between sessions
Changed F1 to be a shortcut for launching the Forge wiki
2013-10-03 08:26:11 +00:00
spr
91cd93783f - Fix: Constructed home screen "Game" menu was not being cleared from MenuBar when switching to other home screens; Menubar was not being repainted properly; 2013-10-03 08:17:44 +00:00
Maxmtg
2d8e4e9053 removed some (not all) slowdonws in quest card shop when owner of a big collection purchases a fatpack. (there were N redraws of owned card list instead of just one) 2013-10-03 08:06:10 +00:00
swordshine
9500b3a5ae - Updated scripts 2013-10-03 07:37:00 +00:00
swordshine
84e124bbf5 - Updated Cube by Juzamjedi 2013-10-03 07:28:58 +00:00
drdev
0d0377ae4a Remove clock from titlebar 2013-10-03 02:14:25 +00:00
drdev
9e1ec67253 Move version and clock to new status bar 2013-10-03 02:11:03 +00:00
drdev
4f8ee5ea52 Increase height of titlebar and size of minimize, maximize, and close icons
Fix so minimize, maximize, and close buttons allow clicking very top of screen and allow canceling click by moving mouse away before releasing
2013-10-03 00:50:31 +00:00
drdev
56654ffcb1 Cache time formatter 2013-10-03 00:28:55 +00:00
Chris
ac48d3634b fixed 2 broken pic URLs. 2013-10-02 13:45:03 +00:00
spr
934e4cbb2c - Constructed game now remembers the last deck played (both left and right decks) and restores at next startup.
- Default human deck type is Preconstructed decks.
2013-10-02 13:35:09 +00:00
Chris
53e631d65f - Cleared out the changes.txt file, now ready for new material. 2013-10-02 12:47:46 +00:00
swordshine
1483d7c969 - update some SVars 2013-10-02 08:29:48 +00:00
spr
71ddee1033 - Constructed screen updates based on feedback. 2013-10-02 06:54:59 +00:00
Maxmtg
480bba7a8c making multimaps in combat class synchronized 2013-10-01 20:40:28 +00:00
Chris
9c4c529c62 [maven-release-plugin] prepare for next development iteration 2013-10-01 14:22:19 +00:00
Chris
2df834804e [maven-release-plugin] prepare release forge-1.5.1 2013-10-01 14:22:10 +00:00
Chris
fb5fab037e - Added new card names to changes.txt.
- Preparing the changes.txt file for the next beta build and release.
2013-10-01 14:09:08 +00:00
spr
fc2e170d09 - Titlebar clock should now display time using format determined by system locale. 2013-10-01 06:32:38 +00:00
swordshine
77602a2aa2 - Fixed NPE for Dev mode 2013-10-01 01:57:52 +00:00
swordshine
dd668cb0fe - Added Reality Twist and Ritual of Subdual 2013-10-01 01:50:32 +00:00
spr
2a7b1f3c68 - Deck category radio buttons replaced by combo; transparent deck list. 2013-09-30 21:38:16 +00:00
spr
05b4a064ab - moved FDeckChooser to new folder. 2013-09-30 21:29:51 +00:00
Sloth
e6f64aebd1 - Cleanup. 2013-09-30 18:25:59 +00:00
spr
e2d9006e5c - Constructed game launch screen revamp (phase 1); Busy indicator added to theme switch menu. 2013-09-30 08:00:52 +00:00
Maxmtg
d991861421 DeckImport - applied skin and enabled filter to import cards 'not older than' chosen date 2013-09-30 06:51:08 +00:00
Maxmtg
c04d43ac66 + methods to get latest card by a certain date 2013-09-30 06:00:57 +00:00
Maxmtg
9cd7e8e034 combat event attackers declared - used google multimap 2013-09-30 03:17:05 +00:00
Maxmtg
ee198870f7 carddb - use google Multimap 2013-09-30 03:16:47 +00:00
Maxmtg
5138ba7605 correct file for FTV:20 2013-09-30 02:59:55 +00:00
dripton
426fab34bc Ugly workaround for IndexOutOfBoundsException when one thread
reads hiddenExtrinsicKeyword while another thread modifies it.

Fixes bug reported in 
http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=6333&start=2445#p133874
2013-09-29 20:44:59 +00:00
drdev
72b31ac9d0 Skin resizable window border 2013-09-29 19:30:10 +00:00
drdev
c957dab3d2 Add digital click to titlebar when full-screen 2013-09-29 19:00:09 +00:00
drdev
f8e522fd1e Allow menu item shortcuts to work when menu hidden 2013-09-29 17:50:08 +00:00
drdev
5ace15ac38 Support Layout > View > Titlebar (F11) to toggle visibility of titlebar 2013-09-29 17:19:05 +00:00
drdev
4f8ef1ef34 Un-maximize when Set Window Size used
Allow dragging titlebar when maximized to un-maximize and move window
2013-09-29 16:43:14 +00:00
drdev
8c580acc42 Prevent being able to resize window when hovering over main menu 2013-09-29 16:22:12 +00:00
drdev
3452039d42 Show icon on titlebar 2013-09-29 16:14:04 +00:00
Chris
20202b08f9 - Added a fluff piece to the changes.txt file.
- Added new card names to changes.txt.
2013-09-29 14:07:48 +00:00
swordshine
fdf0a30843 - Added Chaos Moon, Infernal Darkness and Pale Moon 2013-09-29 13:26:52 +00:00
Sloth
f807986e44 - Added experimental AI support for ProduceMana replacement effects.
- Added Naked Singularity by swordshine.
2013-09-29 10:28:00 +00:00
Maxmtg
358602ad21 developed workaround for bug 744 2013-09-29 09:36:56 +00:00
drdev
321805e786 Support skinned titlebar for main window
Slightly reduce height of main menubar
2013-09-29 06:59:55 +00:00
swordshine
141025a02c - Added Deep Water
- Vanguard: Added Mirri
2013-09-29 05:00:37 +00:00
swordshine
526b86ac16 - Added Pulse of Llanowar 2013-09-29 03:15:02 +00:00
swordshine
0d3eb11aa3 - Mana generation replacement
- Added Mana Reflection
2013-09-29 00:27:46 +00:00
Hellfish
62cf0b5a5e *Corrected an exception message. 2013-09-28 18:17:46 +00:00
Hellfish
0b7238d93b *Allowed multiples of Relentless Rats and Shadowborn Apostles to be added to a commander deck. 2013-09-28 18:02:09 +00:00
dripton
e4e62a8267 Revert r23308 and r23309.
These added synchronized to various methods in Combat,
to fix bugs 740 and 742.  Unfortunately, they could lead
to deadlock, as seen in bug 744.

So this revert fixes bug 744 but reopens bug 740 and bug 740.
2013-09-28 16:19:11 +00:00
Chris
57f95c3c5c - Cleared out the changes.txt file, now ready for new material.
- Added new card names to changes.txt.
2013-09-28 12:46:07 +00:00
Hellfish
28351a1d18 *Added a note to the commander effect indicating which zone the commander is in. Not added to the player panel because space. 2013-09-28 09:01:36 +00:00
Sloth
9b6e34a33f - Fixed DamageDealAi. 2013-09-28 07:22:49 +00:00
Sloth
faad09f594 - Added Mausoleum Turnkey. 2013-09-27 22:25:46 +00:00
Sloth
4b687603f8 - Enforce mandatory targeting when choosing from lists. 2013-09-27 22:24:24 +00:00
swordshine
1084d89cff - Added Scheme: Nature Demands an Offering 2013-09-27 13:35:04 +00:00
Chris
586f6ce5d9 [maven-release-plugin] prepare for next development iteration 2013-09-27 12:41:18 +00:00
Chris
059edfe381 [maven-release-plugin] prepare release forge-1.5.0 2013-09-27 12:41:08 +00:00
Chris
776f4b03ff Minor version number change to the pom file. 2013-09-27 12:31:00 +00:00
Chris
3be5ff1e17 - Preparing the changes.txt file for the next beta build and release. 2013-09-27 12:29:06 +00:00
swordshine
90d51c6dbe - Cleanup 2013-09-26 01:42:39 +00:00
spr
f792bce232 - new overlays menu option. 2013-09-25 18:15:08 +00:00
dripton
94f937ad7e Remove duplicate of the same card name in list. 2013-09-25 16:40:17 +00:00
Sloth
0aacb10d96 - Added draft rankings for Theros (from Le Bestiaire). 2013-09-25 13:57:34 +00:00
Sloth
07b26dd7f3 - Fixed name of Two-Headed Cerberus. 2013-09-25 13:53:35 +00:00
Sloth
6fd8e8de9a - Added another AILogic to ChangeZone effects. 2013-09-25 11:54:38 +00:00
spr
d38898b1dd - #0000743: OutOfMemoryError caused by image ResampleOp in FImagePanel. (http://www.cardforge.org/bugz/view.php?id=743) 2013-09-25 10:15:05 +00:00
Chris
12fd77953f - Added new card names to changes.txt. 2013-09-25 07:39:04 +00:00
drdev
f1db96ddce Improve FSkin.get performance by avoiding type casting 2013-09-25 02:04:54 +00:00
swordshine
537fd9a076 - Fixed Commander combat damage 2013-09-25 01:21:21 +00:00
swordshine
25c18e8f48 - Oracle Changes 2013-09-25 00:32:36 +00:00
Sloth
064d8a8288 - Fixed possible AI crash caused by Polukranos, World Eater. 2013-09-24 21:04:18 +00:00
dripton
8e9fecaf8f Revert r23260
ConcurrentHashMap didn't solve bug 740, so I ended up having to
synchronize methods instead.
2013-09-24 15:45:16 +00:00
dripton
ec75e4d9d9 synchronize all methods that use blockedBands
Fixes bug 742
2013-09-24 15:40:50 +00:00
dripton
4ccf39517b synchronize all methods that use attackedEntities
Fixes bug 740.
2013-09-24 15:30:08 +00:00
swordshine
f26c734c4d - Added Plane: The Maelstrom 2013-09-24 12:00:11 +00:00
RumbleBBU
655c96361e Alternate, more elegant fix to the unlockable editions sorting problem. 2013-09-24 09:42:49 +00:00
Chris
3f4adfbc07 - Added new card names to changes.txt. 2013-09-24 07:53:07 +00:00
swordshine
4d2a2b6ce2 - Fixed Akroan crusader 2013-09-24 05:12:52 +00:00
swordshine
d716493bcd - Converted Oath of Druids, Oath of Ghouls, and Oath of Lieges
- Added Oath of Mages and Oath of Scholars
2013-09-24 00:35:13 +00:00
swordshine
919de9b0fa - Added Conundrum Sphinx 2013-09-24 00:32:01 +00:00
swordshine
a97398e0b3 - Targets in subAbility trigger Precursor Golem now 2013-09-24 00:22:12 +00:00
dripton
2cf046de5e Remove commented-out code. 2013-09-23 16:41:36 +00:00
swordshine
a28e444680 - Fixed Hythonia the Cruel and Soldier of the Pantheon 2013-09-23 12:24:09 +00:00
swordshine
03a3ef8422 - Homeward Path is ready for multiplayer 2013-09-23 11:37:39 +00:00
Sol
f99d1ce51d - Updating Formats for adding Theros next week 2013-09-22 23:21:57 +00:00
Sloth
bf46bd9d96 - Added SVar:PlayMain1:TRUE to 3 Theros cards. 2013-09-22 13:29:38 +00:00
Sloth
5620552344 - AI will now prefer Heroic creatures when casting Auras. 2013-09-22 13:21:15 +00:00
Sloth
3898afe81b - Fixed AI sometimes ignoring "CARDNAME can't be blocked except by three or more creatures". 2013-09-22 11:28:48 +00:00
swordshine
ba9d49d0f1 - Fixed Heroic
- Fixed FightEffect
2013-09-22 08:05:24 +00:00
Sloth
a7f196999f - Improved AI using Shipbreaker Kraken. 2013-09-22 07:02:37 +00:00
swordshine
7493cf2726 - Fixed Heliod, God of the Sun and Shipwreck Singer by Diogenes 2013-09-22 04:14:32 +00:00
swordshine
ffcfd24781 - TargetsValid should find targets in the subabilities 2013-09-22 00:38:44 +00:00
swordshine
bb4f967353 - Prevent NPE 2013-09-22 00:16:52 +00:00
Sloth
8e28ce296a - Replaced some unplayable cards in Jamuraa world quest decks. 2013-09-21 22:08:51 +00:00
Sol
d3b9f4c8d8 - Fix for Anthousa 2013-09-21 17:13:16 +00:00
Sol
5ebdf212e2 - Fix Dragon Mantle, Hammer of Purphoros and Reaper of the Wilds 2013-09-21 17:00:52 +00:00
swordshine
1bc4baffec - Fixed NPE caused by Spatial Merging 2013-09-21 11:35:59 +00:00
swordshine
37661ac0d0 - Fixed the edition file 2013-09-21 11:24:01 +00:00
swordshine
bb7b4c6252 - Fixed Warriors' Lesson 2013-09-21 10:42:00 +00:00
swordshine
aeb6994974 - Improve getLifeThreateningCommanders() 2013-09-21 10:11:23 +00:00
swordshine
892ed7df24 - Fixed getLifeThreateningCommanders() 2013-09-21 09:43:58 +00:00
swordshine
9a60203313 - Cleanup 2013-09-21 02:57:30 +00:00
swordshine
5ce9f79c66 - Updated some scripts to avoid overwriting the original Svars 2013-09-21 02:25:40 +00:00
dripton
0adee5121b Remove some unused imports to fix warnings. 2013-09-20 16:34:33 +00:00
Sol
13070aa96c - Some improvements to Monstrosity text display 2013-09-20 16:29:26 +00:00
dripton
b75012a0a1 Fix spelling of SaTargetRoutines (was SaTargetRountines) 2013-09-20 16:26:43 +00:00
Chris
09c11d1f3f - Added a fluff piece to the changes.txt file. 2013-09-20 13:08:18 +00:00
moomarc
b51bf8f952 - Fixed creature type 2013-09-20 10:27:29 +00:00
Sloth
9db08d508b - Updated some SVars. 2013-09-20 07:57:53 +00:00
Sloth
015aa8f343 - Fixed NPE caused by Bestow. 2013-09-20 07:20:20 +00:00
swordshine
5ed5c9afbe - Fixed several cards with Fading that kept remembered cards 2013-09-20 05:58:23 +00:00
swordshine
f45174318d - Reverted r23257, fixed Duplicant 2013-09-20 04:34:16 +00:00
Sol
a59f5b4d11 - Theros block data 2013-09-20 03:34:03 +00:00
Sol
2e122714b0 - Missed the Theros file to fix typo 2013-09-20 03:29:10 +00:00
Sol
5beba3101e - Fixing issues with Theros cards, adding Oracles that were missed 2013-09-20 03:26:31 +00:00
Sol
c4e0bc0a1a - Updated Oracle for Theros S-Z 2013-09-19 23:55:53 +00:00
Sol
2a0cb56520 - Updated Oracle for Theros N-R 2013-09-19 23:51:59 +00:00
Sol
9e21987039 - Updated Oracle for Theros G-M 2013-09-19 23:51:06 +00:00
Sol
e4fc9164c1 - Updated Oracle for Theros A-F 2013-09-19 23:49:52 +00:00
dripton
f4ce2a9f37 Fix "its" vs. "it's" typo in Sensei's Divining Top. 2013-09-19 21:56:48 +00:00
Sloth
21d7a8fe3f - Merged Theros branch into trunk. 2013-09-19 19:53:33 +00:00
dripton
af8ae84eb5 Add ConcurrentHashMapOfLists and use it for Combat.attackedEntities
Fixes bug 740, intermittent ConcurrentModificationException

The alternative would be synchronizing all access to attackedEntities,
either at the method level or by using an internally synchronized
container like a Hashtable.  But ConcurrentHashMap should give better
performance, since it only locks on writes not reads, and we read
attackedEntities a lot more often than we write to it.
2013-09-19 16:05:15 +00:00
Chris
d73699bcaa - Added new card names to changes.txt. 2013-09-19 08:02:04 +00:00
Sloth
1e55407060 - Fixed NPE caused by High Priest of Penance. 2013-09-19 06:18:10 +00:00
Hellfish
c9987e5efc *Don't Imprint if the card in question isn't exiled.(Really only applicable to commanders) 2013-09-19 05:42:16 +00:00
Sol
4e90eac764 - Simplified Oracle Scraper for magiccards.info 2013-09-19 03:18:34 +00:00
Sloth
24e320237f - AI fix for Monstrosity. 2013-09-18 18:35:30 +00:00
RumbleBBU
0ca16e5996 Fix unlockable sets sorting. 2013-09-18 09:24:36 +00:00
swordshine
5125ef32ab - THS: Added 5 red cards 2013-09-17 12:48:32 +00:00
Chris
9c2c231b93 - Added new card names to changes.txt. 2013-09-17 07:42:19 +00:00
swordshine
35f3949fbc - Implement Rule 702.102d 2013-09-17 02:47:58 +00:00
swordshine
03fb8b24d1 - THS: Added 13 cards 2013-09-17 00:25:23 +00:00
Maxmtg
1ece44afc7 when set was not found, fall back to just card with given name from any set. 2013-09-16 22:39:28 +00:00
moomarc
0b951527fa - Added Blaze of Glory 2013-09-16 15:23:09 +00:00
drdev
b2a86015f1 Fix function name 2013-09-16 08:57:26 +00:00
drdev
f0f5b97e03 Tweak wording on CHANGE.txt 2013-09-16 08:19:24 +00:00
drdev
ba8ec270d1 Support switching between Themes/Skins without restarting 2013-09-16 08:18:19 +00:00
Chris
d3b94b0dd9 - Added new card names to changes.txt. 2013-09-16 08:16:52 +00:00
Chris
7f3a641629 - Added new card names to changes.txt. 2013-09-16 08:14:26 +00:00
moomarc
61073dcd09 - Added Wort, the Raidmother (finally) 2013-09-16 08:03:03 +00:00
drdev
40c840446d Make combo boxes skin correctly 2013-09-16 07:36:39 +00:00
swordshine
6426106e0c - Reverted r23140 2013-09-16 07:04:59 +00:00
swordshine
799387b09b - Fixed Doomsday 2013-09-16 06:51:30 +00:00
Maxmtg
a9e0e660d2 theros edition file 2013-09-16 06:41:59 +00:00
Hellfish
732beaa9fd *Fixed Boseiju, Who Shelters All oracle text 2013-09-16 06:25:20 +00:00
Hellfish
eee4322173 *Converted Commander rules to an effect. (Fixes being unable to cast an Akroma, Angel of Fury commander face down) 2013-09-16 06:14:46 +00:00
swordshine
727920679c - THS: Added 5 cards 2013-09-16 05:47:42 +00:00
swordshine
7ec2d0f8cb - THS: Fixed Bronze Sable 2013-09-16 04:52:59 +00:00
drdev
eb4b25b9e4 Start FComboBox 2013-09-16 03:09:54 +00:00
Chris
a3afd4c35b - Added new card names to changes.txt. 2013-09-15 12:35:36 +00:00
swordshine
cfccacd21d - Template change: "is unblockable" -> "can't be blocked" 2013-09-14 06:25:27 +00:00
swordshine
b40302a3aa - Added Personal Incarnation 2013-09-14 04:17:27 +00:00
Maxmtg
75cd2cdcab restore cards recognition for cases when alias is specified instead of commonly used set code
ddl edition => added 'hvm' alias
2013-09-14 03:39:41 +00:00
swordshine
2f37ca57b4 - Updated the reminder text for Monstrosity 2013-09-14 01:47:22 +00:00
Sloth
e4446b5fa0 - Added the medium quest deck Black Abott 2. 2013-09-13 20:10:04 +00:00
swordshine
9519eb3a17 - Added Truth or Tale 2013-09-13 13:59:55 +00:00
Chris
a1d99ba2ba - Added new card names to changes.txt. 2013-09-13 11:53:20 +00:00
drdev
5c1219f649 Work towards updating combo boxes when theme changes 2013-09-13 07:30:20 +00:00
drdev
e2c773c416 2013-09-13 06:21:49 +00:00
drdev
98d16ba6e1 Fix so disabled background image doesn't come back when changing themes 2013-09-13 06:17:49 +00:00
drdev
a8f3360c40 Update combo boxes in preferences when skin changes 2013-09-13 06:03:25 +00:00
swordshine
c5aa1d3d7e - THS: Added 2 multicolor cards 2013-09-13 05:35:18 +00:00
swordshine
80661d3055 - Added Plane: Stairs to Infinity 2013-09-13 03:55:56 +00:00
swordshine
d4e5a1ffba - Fixed Aladdin's Lamp 2013-09-13 01:48:02 +00:00
swordshine
7b88caee8a - fix r23186 2013-09-13 00:38:00 +00:00
dripton
17f4bbdda1 Apply pqnet's patch to fix bug 704.
(IllegalStateException from using getOpponent() instead of getOpponents())
2013-09-12 23:06:13 +00:00
swordshine
6dacae86f8 - another fix 2013-09-12 14:17:07 +00:00
swordshine
55b182687e - Fixed DigEffect 2013-09-12 13:48:08 +00:00
swordshine
2966504fae - updated the code for the new duel decks 2013-09-12 12:54:48 +00:00
dripton
9df426e427 Fix race in Card.getController()
Fixes bug 737
2013-09-11 21:41:50 +00:00
Chris
f96711fc9a - Added new card names to changes.txt. 2013-09-10 07:31:14 +00:00
swordshine
7d170f4f24 - Converted Freyalise's Winds to script 2013-09-10 04:45:21 +00:00
Sloth
30350041bb - Fixed AI using the ability of Keeper of the Beasts without legal target. 2013-09-09 18:43:55 +00:00
Sloth
bf205b0998 - Added an AILogic for Jace, Architect of Thought. 2013-09-09 17:57:44 +00:00
Sloth
a065c8573f - Expanded AI P/T prediction with +1/+1 counters granting abilities. 2013-09-09 15:27:01 +00:00
Sloth
22c54a488b - AI will no longer cast Scrounge and similar cards when there are no cards to move. 2013-09-09 15:08:25 +00:00
Chris
4b14ff7231 - Added new card names to changes.txt. 2013-09-09 08:48:42 +00:00
moomarc
1bdbfdc7bf - Conspire keyword should be able to stack (just fixed the keywords string, not multiple instances of Conspire actually working properly) 2013-09-09 07:46:59 +00:00
moomarc
7b4812edca - Fixed Recover for Garza's Assassin 2013-09-09 07:27:27 +00:00
swordshine
a6a08bb970 - Added the missing oracle 2013-09-09 06:15:06 +00:00
swordshine
5b47dfbcb7 - Scheme: Added Rotted Ones, Lay Siege 2013-09-09 05:05:12 +00:00
swordshine
d4c54cab89 - Scheme: Added Rotted Ones, Lay Siege 2013-09-09 00:17:45 +00:00
swordshine
358f05ba01 - Updated scripts for commander 2013-09-09 00:15:16 +00:00
drdev
71040279a4 Prevent border around main display panel 2013-09-08 23:27:01 +00:00
drdev
e10843e5cb Fix spacing issues 2013-09-08 22:48:26 +00:00
dripton
98901c4d06 Fix Molder's prompt to reflect that it can target an artifact or enchantment 2013-09-08 18:03:10 +00:00
Chris
12ddd7540b - Added a fluff piece to the changes.txt file.
- Added new card names to changes.txt.
2013-09-08 14:47:53 +00:00
swordshine
565971ac7f - Ruhan of the Fomori can attack specific chosen player now 2013-09-08 13:13:23 +00:00
swordshine
a93ae5b3e9 - Initial code for Bestow
- THS: Added Cavern Lampad, Celestial Archon, Leafcrown Dryad, Nimbus Naiad, Observant Alseid, and Spearpoint Oread
2013-09-08 04:31:50 +00:00
Sol
b662b0a7ba - Clear selected of Partial Paris when Clicking on the "OK" button 2013-09-08 01:22:46 +00:00
dripton
c26e23539b Fix whitespace before I start fixing bug 734 (too many open sound files) 2013-09-07 23:10:22 +00:00
drdev
486a965624 Update fonts when skin changes 2013-09-07 20:06:32 +00:00
Hellfish
f3f44dd65e *Fixed Aladdin's Cave challenge extra cards 2013-09-07 19:21:42 +00:00
drdev
2431e1dd20 Fix crash when updating scaled images
Prevent scaling menu icons to 16x size
2013-09-07 17:27:07 +00:00
drdev
d9eea5d5f0 Ensure status is visible on default menu bar 2013-09-07 17:16:20 +00:00
drdev
9499207bae Fix so menu bar not blanked out when changing skins and status message is retained 2013-09-07 17:06:52 +00:00
drdev
6c6ba5742f Fix so menu bar updated properly when skin changed 2013-09-07 16:36:44 +00:00
Sol
fcf1ac425e - Fix Commander SpellCost not affecting the rest of your spells 2013-09-07 16:32:25 +00:00
swordshine
dba19e6cb7 - Commander spell can be cast from hand if it was bounced 2013-09-07 13:17:34 +00:00
Hellfish
82bb71a34b *Applied Swordshines fix to Commander cost increasing. Thanks! :) 2013-09-07 13:01:29 +00:00
Chris
cd061cd660 - Added new card names to changes.txt. 2013-09-07 12:52:22 +00:00
Hellfish
ea6795df35 *Made Commander casting a spell instead of an ability. Fixes interaction with SpellCast triggers but currently breaks Commander cost increase. 2013-09-07 08:11:35 +00:00
spr
35edfd936b - Fix : tab visibility now updated without using revertLayout() which could alter the state of the active layout and was possibly causing repaint artifacts. 2013-09-07 04:26:58 +00:00
swordshine
e18b3b3537 - Fixed "Play with the top card of your library revealed." for commanders 2013-09-06 14:35:33 +00:00
swordshine
f9d749e2cb - More cards converted to BecomesTarget trigger 2013-09-06 14:14:38 +00:00
swordshine
0baa952db7 - Several cards with "T:Mode$ SpellAbilityCast | TargetsValid$ Card.Self" changed to BecomesTarget trigger 2013-09-06 14:00:58 +00:00
swordshine
fa443f0c7f - ChangeTargets Effect will also trigger BecomesTarget 2013-09-06 13:35:06 +00:00
Chris
98b8c2b43a - Added a fluff piece to the changes.txt file.
- Added new card names to changes.txt.
2013-09-06 11:15:11 +00:00
spr
f5b0fa0467 - update : Card overlays if shown now always shown regardless of card image size. 2013-09-06 10:29:23 +00:00
Sloth
67608ae02a - Updated evaluateCreature to consider Cypher. 2013-09-06 07:31:19 +00:00
dripton
73495c4a76 Slightly improve grammar, from "Discard 1 cards" to "Discard 1 card(s)."
The real fix would involve dynamically adding the 's' depending on the 
current number of cards to discard, but that's more complex.
2013-09-05 23:45:13 +00:00
dripton
3ae5b4cd80 Add null check to avoid NPE
Fixes bug 735
2013-09-05 23:07:53 +00:00
Sloth
6b4de9833f - Fixed cards with "TargetsWithDefinedController$ Targeted" (Memory's Journey and friends). 2013-09-05 14:50:09 +00:00
Sloth
4531658dd8 - Fixed PlayEffect not allowing lands to be played. 2013-09-05 11:37:48 +00:00
Sloth
11e738e6c6 - Fixed possibility of getting stuck with no targets. 2013-09-05 11:27:54 +00:00
Chris
f531baf7d3 - Added new card names to changes.txt. 2013-09-05 11:26:36 +00:00
Sloth
f4e791b6f1 - Fixed multi targeting in DamagePreventAi. 2013-09-05 11:05:43 +00:00
swordshine
c05cd7b2f6 - THS: Added Ashiok, Nightmare Weaver 2013-09-05 07:06:21 +00:00
Maxmtg
9778fe7dfd deck names won't contain slashes any more 2013-09-05 07:01:08 +00:00
swordshine
00208b69a7 - Added Hall of the Bandit Lord 2013-09-05 04:05:34 +00:00
swordshine
3df8397c9a - Add Monstrosity to unparsed abilities 2013-09-04 13:42:04 +00:00
swordshine
b480c2895c - THS: Added Hundred-Handed One 2013-09-04 12:59:34 +00:00
Chris
928b4fa887 - Added new card names to changes.txt. 2013-09-04 12:27:49 +00:00
swordshine
4a8ff10965 - keyword "CARDNAME can't attack during extra turns." for Medomai the Ageless 2013-09-04 11:49:59 +00:00
swordshine
23df025313 - Updated Urza's Incubator 2013-09-04 10:51:09 +00:00
spr
aa4ee6ec6b - Card Overlays option added to Game menu. 2013-09-04 07:29:36 +00:00
Hellfish
a0ca0c47c9 *Reintroduced Dig changes for Interplanar Tunnel (less broken this time. JINX!) 2013-09-04 06:21:19 +00:00
Hellfish
775879096f *Removed 'Random' option from Commander and Planar deck choice when there are no such decks. 2013-09-04 06:09:54 +00:00
swordshine
8969d07d45 - Added Card Edition "Duel Decks: Heroes vs. Monsters"
- Added Xenagos to the Planeswalker type
2013-09-04 05:58:28 +00:00
Sol
b1fd15c083 - Fix DigEffect trying to use library position for all zones 2013-09-04 02:41:06 +00:00
swordshine
b9f4a9abda - THS: Added Ember Swallower, Reverent Hunter, Sealock Monster, Stoneshock Giant, and Sylvan Caryatid 2013-09-04 00:19:33 +00:00
drdev
fc5230a9b9 Fix rendering of scaled images 2013-09-04 00:18:06 +00:00
drdev
9f6f9ce7bb Prevent stack overflow when setting regular cursor 2013-09-03 22:58:00 +00:00
drdev
b9d5cc4ae7 Fix so scrollbars and buttons aren't messed up when skin changed 2013-09-03 22:47:28 +00:00
drdev
cfed3ee53a Fix progress bar messages 2013-09-03 22:16:33 +00:00
drdev
a242fbd8a2 Support updating icons, images, and cursors when skin changed 2013-09-03 21:55:47 +00:00
Sloth
b1a8accfd0 - AI will no longer destroy stolen permanents when the stealing aura can be destroyed. 2013-09-03 20:57:01 +00:00
Chris
905d64cb51 - Added new card names to changes.txt. 2013-09-03 13:02:25 +00:00
Maxmtg
ab2d7ae029 might prevent NPE choosing deck 2013-09-03 06:19:36 +00:00
Maxmtg
2b33f588bd clear up warnings,
remove useless setters in RegisteredPlayer
a few style clean ups in cardfactory/CardFactoryUtil.java
2013-09-03 06:14:17 +00:00
swordshine
3c86a85cd3 - Fixed Monstrosity 2013-09-03 00:38:42 +00:00
Sloth
b4ae3c97a3 - Improved TokenAI. 2013-09-02 20:25:28 +00:00
Sloth
80dd6a2efa - Fixed AI removing the last +1/+1 counter from Golgari Grave-Troll to regenerate. 2013-09-02 20:15:04 +00:00
Sloth
5069854924 - Fixed Trial//Error. 2013-09-02 20:08:30 +00:00
Sloth
29d4875778 - Fixed Canopy Cover. 2013-09-02 19:52:50 +00:00
Hellfish
df44f00eb8 *For some reason I thought the commander blocking hadn't been committed. Removing duplicate code. 2013-09-02 19:10:31 +00:00
drdev
1a08cd6ae4 Support caching derived colors for reuse and actually updating colors when skin changed 2013-09-02 16:28:02 +00:00
drdev
2f39539135 Prevent crash when changing skin 2013-09-02 16:00:06 +00:00
drdev
8350c398f3 Support changing skin on the fly 2013-09-02 15:44:00 +00:00
Chris
3591759cdb - Added new card names to changes.txt. 2013-09-02 13:32:11 +00:00
Chris
f352704fcd - Cleared out the changes.txt file, now ready for new material. 2013-09-02 12:58:56 +00:00
swordshine
679c0fea03 - THS: Added Flamespeaker Adept (TriggerScry) 2013-09-02 08:00:41 +00:00
Hellfish
370927e489 *Reintegrated Commander branch 2013-09-02 05:51:40 +00:00
swordshine
d675097da5 - THS: Added Nessian Asp 2013-09-02 05:47:03 +00:00
drdev
e4c7797102 Fix background of home screen 2013-09-01 23:11:03 +00:00
drdev
57a9c54630 Refactor skin colors and support tracking skinned components 2013-09-01 19:35:46 +00:00
drdev
9c885af7ec 2013-09-01 19:16:21 +00:00
Hellfish
242d293f5a *Fixed stupidity in commander blocking 2013-09-01 18:06:47 +00:00
Hellfish
bc44426d9d *Expanded AF_Dig
*Added the Planechase phenomenon Interplanar Tunnel
2013-09-01 13:57:56 +00:00
Sloth
e4441f9126 - Fixed Simic Manipulator with X=0. 2013-09-01 12:37:51 +00:00
swordshine
97855b563d - THS: Added Nylea, God of the Hunt (God is now added to the creature type list) 2013-09-01 11:56:17 +00:00
Hellfish
7ef5462969 *Fixed card text displaying commander damage dealt. 2013-09-01 09:24:46 +00:00
Hellfish
714dbdc930 *Made AI at least semiconscious of blocking commanders 2013-09-01 09:06:17 +00:00
swordshine
f1366a5e8a - THS: added Polukranos, World Eater and Nykthos, Shrine to Nyx 2013-09-01 08:56:06 +00:00
Hellfish
5af7659883 *Merged from trunk up to r23056 2013-09-01 07:31:14 +00:00
Sloth
05df1adb11 - Updated the quest deck Mortivore 3. 2013-08-31 06:56:46 +00:00
Sloth
05066496d8 - Fixed Extort description. 2013-08-30 22:07:31 +00:00
Sloth
599821c018 - Fixed Saproling Burst. 2013-08-30 22:02:04 +00:00
Sloth
52cae0e723 - Fixed Scalpelexis. 2013-08-30 21:46:04 +00:00
Sloth
ceb9180bbe - Fixed Fire Juggler. 2013-08-30 21:43:41 +00:00
Sloth
657beeb63d - Fixed Diregraf Escort. 2013-08-30 18:33:11 +00:00
Chris
16a915faa1 [maven-release-plugin] prepare for next development iteration 2013-08-30 12:32:46 +00:00
Chris
2ca3d67eb5 [maven-release-plugin] prepare release forge-1.4.7 2013-08-30 12:32:36 +00:00
Chris
309cf6658d - Preparing the changes.txt file for the next beta build and release. 2013-08-30 12:20:13 +00:00
spr
e21aac63f4 - Added "How to Play" option to Help menu which links to the cunningly hidden "res\howto.txt". 2013-08-30 04:36:40 +00:00
Sloth
9a0b240e73 - Fixed Vanish into Memory. 2013-08-29 21:20:34 +00:00
swordshine
046f3a6458 - Fixed Swords to Plowshares (a LKI issue caused by TargetedController when some cards changed the controller of the creature) 2013-08-28 14:28:01 +00:00
Sloth
398a3ed1ea - Fixed possibility of getting stuck with Tangle Wire. 2013-08-28 11:12:08 +00:00
Sloth
f1ab723957 - Fixed LKI's of tokens not being marked as tokens. 2013-08-28 10:00:39 +00:00
Sloth
9380a06a35 - Fixed Soul Barrier. 2013-08-28 09:56:14 +00:00
swordshine
73131ba99e - Fixed Mikaeus, the Unhallowed 2013-08-28 04:02:40 +00:00
Sloth
12e813a5a1 - Fixed Raid Bombardment. 2013-08-27 20:49:50 +00:00
Chris
de87fcb123 - Added new card names to changes.txt. 2013-08-27 12:24:27 +00:00
swordshine
26b4eb000a - Fixed typo 2013-08-27 12:19:21 +00:00
swordshine
4c9dacbcbe - move the new THS card to the branch 2013-08-27 12:09:41 +00:00
swordshine
29a959fb59 - Initial implementation of the new keyword ability Monstrousity and its related trigger
- Theros: Added Shipbreaker Kraken
2013-08-27 10:36:25 +00:00
Sloth
b5049bbb8d - Added an easy version of the Galadriel quest deck by Nordos. 2013-08-27 09:23:53 +00:00
Sloth
42ab52e791 - Added a mandatory AI part to ControlGainAI. 2013-08-27 09:23:11 +00:00
swordshine
999070fd9b - Fixed Quicksilver Fountain by squee1968 2013-08-27 01:27:08 +00:00
spr
03343276c2 - Declare blockers fix added to CHANGES.txt. 2013-08-26 17:52:47 +00:00
spr
02e7a8920a - Additional CHANGES.txt updates. 2013-08-26 17:29:00 +00:00
spr
fbc2d6ad7e - Duel/Match screen changes detailed. 2013-08-26 17:22:40 +00:00
Sloth
7ce642fa7b - Unlikely but possible case fixes in player hasProperty. 2013-08-26 09:07:52 +00:00
Hellfish
8c984d6dbe *Merged from trunk up to r23024 2013-08-26 05:59:14 +00:00
spr
9c0dad1342 - Added menu option to toggle sound on/off from within a duel. (http://www.cardforge.org/bugz/view.php?id=727) 2013-08-26 03:03:30 +00:00
Chris
dc69975b87 - Added a fluff piece to the changes.txt file. 2013-08-26 02:18:20 +00:00
spr
da06932d85 - Fix : 0000726: Picture preview panel does not adhere to Scale Image Larger setting. (http://www.cardforge.org/bugz/view.php?id=726 2013-08-26 02:01:59 +00:00
Sloth
4cfed1e438 - Updated some SVars. 2013-08-25 21:44:58 +00:00
spr
8c461edc1d - Fix : MenuBar was not disabling when overlay was active. 2013-08-25 21:00:41 +00:00
spr
ed7d5aa8af - Game Log Console efficiency & UI updates. (see http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=11561) 2013-08-25 20:26:54 +00:00
drdev
66a4b444e3 Fix spacing issue 2013-08-25 17:40:31 +00:00
drdev
cebcd25f81 Add Theme submenu to Layout menu 2013-08-25 17:38:58 +00:00
drdev
48ba246fc4 Make Layout menu available on all screens (with certain options hidden based on screen)
Move Set Window Size out of Dev Mode pane/menu and into Layout menu
2013-08-25 14:43:36 +00:00
Sloth
16a2e75304 - Fixed groupAndOrderToPayShards using an unordered list. 2013-08-25 06:47:07 +00:00
moomarc
eb1d4a6354 - Updated quest icon avatar download list 2013-08-24 18:08:58 +00:00
Chris
490abc5826 - Added new card names to changes.txt. 2013-08-24 12:07:03 +00:00
spr
90c78a469d - Fix: Prompt heading was not being reset to "Setup Game" on new game. 2013-08-24 11:44:26 +00:00
spr
3225112fc7 - Fix: Prevent buttons in REPORT_MESSAGE panel from disappearing off screen as the panel size is decreased.
- Cosmetic updates to appearance.
2013-08-24 11:17:01 +00:00
Sloth
20732ab927 - Added the quest deck Leela 2. 2013-08-24 10:34:46 +00:00
Maxmtg
501a0ce009 fix: concede during declare blockers 2013-08-24 09:21:00 +00:00
moomarc
95af0e1ef5 - Added Plane: Grand Ossuary 2013-08-23 14:59:19 +00:00
moomarc
92a7c1a20a - Removed duplicate svar from Predator Ooze 2013-08-23 10:32:09 +00:00
Sloth
c51abaaaf4 - Added the name of the source card to some targeting prompt messages. 2013-08-23 09:35:45 +00:00
swordshine
1df24c0287 - Fixed TriggerDescription 2013-08-23 08:47:07 +00:00
swordshine
22e6603a5b - Converted keyword "Whenever a creature dealt damage by CARDNAME this turn is put into a graveyard, put a +1+1(+2/+2) counter on CARDNAME." to script 2013-08-23 08:43:10 +00:00
Maxmtg
8c07e0b89f gave names to all IStorage instances, fixed display of card list for decks in subfolders 2013-08-23 05:40:24 +00:00
drdev
4be5d02fd7 Make progress on UI for ItemManager filters 2013-08-23 01:06:03 +00:00
Sloth
d6176eec0d - Fixed Hunting Wilds. 2013-08-22 18:42:20 +00:00
spr
2279087023 - Added option to hide panel tabs to Layout menu. 2013-08-22 16:35:52 +00:00
Chris
59197f2ac9 - Added new card names to changes.txt. 2013-08-22 12:24:37 +00:00
swordshine
2af8c51798 - Added Necrotic Plague and Quicksliver Fountain
- Plane: Added Immersturm
2013-08-22 11:49:15 +00:00
spr
a05fbe5cd8 - Game, Layout and DevMode menus added to match screen menu bar. 2013-08-22 10:32:06 +00:00
Sloth
30f12050dc - Fixed Cytoplast Root-Kin. 2013-08-22 07:59:58 +00:00
spr
fdc97228e7 - Menu bar visibility can be toggled using F1 key.
- Hints or status info can be displayed on the right-hand side of the menu bar.
2013-08-22 07:50:04 +00:00
Sloth
ca9266f772 - Added Erithizon. 2013-08-21 21:58:41 +00:00
Sloth
d1eeeedca1 - The bounce ability of Sunken Hope is now mandatory. 2013-08-21 16:31:52 +00:00
Sloth
39486f078c - Added the quest deck Havok 3 by Nordos. 2013-08-21 16:19:35 +00:00
swordshine
c6904e740c - Added Karplusan Minotaur 2013-08-21 14:20:58 +00:00
Chris
626279667f - Added new card names to changes.txt. 2013-08-21 12:31:20 +00:00
Sloth
c1d8cccdb3 - Moved check for TargetsWithDefinedController to the right place. 2013-08-21 11:57:14 +00:00
swordshine
db8a191afb - Added Mossbridge Troll 2013-08-21 09:06:48 +00:00
Sloth
e8099b8492 - Added Death Match. 2013-08-21 08:36:12 +00:00
Sloth
5bcea269de - Added some basic handling for tokens to the copyCard function (looks like it's used in places where this is necessary). 2013-08-21 08:23:28 +00:00
Sloth
9fe331d11a - Fixed Thoughtbound Primoc crashing the game . 2013-08-21 08:03:43 +00:00
Hellfish
cbeb5ced09 *Merged from trunk up to r22981 2013-08-21 06:17:56 +00:00
Hellfish
03ef46b316 *Basic land handling in cmd deck editor 2013-08-21 05:53:46 +00:00
Hellfish
66de7141d9 *Com Deck editor basic lands handled.
*Preliminary commander damage blocking ai (not yet fully in effect)
2013-08-21 05:30:28 +00:00
swordshine
8f80f4d439 - Added Illuminated Folio 2013-08-21 05:05:55 +00:00
drdev
4b30a7eca1 Make progress on API for new ItemManager filters
Create LayoutHelper and TypeUtils classes
2013-08-21 02:25:13 +00:00
spr
5ee58d727a - New forge menu bar (part 1 of 2). Includes common Forge and Help menus. 2013-08-21 01:13:26 +00:00
swordshine
f8f03a57ba - More cards ready for multiplayer 2013-08-21 00:42:32 +00:00
spr
34618e957c - Forge forced to use Java cross platform "Metal" look and feel which should only really affect Mac users (in a good way hopefully!). More details, see http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=11126#p125845. 2013-08-20 05:26:24 +00:00
Sol
f745ba9f5d - Updating Svar 2013-08-20 02:56:20 +00:00
drdev
1677e1eeb1 Refactor so ItemManager is abstract and ItemFilter doesn't extend JPanel
Start working on transitioning card color/type filters
2013-08-20 00:07:39 +00:00
Maxmtg
eebbb45b2c better display of subfolders 2013-08-19 22:48:33 +00:00
Maxmtg
ada5fa5056 Subfolders for constructed decks work in r/o mode (part 2 of ~3) 2013-08-19 22:40:10 +00:00
Maxmtg
df6860294d Support for nested folders that store constructed decks - part 1 of ≈3 2013-08-19 20:48:21 +00:00
Sloth
8b97275195 - The AI will now trade blockers with attackers like Goblin Lackey more aggressively. 2013-08-19 11:13:17 +00:00
Hellfish
7dfde0aba3 *Somehow missed merging some revisions 2013-08-19 08:33:32 +00:00
Hellfish
517b1ae328 *Merged changes from trunk
*Tarted up the Commander Deck Editor
2013-08-19 08:20:08 +00:00
drdev
7e92f73a30 Add ItemFilter.java (not committed by accident) 2013-08-18 23:09:31 +00:00
drdev
1514ad0694 Create ItemFilter class 2013-08-18 23:05:15 +00:00
Maxmtg
48bebfef05 interface for nested folders support in Istorage 2013-08-18 21:21:47 +00:00
Hellfish
19cb78e529 *Made Commander casting sorcery speed. 2013-08-18 21:06:58 +00:00
Maxmtg
ddb66257ce * Following the ideas implemented in java.util.collections, IStorageView interface removed, the base class is read-only by default.
* isUnique removed for being  synonym for !contains
* QuestDeckMap inherited correctly from StorageBase to avoid duplicate code.
2013-08-18 20:16:09 +00:00
Hellfish
fded944458 *Preliminary Mana replacement 2013-08-18 20:08:03 +00:00
Hellfish
e55d5f8199 *Fixed Command Tower in non-Commander scenarios 2013-08-18 19:47:33 +00:00
Hellfish
e8dc32489d *Fixed Commander deck editor 2013-08-18 19:43:44 +00:00
Hellfish
f8ec884788 *Initial Commander checkin
*Everything implemented *except* mana replacement
*Added Command Tower
2013-08-18 19:15:53 +00:00
Hellfish
fa0fb3e519 *Created Commander branch 2013-08-18 19:14:05 +00:00
Maxmtg
023bc56986 TableSorter renamed to ItemPoolSorter and moved to ItemPool's package - this also removes an incorrect reference from Deck to gui. 2013-08-18 19:10:54 +00:00
drdev
c52050e37c Make all text fields select all on focus 2013-08-18 19:03:30 +00:00
Chris
a523f3c130 - Added new card names to changes.txt. 2013-08-18 16:34:34 +00:00
Chris
0126e6dae3 - Cleared out the changes.txt file, now ready for new material. 2013-08-18 14:02:20 +00:00
Sloth
2a991e219f - Fixed being able to discard tokens. 2013-08-18 11:51:35 +00:00
Sloth
3c31e29a48 - Tokens leaving the battlefield will now also create LKI copies. 2013-08-18 10:45:20 +00:00
Sloth
e7a143e181 - Fixed Exalted Dragon. 2013-08-18 08:12:48 +00:00
Sloth
03b37b049b - Fixed overeager RuntimeException caused by Coalition Relic. 2013-08-18 06:49:03 +00:00
drdev
1563cb4693 Refactor Card Catalog and Current Deck to use new ItemManager control
Support ghost text in FTextFields and add "Search" ghost text for Card Catalog field and use in place of old "[New Deck]" logic
Standardize size of buttons and text fields a bit
Allow horizontal scrollbar for card tables in Deck Editor if preference for elastic columns not on
2013-08-18 06:13:15 +00:00
drdev
82f32154fd Make search in buttons be same size as Add Filter button 2013-08-18 00:10:58 +00:00
drdev
37b13aa484 Add parameterless function for setting to show ghost text with focus 2013-08-18 00:06:22 +00:00
drdev
cf00e02c12 Change ghost text default to be hidden with focus
Add ghost text to Card Catalog search field
2013-08-17 23:04:40 +00:00
drdev
4bfb8a840a Prevent crash when hovering over table header to right of final column 2013-08-17 22:38:55 +00:00
drdev
490efdbd5a Hide search box for now in Item Manager 2013-08-17 22:33:44 +00:00
Sloth
d2335d2382 - Converted Magus of the Abyss to script. 2013-08-17 20:59:09 +00:00
Sloth
7e8a729fed - Added Ley Line. 2013-08-17 20:56:33 +00:00
Sloth
d6274b42af - Added Pandemonium. 2013-08-17 20:37:09 +00:00
Sloth
699a502cc5 - Added the option for targets of triggers to be chosen by another player.
- Converted The Abyss to script.
2013-08-17 19:21:33 +00:00
drdev
292bfed82a Don't auto-resize columns if want elastic columns set to false 2013-08-17 16:22:05 +00:00
drdev
a34847ab7b Remove table functions from ItemManager class 2013-08-17 16:01:02 +00:00
drdev
9e5f7f943b User doLayout override to layout ItemManager components instead of resize handler 2013-08-17 15:13:33 +00:00
drdev
7dc9afddb3 Make ItemManager derive from JPanel instead 2013-08-17 15:10:26 +00:00
Sloth
f174d73098 - State effects are now checked after a land is played (fixes the legend rule). 2013-08-17 10:45:37 +00:00
Sloth
15c90a00cd - Fixed cleanup of phased out cards. 2013-08-17 10:38:55 +00:00
swordshine
1ecb6728b1 - Converted static ETB triggers to replacement effects 2013-08-17 05:26:48 +00:00
swordshine
f13c38e135 - Fixed replacement effects for cloned cards 2013-08-17 04:55:13 +00:00
swordshine
7c34056281 - Converted Virulent Wound to script 2013-08-17 04:03:51 +00:00
swordshine
0fb1c82dc0 - Fixed Heat Stroke and Defiant Vanguard 2013-08-17 02:59:10 +00:00
drdev
ecd8e8838f Fix layout in Item Manager 2013-08-17 02:46:37 +00:00
drdev
cd969babff Increase text field height by 2 pixels 2013-08-17 01:53:21 +00:00
drdev
116a24ac23 Support ghost text in text fields and make them look nicer 2013-08-17 01:49:36 +00:00
swordshine
a951e4eaa0 - Remove hidden extrinsic keyword "At the beginning of the end step, destroy/exile CARDNAME." after it triggers. 2013-08-17 00:54:57 +00:00
Sloth
fa820d4e07 - Fixed ControlGain effects not lasting until Cleanup step. 2013-08-16 22:01:31 +00:00
Sloth
f0ab756a5d - Fixed AttackersDeclared triggering without attackers. 2013-08-16 20:14:07 +00:00
Sloth
6545960635 - Fixed typo in Vanishing description. 2013-08-16 20:02:10 +00:00
spr
ef8bb689d7 - ComboBox style now set globally via UIManager which should hopefully resolve issue with Mac (see http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=11126#p125845). 2013-08-16 19:45:42 +00:00
Chris
ce988a66df [maven-release-plugin] prepare for next development iteration 2013-08-16 13:09:31 +00:00
Chris
54d98f710c [maven-release-plugin] prepare release forge-1.4.6 2013-08-16 13:09:20 +00:00
Chris
c1ab52e38f - Preparing the changes.txt file for the next beta build and release. 2013-08-16 12:57:41 +00:00
swordshine
42f6c88463 - made the hidden keyword "At the beginning of the end step, sacrifice CARDNAME." permanent 2013-08-16 12:27:27 +00:00
swordshine
d85e43a427 - Converted "At the beginning of your end step, return CARDNAME to its owner's hand." to a trigger 2013-08-16 12:17:33 +00:00
Sloth
d74f571ddb - Little improvement for exalted in isEffectiveAttacker. 2013-08-15 20:25:00 +00:00
swordshine
cfcbde62b2 - More cards ready for multiplayer
- Converted several cards to replacement effects
2013-08-15 04:55:40 +00:00
swordshine
f3fbb82dbd - Converted two cards to replacement effects 2013-08-15 00:34:45 +00:00
swordshine
0a0c9d8070 - More cards ready for multiplayer 2013-08-14 14:10:32 +00:00
drdev
27e22ace02 Support horizontal scrolling item manager container 2013-08-14 02:43:26 +00:00
Sol
5b7197fbd6 - Fire SpellResolve event before the spell gets reset 2013-08-13 02:27:04 +00:00
swordshine
a1764bf043 - More cards ready for multiplayer 2013-08-13 00:19:12 +00:00
Sloth
cfc280274f - Expanded AI use of damageFromETB (Poisonbelly Ogre, Suture Priest, etc.). 2013-08-12 18:54:06 +00:00
Chris
258953ec53 - Added new card names to changes.txt. 2013-08-12 12:16:53 +00:00
Sloth
236d528923 - Some improvements for damageFromETB. 2013-08-12 11:45:24 +00:00
Sloth
3fd6c7b688 - The AI will no longer kill itself with Ankh of Mishra and similar cards. 2013-08-12 10:59:17 +00:00
drdev
3306fb4352 Make ItemManager transparent 2013-08-12 01:24:15 +00:00
drdev
c0960c2250 Start working on having ItemManager render controls 2013-08-12 01:18:57 +00:00
swordshine
651fd5e5a2 - Converted Power Surge
- Added Monsoon
2013-08-12 00:20:15 +00:00
drdev
4d72113af4 Fix crash when opening Deck Editor 2013-08-12 00:08:12 +00:00
drdev
ca6fe5105c Remove need for ITableContainer 2013-08-11 23:48:18 +00:00
Sol
27c19645ac - Simplify refundManaPaid to fix infinite Mana issue with Sol Ring 2013-08-11 22:43:16 +00:00
drdev
259086a979 More refactoring 2013-08-11 19:51:33 +00:00
drdev
9f4ba4b50c Update names of properties/variables 2013-08-11 18:47:46 +00:00
drdev
21ad3cfc5e Rename ListView to ItemManager 2013-08-11 18:31:05 +00:00
Sloth
bfba7a5102 - Fixed Whip Vine. 2013-08-11 18:13:51 +00:00
drdev
0119fcd24a Get deck editor working again 2013-08-11 18:06:00 +00:00
asepetci
39edeacc5b updated rankings.txt 2013-08-11 14:20:04 +00:00
Sloth
e0dcec7d5b - Fixed combat tab always showing during combat even when the stack is not empty. 2013-08-11 13:23:04 +00:00
Sloth
3ec7071889 - Fixed Joven's Ferrets. 2013-08-11 13:01:55 +00:00
Sloth
eeb411bacb - Added some mandatory targeting code to the default doTriggerAINoCost. 2013-08-11 08:31:51 +00:00
Sol
03d13ebbc1 - Fix Reflecting Pool bug, activating player wasn't being set to controller which means the second Reflecting Pool wasn't properly filtering what it could reflect 2013-08-11 04:06:37 +00:00
drdev
46bb7df90e Update variable name 2013-08-11 03:00:48 +00:00
drdev
69ed6496a6 Refactor Deck Editor to use ListView and get compile working 2013-08-11 02:54:50 +00:00
drdev
b100daea1b Get compile working 2013-08-10 23:54:05 +00:00
Sloth
ec38900386 - Added the easy quest opponent Cohen the Barbarian 1. 2013-08-10 21:09:40 +00:00
drdev
a523cdf1e6 Start setting up ListView views and models 2013-08-10 17:01:44 +00:00
drdev
c552ef1616 Make ItemPool and ItemPoolView more generic 2013-08-10 15:56:24 +00:00
drdev
752a4413f3 Make more generic ListView 2013-08-10 14:32:33 +00:00
Chris
186bd2d7da - Added new card names to changes.txt. 2013-08-10 12:37:23 +00:00
swordshine
610c2f98ce - Fixed Isochron Scepter not imprinting Research // Development 2013-08-10 12:02:29 +00:00
spr
fdac56a9a7 - Fix : Selected human & AI avatars now remain in fixed position when scrolling list of available avatar images. 2013-08-10 05:55:39 +00:00
swordshine
2bb8c97a5a - An accurate script of Ashling, the Extinguisher Avatar
- Karn's Ultimate can be used in Variants
2013-08-10 04:48:51 +00:00
swordshine
ad3b034fd2 - Fixed Caged Sun by Zirbert 2013-08-10 00:48:31 +00:00
swordshine
b2b1657e31 - Converted Ripple to script 2013-08-10 00:34:24 +00:00
spr
3a4087a2e1 - Zoomer now supports split, flip and double-sided cards including cards played face down. (see CHANGES.txt for full details). 2013-08-09 20:53:28 +00:00
Sloth
3fe7d3adf3 - Added Rasputin Dreamweaver. 2013-08-09 18:40:26 +00:00
swordshine
f64566dbae - More card scripts updated 2013-08-09 13:38:24 +00:00
swordshine
98f3a50fbd - Fixed Eunuchs' Intrigues 2013-08-09 13:15:23 +00:00
Chris
ef5234d734 - Added new card names to changes.txt. 2013-08-09 12:38:45 +00:00
Sloth
5b34571cf2 - Fixed script of Pyromancer Ascension. 2013-08-09 11:42:58 +00:00
swordshine
edac489791 - Updated scripts 2013-08-09 10:11:05 +00:00
swordshine
acb01268da - Fixed Mask of Intolerance 2013-08-09 08:12:12 +00:00
swordshine
9b19a88a14 - Update card scripts 2013-08-09 07:44:35 +00:00
swordshine
555a8bfed7 - Fixed targeted SpellAbility for some cards with counter effect (please review) 2013-08-09 07:39:50 +00:00
swordshine
b4efa372b2 - More cards ready for multiplayer 2013-08-09 04:54:45 +00:00
swordshine
8ee5a5fa41 - More cards ready for multiplayer 2013-08-09 03:14:12 +00:00
drdev
c77f70b371 Get compile working 2013-08-09 01:54:30 +00:00
swordshine
c4f1721250 - Added Harsh Judgment
- More cards ready for multiplayer
2013-08-09 00:32:01 +00:00
Sol
32d2f98bef - Mana Abilities with subAbilities won't auto choose in express mana payment 2013-08-09 00:29:22 +00:00
Sloth
1f40291c1b - Added some AITapDown SVars. 2013-08-08 20:08:23 +00:00
Sloth
8b3dda264b - Added Citadel of Pain by lazylockie. 2013-08-08 19:59:02 +00:00
moomarc
1a5c749b15 - Improved script of Venser, Shaper Savant 2013-08-08 18:34:20 +00:00
moomarc
0afd72195b - Added Clockspinning (including supporting AI) 2013-08-08 17:40:54 +00:00
swordshine
fef2c873d5 - Fixed DigAi for Guild Feud (issue 719, http://cardforge.org/bugz/view.php?id=719) 2013-08-08 12:57:25 +00:00
Chris
7d0fdfff24 - Added new card names to changes.txt. 2013-08-08 12:36:39 +00:00
swordshine
2d966bc535 - More cards ready for multiplayer 2013-08-08 12:25:30 +00:00
swordshine
4b3c8b555e - More cards ready for multiplayer 2013-08-08 12:01:34 +00:00
swordshine
c0de6f7721 - Simplified Standstill's script 2013-08-08 10:25:05 +00:00
swordshine
70323eccd0 - Added Edition "From the Vault: Twenty" by dmacgamer 2013-08-08 08:26:52 +00:00
swordshine
b259c66530 - Updated the script of Doomsday (should be affected by "can't search library" effect) 2013-08-08 07:19:00 +00:00
moomarc
84bbd884ae - Added Stranglehold 2013-08-08 06:46:26 +00:00
swordshine
fb3867c21c - Converted Recover to script 2013-08-08 06:37:32 +00:00
moomarc
0b61e6b4b6 - fixed to Eater of Days 2013-08-08 06:05:10 +00:00
swordshine
fbad22131a - Cleanup 2013-08-08 05:08:28 +00:00
spr
884232bd33 - Fix : NPE on zooming a card with no rules (eg. human creature token). 2013-08-08 04:49:46 +00:00
swordshine
70acd483d1 - Converted the upkeep trigger of Obsidian Fireheart to script 2013-08-08 04:41:43 +00:00
swordshine
018699cc39 - Updated scripts 2013-08-08 03:57:54 +00:00
swordshine
61d1786a00 - Converted "At the beginning of the end step, sacrifice CARDNAME.", can be targeted by Stifle 2013-08-08 03:17:59 +00:00
drdev
07c38892f9 Start breaking off files for CardListView 2013-08-08 03:17:55 +00:00
Sol
f689d44f01 - Convert skip your next turn cards from giving an extra turn to an opponent (since that's wrong) 2013-08-08 02:26:47 +00:00
swordshine
ce53c8d84a - Converted Swans of Bryn Argoll to script 2013-08-08 02:04:20 +00:00
swordshine
d1030df71a - Updated Hydra Omnivore 2013-08-08 01:43:12 +00:00
swordshine
d9be047a5c - Converted Tectonic Instability to script 2013-08-08 01:24:48 +00:00
swordshine
2966a22521 - Fixed Sparkcaster 2013-08-08 01:10:58 +00:00
swordshine
79d5f9b46d - Cleanup unnecessary text in card scripts
- Fixed Taoist Mystic
2013-08-08 00:32:57 +00:00
swordshine
9f387d1ddf - Converted Vanishing to script
- Updated Maelstrom Djinn
2013-08-08 00:21:27 +00:00
drdev
f32a1455fd 2013-08-08 00:05:09 +00:00
Sloth
1dcc84a894 - Added Stoneshaker Shaman by lazylockie. 2013-08-07 20:31:30 +00:00
Sloth
1309a14ea0 - Added some basic AI to support and added Copperhoof Vorrac by marc. 2013-08-07 20:20:00 +00:00
drdev
04010be62a Update CHANGES.txt with note about default window size/position 2013-08-07 15:50:47 +00:00
drdev
d8319fd89e Remember window size/position between sessions 2013-08-07 15:37:48 +00:00
moomarc
0dbd8155ae - Added Rock Jockey 2013-08-07 15:27:15 +00:00
moomarc
f426c6be3d - Small comment added to changes.txt about the new preference 2013-08-07 15:02:12 +00:00
swordshine
88d32d6c4a - Converted Fading to script (now can be stifled and copied by Strionic Resonator) 2013-08-07 13:10:08 +00:00
drdev
784e8ba0eb Make arrow icons appear the same size for all 4 directions 2013-08-07 12:54:23 +00:00
swordshine
196ea025a9 - entersBattleFieldWithCounters command converted to etbCounter keyword 2013-08-07 12:16:03 +00:00
swordshine
654f64b604 - reverted some changes because r22822 fixes most of the cases 2013-08-07 12:13:32 +00:00
Chris
b568fdd47b - Added new card names to changes.txt. 2013-08-07 11:27:23 +00:00
Sloth
45e72f9202 - Fixed stale card objects of cards leaving the battlefield having the wrong currentZone variable. 2013-08-07 11:05:31 +00:00
Sloth
4f71f79bb4 - Added Heat Wave. 2013-08-07 10:23:20 +00:00
spr
9aa52d7094 - Added Release Notes section under the Game Settings menu.
- FSkin now offers a fixed font.
2013-08-07 02:40:27 +00:00
Sloth
267dfa7545 - Fixed type of Vastwood Hydra. 2013-08-06 20:16:40 +00:00
spr
f8a086a26b - Split cards (name contains "//") are now rotated 90 degrees in zoomer. 2013-08-06 18:05:52 +00:00
moomarc
c78689db89 - Added War Cadence
- new preference for enabling/disabling the prompt for block costs of 0.
2013-08-06 17:39:37 +00:00
Sloth
44b4e699aa - Script cleanup of Cocoon. 2013-08-06 14:03:13 +00:00
Chris
e3a88484c6 - Added new card names to changes.txt. 2013-08-06 11:49:39 +00:00
swordshine
f2e710f94d - experimental fix of ChangeZoneEffect.changeKnownOriginResolve and SacrificeEffect
- Added Traveling Plague
2013-08-06 11:44:01 +00:00
Sloth
7df35a6203 - Added Cocoon. 2013-08-06 11:14:05 +00:00
Sloth
5558692821 - Fixed "At the beginning of the end step, sacrifice CARDNAME." and friends. 2013-08-06 10:30:57 +00:00
swordshine
47db405dd5 - Fixed Tithe
- updated some scripts
- removed unused imports
2013-08-06 08:58:51 +00:00
swordshine
47faabd7f6 - Converted Strom world for multiplayer 2013-08-06 06:03:31 +00:00
swordshine
409dd8c250 - Added Volcano Hellion 2013-08-06 03:07:04 +00:00
spr
1b995b1c0d - CardPicturePanel now uses new FImagePanel instead of ScaledImagePanel (more details at http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=11218). 2013-08-06 00:38:42 +00:00
spr
1a48640042 - Fix : Two identical cards with one foiled. Picture preview does not display foil image when moving mouse pointer from the non-foil card. 2013-08-05 23:31:50 +00:00
Sloth
9d3a944033 - Fixed makeEvokeSpell messing up in Deck Editor. 2013-08-05 18:02:21 +00:00
swordshine
f1ea2abcc5 - Fixed Knowledge Pool 2013-08-05 13:36:16 +00:00
swordshine
108c0662ca - ChooseCardEffect for Sundering Titan should be mandatory 2013-08-05 13:05:49 +00:00
Chris
4ad15366ae - Added new card names to changes.txt. 2013-08-05 12:16:13 +00:00
swordshine
1c53168e12 - Converted keyword "At the beginning of your upkeep, CARDNAME deals " 2013-08-05 11:52:51 +00:00
swordshine
df5ded6050 - Converted "At the beginning of your upkeep, sacrifice CARDNAME unless you pay"
- Adding counters should be part of resolving of Cumulative upkeep
2013-08-05 11:41:47 +00:00
swordshine
52dfa47d6d - Converted the other two cards with "At the beginning of your upkeep, destroy CARDNAME" keyword to script 2013-08-05 11:19:31 +00:00
moomarc
2df22b5a42 - New Plane: Lair of the Ashen Idol 2013-08-05 11:19:19 +00:00
swordshine
a6a151f98f - Converted Cosmic Horror to script 2013-08-05 11:01:07 +00:00
swordshine
ec645d7f0e - Converted the triggered ability of Echo 2013-08-05 10:49:46 +00:00
moomarc
1d2666c598 - Added Wall of Caltrops 2013-08-05 10:16:06 +00:00
moomarc
85a9990f50 - Added Mangara's Equity 2013-08-05 08:34:17 +00:00
Sloth
6a681094f8 - Added Awesome Presence. 2013-08-05 08:15:53 +00:00
drdev
c8ee474025 Cleanup file header 2013-08-05 08:00:49 +00:00
drdev
8b4da360c1 Create FAbsolutePositioner and FScrollPanel for GUI toolbox
Improve layout of home screen menu panel
Allow scrolling the home screen menu using mouse wheel or arrow buttons
2013-08-05 07:59:48 +00:00
drdev
313ede1465 Add "Set window size" tool for Developer mode 2013-08-05 07:38:37 +00:00
Sloth
2bc8120186 - Improved ControlGainAi. 2013-08-04 18:53:52 +00:00
Sloth
068dce1b56 - Improved Evoke AI. 2013-08-04 18:29:33 +00:00
Sloth
7a110a80b5 - Fixed getDefinedSpellAbilities not using stackInstances. 2013-08-04 12:11:08 +00:00
Chris
a1da50a1dd - Added new card names to changes.txt. 2013-08-04 12:08:38 +00:00
Sloth
8bfe0746dd - Added Ayesha Tanaka. 2013-08-04 10:17:19 +00:00
Sloth
5e625dc08d - More use of playImmediately AI function. 2013-08-04 09:19:57 +00:00
Maxmtg
e16d885d30 renamed list of combatants that dealt 1st strike damage and added a comment for better understanding of code. 2013-08-04 07:48:49 +00:00
swordshine
369405e1f5 - Added Strionic Resonator 2013-08-04 06:34:24 +00:00
swordshine
d34e40ea29 - Plane: Added Jund
- Converted Maelstrom Nexus to script
2013-08-04 06:33:19 +00:00
swordshine
759a9bed7a - Converted Poisonous, Cascade
- Converted Celestial Mantle and Scalpelexis to script
2013-08-04 06:30:14 +00:00
swordshine
a7e0522cf9 - Converted Annihilator 2013-08-04 06:25:38 +00:00
swordshine
44f819e9be - Updated PlayEffect and related scripts for linked abilities 2013-08-04 06:24:48 +00:00
swordshine
f55566956e - Added Arcanum Wings and Grip of Chaos 2013-08-04 06:12:43 +00:00
swordshine
9d9ae41006 - Updated SkieraCube 2013-08-04 06:10:54 +00:00
swordshine
b19a6ae0d4 - Converted Frenzy Sliver, Fixed Sylvan Library 2013-08-04 06:06:45 +00:00
swordshine
d4996103c5 - Fixed RepeatEffect 2013-08-04 06:04:22 +00:00
Sloth
ef4ef398ed - More use of playImmediately AI function. 2013-08-03 21:21:35 +00:00
Sloth
82b6055a6d - More use of playImmediately AI function. 2013-08-03 20:45:15 +00:00
Sloth
994dfe1366 - The AI will now try to activate abilities of permanents about to be destroyed. 2013-08-03 18:40:11 +00:00
Chris
6e71b2f120 updated readme.txt 2013-08-03 13:08:41 +00:00
Sloth
26bea083af - Fixed Gorilla Berserkers. 2013-08-03 08:07:49 +00:00
drdev
800786f314 Prevent card zoomer getting stuck in some cases 2013-08-03 02:17:36 +00:00
Sol
9ff7adab79 - Fix AI logic paying life for Shocklands 2013-08-02 20:07:47 +00:00
Sloth
aa4c4acd6e - Improved playReusable AI. 2013-08-02 19:50:25 +00:00
Sol
345cece010 - Combat Damage now more accurate when considering gaining/losing first strike after first strike damage has been dealt. 2013-08-02 14:57:52 +00:00
Chris
ac00afd142 - Added new card names to changes.txt. 2013-08-02 12:52:51 +00:00
Chris
585e97538c - Cleared out the changes.txt file, now ready for new material. 2013-08-02 12:49:05 +00:00
moomarc
cfcd4e9404 - New Plane: Mount Keralia 2013-08-02 11:54:23 +00:00
Sloth
5865604e0f - Improved DamagePreventAi. 2013-08-02 10:20:28 +00:00
Agetian
398c8026df - A temporary measure to alleviate a severe issue with the game hanging in zoom mode on Linux operating systems when a mouse wheel is accidentally scrolled up while it's pressed to activate the "zoom-on-click" mode. 2013-08-02 08:45:31 +00:00
moomarc
594c22b9f9 - Added No Quarter 2013-08-02 08:09:06 +00:00
Agetian
b91d3a38f3 - Implemented a way to modify the card value if it's a foil.
- Code simplification related to setting a foil finish sprite.
2013-08-02 05:50:50 +00:00
Sloth
d4ddd8114c - Fixed Safe Haven. 2013-08-01 20:38:40 +00:00
Sloth
02bf1b283d - Fixed Dismantle. 2013-08-01 18:19:07 +00:00
Sloth
aa846eed7d - Fixed persist/undying triggering even when the dying has been replaced. 2013-08-01 18:16:23 +00:00
Sloth
487900ea58 - Fixed Hellrider. 2013-08-01 18:07:03 +00:00
Sloth
6d93668df5 - Added Wiitigo. 2013-08-01 12:39:48 +00:00
Sloth
4c73af527c - Fixed Grindstone. 2013-08-01 08:58:33 +00:00
spr
73f02b8c30 - Fix: refactoring introduced potential for NPE. 2013-07-31 22:08:09 +00:00
Sloth
1d51805181 - Updated two of the sliver decks with M14 slivers. 2013-07-31 21:22:31 +00:00
spr
b41dd6ff64 - A couple of Extract Method refactorings. Intention is to use in subsequent updates. 2013-07-31 18:21:10 +00:00
spr
e3f9bf17f6 - Fix : an image cache miss is generating a second redundant entry for the same image. 2013-07-31 18:11:47 +00:00
Chris
7a6ea2f2db [maven-release-plugin] prepare for next development iteration 2013-07-31 12:49:33 +00:00
Chris
ffe6d0b406 [maven-release-plugin] prepare release forge-1.4.5 2013-07-31 12:49:22 +00:00
Chris
3bff036d04 - Added new card names to changes.txt.
- Preparing the changes.txt file for the next beta build and release.
2013-07-31 12:39:07 +00:00
swordshine
b4ee92ea28 - Added Sea Troll
- Phenomenon: Reality Shaping
2013-07-31 11:18:52 +00:00
swordshine
e49147f5c2 - Plane: Eloren Wilds, Norn's Dominion, and Prahv
- Added Mishra's War Machine
2013-07-31 11:13:45 +00:00
swordshine
7aa3910911 - Added Circling Vultures and Mercadias Downfall 2013-07-31 11:06:56 +00:00
swordshine
16f0be2758 - Added Gilded Drake, Nefarious Lich and Rocket Launcher 2013-07-31 11:04:45 +00:00
swordshine
732bc9be73 - Converted Crumbling Sanctuary to script 2013-07-31 11:01:35 +00:00
Sloth
235abb58f4 - Fixed Legion Loyalist. 2013-07-31 07:33:59 +00:00
Maxmtg
5ff00b2c5c fix some possible NPEs (when combat = null) 2013-07-31 06:54:25 +00:00
Agetian
a0d37f7edd - Added the old style (pre-8ED) foil sprite sheet. 2013-07-31 05:29:50 +00:00
Agetian
04a0d0c04c - Foil cards will now correctly display in deck editors (with foil).
- Fixed the foil card display during the match.
2013-07-31 05:28:03 +00:00
drdev
49beec26c5 Fix right-click support for cards 2013-07-31 01:21:39 +00:00
Sloth
7686ef0d73 - Fixed a possible IndexOutOfBounds error in startGame. 2013-07-30 20:54:19 +00:00
Chris
c2d8fb9da2 different approach to 22705 fix. 2013-07-30 13:41:20 +00:00
Chris
9d6afb9f55 [maven-release-plugin] prepare for next development iteration 2013-07-30 12:55:38 +00:00
Chris
de805f68c5 [maven-release-plugin] prepare release forge-1.4.4 2013-07-30 12:55:29 +00:00
moomarc
79a1ed3d03 - small fix to my AILogic from previous commit 2013-07-30 12:45:30 +00:00
Chris
5a451977a4 - Preparing the changes.txt file for the next beta build and release. 2013-07-30 12:44:47 +00:00
Chris
50e482df9a Turn off Tests for ReadDraftRankings 2013-07-30 12:14:59 +00:00
moomarc
576697993e - Added Aegis of Honor 2013-07-30 12:02:09 +00:00
Sloth
7adc31890c - Fixed copying modal spells. 2013-07-30 11:31:55 +00:00
Sloth
afa42a53cd - Fixed tokens leaving the battlefield not unpairing. 2013-07-30 11:15:51 +00:00
asepetci
3cb2b09dd6 updated rankings.txt 2013-07-30 06:17:10 +00:00
drdev
35213d720e Minor update to CHANGES.txt 2013-07-30 01:37:58 +00:00
drdev
dd0b8b94fa Fix Continue and Restart in match screen 2013-07-30 01:15:37 +00:00
Chris
152587e5c4 - Added new card names to changes.txt. 2013-07-29 12:11:06 +00:00
moomarc
70c98f6cea - more changes to generated snake theme 2013-07-29 07:42:24 +00:00
moomarc
288c1d8867 - Added Mark of Sakiko
- added two new cards to the Snakes semi-random deck
2013-07-29 06:46:32 +00:00
drdev
a9ab0c7fc6 Fixed so, after dragging a pane tab to a new location, the pane it was in before selects its most recent remaining tab instead of being blank 2013-07-29 01:51:46 +00:00
Sloth
af89ddf40e - Fixed Vizkopa Confessor with X=0. 2013-07-28 22:31:22 +00:00
Maxmtg
57c7e32361 fix to issue 721 2013-07-28 22:04:29 +00:00
drdev
00779c550c Support card zoom while holding middle mouse button down or holding left and right mouse button down at same time
Fix so cards are "selected" on mouse up instead of mouse down, allowing things like drag drop and zoom to work if the card is currently actionable
2013-07-28 21:30:19 +00:00
Sloth
6f128f61e1 - Improved AttachAI for Fortifications. 2013-07-28 15:14:42 +00:00
Sloth
9ad1c5d2e7 - Improved AI dealing with Immobilizing Ink. 2013-07-28 15:07:06 +00:00
moomarc
d06d797ab1 - Added Sakiko, Mother of Summer 2013-07-28 13:14:02 +00:00
moomarc
14ae68b38c - Added Shizuko, Caller of Autumn 2013-07-28 12:08:14 +00:00
moomarc
85a31e7f04 - small fixes to CHANGES.txt (Vengeful Archon wasn't new and Edge of Malakol in correct section) 2013-07-28 11:56:25 +00:00
moomarc
003081508c - Added Sakura-Tribe Springcaller 2013-07-28 11:51:09 +00:00
moomarc
e62d8e2bdc - Added Journeyman skin to default release skins 2013-07-28 11:38:01 +00:00
Sloth
2cacb05e66 - Fixed prompt of handleLegendRule. 2013-07-28 07:39:18 +00:00
Sloth
8c4f6650c2 - Fixed trigger of Deep-Sea Kraken. 2013-07-28 07:37:39 +00:00
drdev
5da85b079a Save and restore selected tab for each pane
Avoid refreshing entire Deck Editor when opening a deck
2013-07-28 00:50:38 +00:00
drdev
0c9a29000e Added double click support to All Decks list and fixed hover bug 2013-07-27 22:50:02 +00:00
drdev
412b7501e5 Added right-click support for filter buttons
Fixed bugs with handling button click events
2013-07-27 22:06:34 +00:00
Sloth
87ffcf737f - Fixed AddCounter costs with amount of 0. 2013-07-26 05:57:38 +00:00
Chris
10a83ed994 - Added new card names to changes.txt. 2013-07-25 11:40:29 +00:00
Sloth
b9da0fa6bd - Made Vengeful Archon AI safe (but not playable). 2013-07-24 20:36:46 +00:00
Sloth
b2957a56a8 - Flying for Scourge of Valkas. 2013-07-24 16:13:51 +00:00
Maxmtg
e54cef963b improve ai-vs-ai cli: number of games can be specified, removed dialog with cards ai cannot play 2013-07-24 05:33:50 +00:00
Chris
410e562888 - Added a fluff piece to the changes.txt file. 2013-07-23 19:29:33 +00:00
Chris
58a2cb6258 - Added new card names to changes.txt. 2013-07-23 11:33:43 +00:00
swordshine
c658c937a0 - Added Frankenstein's Monster 2013-07-23 10:31:49 +00:00
swordshine
217f78a5e8 - Plane: added Celestine Reef 2013-07-23 07:57:17 +00:00
swordshine
8d3c817195 - Plane: added Agyrem 2013-07-23 06:13:05 +00:00
spr
9ce5fc4f58 - Added a Card Zoomer! 2013-07-23 03:29:34 +00:00
swordshine
b8eff3db00 - Added Edge of Malacol 2013-07-23 00:53:28 +00:00
Chris
cbe7be7d20 - Added a fluff piece to the changes.txt file. 2013-07-22 21:53:29 +00:00
Sloth
021f482aea - AI will now play lands exiled with Uba Mask. 2013-07-22 21:41:29 +00:00
Maxmtg
24b371d58a ai vs ai games can be run from command line interface 2013-07-22 21:03:04 +00:00
swordshine
010edda2cd - Fixed Far // Away 2013-07-22 11:47:29 +00:00
Chris
a2ecdabe8d - Added new card names to changes.txt. 2013-07-22 11:24:47 +00:00
swordshine
deda7f13d1 - Another fix for LKI 2013-07-22 10:56:33 +00:00
swordshine
1152f3f490 - Fixed several cards with sacrifice effect not using LKI 2013-07-22 10:46:48 +00:00
swordshine
89151422ba - Added Planar Overlay 2013-07-22 09:55:55 +00:00
swordshine
0d6ae53860 - Fixed Hoarding Dragon 2013-07-22 09:22:04 +00:00
swordshine
55d0eb904d - Fixed Sporogenesis by squee1968
- Added Twist Allegiance
2013-07-22 07:49:57 +00:00
Maxmtg
ec1f2aa35a Lobby and NetServer moved out of FControl to allow their usage without Gui loaded (and FControl instantiated) 2013-07-22 06:40:36 +00:00
swordshine
f3a6b9f536 - Added Timesifter 2013-07-22 05:15:54 +00:00
swordshine
4f60bcc16d - Added Stronghold Gambit 2013-07-22 01:52:23 +00:00
swordshine
2255ebd533 - Added Steam Vines 2013-07-22 00:47:37 +00:00
swordshine
1ebf2f5003 - Added Suffocation 2013-07-22 00:35:40 +00:00
Maxmtg
2a55d1ea03 card detail panel will not display card id for cards not belonging to any game (id<=0) 2013-07-21 22:06:42 +00:00
Maxmtg
4d9c988059 card id is assigned externally and cannot change.
card ids have to be unique within game to support multiple simultaneous games
2013-07-21 21:31:21 +00:00
Sloth
ef0225c1bd - Fixed Totem Armor crashes. 2013-07-21 17:02:21 +00:00
Agetian
633fec0094 - Terminology correction in ChooseSourceEffect (according to phrasing in the comprehensive rules). 2013-07-21 13:33:39 +00:00
Agetian
d5c9a9c34a - Implemented a part of the rule 119.7: a source can be a face-up card in the command zone. 2013-07-21 11:55:25 +00:00
swordshine
a547bbc815 - Added Rogue Skycaptain 2013-07-21 11:17:03 +00:00
Chris
2af5a26ca3 - Added new card names to changes.txt. 2013-07-21 10:53:48 +00:00
Sloth
24b61319ca - Cleanup. 2013-07-21 10:45:47 +00:00
Sloth
560b18ab14 - Fixed a bug in getAllBlockers (don't know whether it's relevant). 2013-07-21 10:32:34 +00:00
Sloth
2bee73487a - Little fix in executeRampageAbility. 2013-07-21 10:29:35 +00:00
Sloth
767df4ba4f - Fixed a bug in setLabelLayout (don't know whether it's relevant). 2013-07-21 10:20:40 +00:00
swordshine
93522443a4 - Added Sporogenesis 2013-07-21 06:33:11 +00:00
swordshine
af20f7b37c - Fixed Elite Arcanist and Unexpected Results 2013-07-21 05:58:52 +00:00
spr
795c0c2673 - Fix : NullPointer exception if AI and/or Player deck not specified in Sanctioned Format: Constructed view. [#688] 2013-07-21 03:29:10 +00:00
spr
b97e89754b - New turn log entry is emphasized.
- Updated FSkin.java to return default font at a default size instead of point size 1.
2013-07-21 01:25:31 +00:00
Sloth
80ad9ec410 - Fixed Terastodon and friends when not targeting anything. 2013-07-20 21:37:11 +00:00
Maxmtg
ba9fb93a7b removed currentGame from Match (in theory parallel matches are now possible, such as ai vs ai matches started in different threads)
Match no longer has last game outcome.
Win/Lose screens recieve just played game as a parameter to initialize and perform ante manipulations
2013-07-20 21:16:21 +00:00
Sloth
cb461a2304 - Fixed AI not always choosing targets for optional triggers. 2013-07-20 21:01:57 +00:00
Maxmtg
b4f6dbdeb6 added a method to launch game by a single call to FControl (removed duplicate code from controllers specific to game modes) 2013-07-20 20:37:25 +00:00
Sloth
ab9092d53e - Improved AnimateAi. 2013-07-20 20:23:26 +00:00
Maxmtg
b741c594e2 removed unused function 2013-07-20 20:15:06 +00:00
Chris
01973b0712 - Temporary disabling of the first two card tests which caused the build failure. 2013-07-20 20:12:48 +00:00
Sloth
00ffcc50d8 - Fixed LTB triggers on tokens triggering twice. 2013-07-20 14:29:19 +00:00
Chris
e1503691f9 - Added new card names to changes.txt. 2013-07-20 11:32:53 +00:00
Sloth
f8ecb5298f - Improved AI using Vithian Stinger. 2013-07-20 10:52:26 +00:00
Sloth
f83c4a36b5 - Improved AI anticipating activated First Strike abilities. 2013-07-20 10:25:20 +00:00
Sloth
f839c1c41c - Implemented rule 303.4h for auras. 2013-07-20 06:47:48 +00:00
Sloth
f94b44b65f - Prevent crash when AI is forced to play Angel of Salvation. 2013-07-19 22:12:26 +00:00
Sloth
928ac60b42 - Updated 3 quest decks with M14 cards. 2013-07-19 20:54:26 +00:00
Sloth
9bf9c167a7 - Improved AI using Tribute to the Wild. 2013-07-19 18:52:12 +00:00
moomarc
fd63bda12a - Added scheme: Drench the Soil in Their Blood
- Archenemy schemes will only be played on pre-combat main phases.
2013-07-19 15:23:48 +00:00
moomarc
bde583d381 - Moved evaluateBoardState to ComputerUtil from ComputerUtilCard 2013-07-19 15:07:42 +00:00
moomarc
6a6050dea2 - Added scheme: Choose Your Champion and supporting AI logic.
- Added a basic board state evaluation that returns the player from a list with the best rating. Could probably be improved with better weightings.
2013-07-19 14:51:49 +00:00
Chris
355ab88ba9 - Added new card names to changes.txt. 2013-07-19 12:17:12 +00:00
moomarc
adc22f97ff - Added Cycle of Life 2013-07-19 11:32:26 +00:00
swordshine
fdd53c2668 - Fixed Fact or Fiction 2013-07-19 08:43:32 +00:00
moomarc
37e3dac97f - Updated my details in the pom.xml 2013-07-19 06:43:52 +00:00
Sloth
ac99a905ec - Little addition for Shape of the Wiitigo. 2013-07-19 05:43:37 +00:00
Maxmtg
5b91a68b2f Moved quest game initialization to fcontrol, since quest was a bad dependence from game
separated createGame and tartGame to make Fcontrol.attach optinal and called from UI code that starts a game
2013-07-18 21:37:02 +00:00
Sloth
5b2ceef0aa - Added Shape of the Wiitigo. 2013-07-18 18:58:58 +00:00
spr
2c54c811d5 - Fix: theme combo displays "Dark Ascension" when current theme is "Default". [#716] 2013-07-18 16:36:40 +00:00
asepetci
55a8d9a552 updated rankings.txt 2013-07-18 12:49:34 +00:00
Chris
93227be07e - Added new card names to changes.txt. 2013-07-18 10:14:38 +00:00
moomarc
42adaacb04 - Added Thought Dissector 2013-07-18 09:19:06 +00:00
moomarc
0b6cbb0c43 - Added Spatial Binding
- fixed state based effects handling auras and equipment when they would be indirectly phased out but can't
2013-07-18 08:20:46 +00:00
moomarc
37568e0410 - Added Tide of War
- added BlockersDeclares trigger
2013-07-18 06:56:55 +00:00
Sol
eba08dd086 - Adding Fat Pack info for M14 2013-07-18 01:53:05 +00:00
Sol
3472ce4675 - Redraw after Morph Up 2013-07-18 00:58:29 +00:00
spr
0465095bbc - New Themed ComboBox setting to enable/disable themed combos addressing coloring clashes in Mac OSX causing readability problems [#715]. 2013-07-17 22:45:44 +00:00
Sloth
6134d2585c - Fixed trigger of AI's Sphinx-Bone Wand not being removed from stack. 2013-07-17 21:00:42 +00:00
Sloth
344643ffdd - The Trigger of the harbingers is now optional. 2013-07-17 20:11:55 +00:00
Sloth
4bfc8bb117 - Populate is now mandatory. 2013-07-17 20:03:27 +00:00
Chris
cce1d2f361 - Added new card names to changes.txt. 2013-07-17 11:58:34 +00:00
moomarc
ab68c32549 - Fixed Reverent Silence (and other "each opponent gains life" cost) 2013-07-17 10:53:04 +00:00
moomarc
0c6275777e - Added Hallow 2013-07-17 10:24:23 +00:00
Sloth
0ae4cd25b6 - Implemented multiplayer rule 802.4a: "A player can block only creatures attacking him or a planeswalker he controls". 2013-07-17 10:08:46 +00:00
Sloth
8d030f3fac - Added a copy of Tsabo's Assassin to the quest deck Hermes Conrad 2. 2013-07-17 09:27:36 +00:00
moomarc
e6df31e338 - Added Mindbender Spores 2013-07-17 06:44:38 +00:00
Agetian
6a09f78fc5 - Fixed a bug related to triggers firing when counters are removed. 2013-07-17 05:28:00 +00:00
Sol
57844e8c7c - Add references for Extort 2013-07-17 02:50:31 +00:00
Sol
845d67db52 - Fixing Ninjutsu cards not setting unblocked that was broken in r22261
Most hilarious NPE at a line commented with "// this is called after declare blockers, no worries 'bout nulls in isBlocked"
2013-07-17 00:39:22 +00:00
Sol
4f5de217e7 - Fix issue with Quest Wins Per Booster being set to 0 2013-07-17 00:13:20 +00:00
Sol
39d18a48c8 - Updating Oracle N-Z 2013-07-16 23:23:01 +00:00
Sol
0bea980aa7 - Updating oracle texts A-M 2013-07-16 23:22:20 +00:00
moomarc
b0e09f8cff - Added Samite Blessing 2013-07-16 17:16:11 +00:00
spr
299ab754b3 - New Visual Themes setting to hide or show background image on match screen. Default show. 2013-07-15 19:19:01 +00:00
spr
cada68dee5 - Converted AI Profile list to themed combo and moved to top of GamePlay section. 2013-07-15 19:04:38 +00:00
spr
70c2d18abe - Converted Skins list to themed combo and added to new Visual Themes section. 2013-07-15 18:56:39 +00:00
spr
dd34b9bf0f - Refactoring. Moved Dev Mode and Log Verbosity into Advanced Settings section. Refactored FComboBoxPanel. 2013-07-15 18:46:04 +00:00
moomarc
4c52a82e85 Fixed Faithful Squire//Kaiso, Memory of Loyalty (flip side was missing flying) 2013-07-15 18:08:08 +00:00
Chris
99f30eb07e - Added new card names to changes.txt. 2013-07-15 11:38:01 +00:00
spr
7f67bfb2df - All reset buttons now appear under Troubleshooting section.
- Increased visibility of Troubleshooting section by moving to the top of the preferences screen.
- Added confirmation dialogs to all reset buttons.
2013-07-15 09:18:31 +00:00
spr
4a2c0a2536 - Fix: UI_SKIN default value should be "Default" instead of "default". 2013-07-15 09:00:29 +00:00
swordshine
019685ef9b - Fixed Debuff Effect 2013-07-15 05:54:45 +00:00
swordshine
33b29ca55d - Fixed ChangeZoneAll effect remember things twice (Winds of Charge) 2013-07-15 05:45:33 +00:00
Sol
e9d962388d - Bugfix for Finest Hour: Combats this turn needs to be incremented before triggers are run. 2013-07-15 03:59:05 +00:00
Sol
913a6ec653 - ChooseCard will now use the "order" dialog instead of multiple popups if you need to choose more than one Card
- Convert Phyrexian Dreadnought and Sutured Ghoul to script
2013-07-15 02:56:54 +00:00
swordshine
d2c2138be6 - Added Kudzu 2013-07-15 00:18:51 +00:00
Chris
4bb0b15adc - Added new card names to changes.txt. 2013-07-14 12:02:05 +00:00
swordshine
6aa57212a9 - Vanguard: added Enigma Sphinx Avatar 2013-07-14 09:38:32 +00:00
swordshine
5a30bc849e - Added Autumn's Veil 2013-07-14 07:00:17 +00:00
swordshine
995c5705e5 - Added Nettlevine Blight 2013-07-14 05:54:57 +00:00
swordshine
c580b15643 - Fixed Mesmeric Sliver 2013-07-14 05:14:20 +00:00
swordshine
9a97bc6824 - Fixed Deadeye Navigator 2013-07-14 05:04:40 +00:00
Chris
9c58d20320 - Cleared out the changes.txt file, now ready for new material. 2013-07-13 12:40:03 +00:00
swordshine
210e06fd62 - the new Gaea's Touch 2013-07-13 12:26:06 +00:00
Sloth
cb085223b3 - Fixed Mindstab Thrull crash. 2013-07-13 12:06:18 +00:00
swordshine
b8954ef27b - Fixed Golem Artisan and Lunar Avenger 2013-07-13 06:06:45 +00:00
spr
b7ca99dd55 - New Game Log Verbosity setting. 2013-07-13 02:12:25 +00:00
swordshine
191783d30c - Fixed Jodah's Avenger 2013-07-13 01:18:51 +00:00
Sloth
0ba70bb4f7 - Fixed Guardian of the Ages. 2013-07-12 20:31:07 +00:00
Sloth
277f63609c - Fixed Thorncaster Sliver. 2013-07-12 20:27:49 +00:00
Sloth
cd01b7ba6b - Fixed Young Pyromancer. 2013-07-12 20:23:44 +00:00
Sloth
18a25447a6 - Moved Unearth replacement effect to GameAction.changeZone so it will work correctly with triggers.
- "If CARDNAME would be put into a graveyard from anywhere, reveal CARDNAME and shuffle it into its owner's library instead." will now be turned into a proper replacement effect with a macro.
2013-07-12 20:22:39 +00:00
Sol
93468a849c - Converted Transmute Artifact to script 2013-07-12 18:42:22 +00:00
Chris
bc864fa71e [maven-release-plugin] prepare for next development iteration 2013-07-12 15:11:40 +00:00
Chris
63e46dcf12 [maven-release-plugin] prepare release forge-1.4.3 2013-07-12 15:11:29 +00:00
Sloth
3ac1ddb51e - Reverted r22549 and used another fix. 2013-07-12 13:39:21 +00:00
Chris
18d3b1ffa8 - Preparing the changes.txt file for the next beta build and release. 2013-07-12 12:47:12 +00:00
Sloth
3c713fb362 - Fixed Karn Liberated. 2013-07-12 11:25:09 +00:00
swordshine
c74a577030 - Legend rule for Brothers Yamazaki 2013-07-12 09:49:13 +00:00
Sloth
a849c03651 - Fix for last commit. 2013-07-12 09:42:41 +00:00
Sloth
bf8be3096d - Moved CardsAddedThisTurn registration from Zone.add to changeZone. 2013-07-12 09:32:38 +00:00
jsv
34a5375a21 Fixed a typo in Goblin Replica. 2013-07-12 06:19:56 +00:00
swordshine
2303f414bb - Fixed Bubbling Cauldron
- Fixed Rally the Righteous
- Card Panel: keyword "Unblockable" changed to "Can't be blocked."
2013-07-12 00:31:56 +00:00
spr
8331e86624 - Modified setting. "Text/Mana Overlay" replaced with individual toggle setting for Card Name, P/T and Mana Cost overlays. 2013-07-11 23:00:01 +00:00
spr
c591902722 - Addresses issue 0000659 concerning the sidebar menu options extending past bottom of screen. Added new Compact Menu setting that will prevent more than one menu group from being open at a time which should alleviate this problem. 2013-07-11 15:30:30 +00:00
Chris
36a478d78d - Added new card names to changes.txt. 2013-07-11 11:15:25 +00:00
jsv
6f278cead4 Fixed a typo in Legolas deck description. 2013-07-11 11:03:45 +00:00
spr
6fe7063664 - Fix: Opening Deck Editor crashes Forge if you have previously dragged Draw Order to its own tab and restarted Forge. [ISSUE 710]. 2013-07-11 07:12:22 +00:00
Maxmtg
c1f903afcd Using Serum Powder from input mulligan runs exile-draw in a right thread 2013-07-11 06:26:06 +00:00
swordshine
2344bf696e - Added Colossal Whale and Banisher Priest
- Fixed targeting of Postmortem Lunge
- Fixed Mask of Memory
2013-07-11 00:20:58 +00:00
Maxmtg
ba93f2a431 AI: changed many calls to accept Collection<T> instead of List<T>
GameAction - legend rule and planeswalker rule are updated to match changes introduced with "Magic 2014 Core Set"
InputSelectCardsFromList also accepts any Collection<T>, not just List<T>
PlayerControllerHuman - chooseSingleCardForEffect tries to use InputSelectCardsFromList when all cards are in Battlefield or own hand
2013-07-10 22:07:08 +00:00
Sloth
15b3698619 - Updated some SVars of M14 cards. 2013-07-10 20:06:52 +00:00
Sloth
10060a66f8 - Updated some SVars of M14 cards. 2013-07-10 18:47:40 +00:00
Maxmtg
3ccc53a63c sends events when damage assigned changes 2013-07-10 13:05:23 +00:00
Maxmtg
cd120bcad4 Added redraw for times when AI declares attackers and combat ends to show/hide combat icons
"exalted" ability inlined (because its routine became simplier after it had been replaced with script)
2013-07-10 12:22:26 +00:00
Chris
d282f07720 - Added a fluff piece to the changes.txt file. 2013-07-10 11:21:22 +00:00
Maxmtg
1d66df366f sword icon removed from creature that is un-declared as attacked from InputAttack 2013-07-10 11:12:40 +00:00
Sloth
3a0f0cdfa8 - Updated the quest deck Bela Lugosi 3 (with input from Nordos). 2013-07-10 06:17:24 +00:00
Sloth
ed291cfe4d - Restored AI using the DiscardMeByOpp SVar. 2013-07-10 06:13:48 +00:00
swordshine
eec5a085e8 - Fixed Marauding Maulhorn
- Updated SkieraCube
2013-07-10 05:36:37 +00:00
Sol
44ebba25e5 - Fix Corpse Hauler targeting 2013-07-10 01:57:52 +00:00
Sloth
eb484df801 - Added M14 to some lists. 2013-07-09 18:57:50 +00:00
Maxmtg
a3b84f0876 m14 set description file 2013-07-09 18:54:55 +00:00
Sloth
3aaa7345f6 - Improved canPlayAI() of LevelUp abilities. 2013-07-09 18:45:13 +00:00
Sloth
7559f7c2f9 - Merged M14 branch into trunk. 2013-07-09 17:59:16 +00:00
Maxmtg
e48e7aa544 redraw battlefield when mana payment is cancelled 2013-07-09 16:04:15 +00:00
swordshine
55a71ea46a - Fixed Dance, Pathetic Marionette 2013-07-09 13:13:56 +00:00
Agetian
6879729b01 - Implemented Archenemy rules 904.5 and 904.6 (the Archenemy has 40 life and always takes the first turn of the game). 2013-07-09 11:50:00 +00:00
Chris
ad5f9232f7 - Added new card names to changes.txt. 2013-07-09 11:26:06 +00:00
Sloth
45c44fd936 - Fixed Sleeper Agent. 2013-07-09 08:20:39 +00:00
swordshine
f7cc0dbd00 - Fixed searching a card in library and put it on the top 2013-07-09 07:40:45 +00:00
Maxmtg
0bf2cc8442 playSpellAbilityNoStack - added parameter 'mayChooseNewTargets' - it is passed to HumanPlaySa method and is a key to call doTrigger on AI's side 2013-07-09 05:55:43 +00:00
swordshine
23c8590123 - M14: Added Artificer's Hex 2013-07-09 04:06:12 +00:00
Sol
5ad15655a9 - Convert Master of the Wild Hunt to script 2013-07-09 01:28:52 +00:00
Maxmtg
59249a7155 Prerequisites to launch Forge without UI. (used by ai-vs-ai CLI simulation and by dedicated server mode - when it's done) 2013-07-08 23:05:40 +00:00
Maxmtg
7f545935b4 playNoStack called via playercontroller 2013-07-08 22:37:45 +00:00
Maxmtg
fe9001a550 moved the possible options evaluation down the call stack 2013-07-08 22:23:41 +00:00
Maxmtg
313bed630a moved choice of ability modes to PlayerController - got rid of both: bad imports in CharmEffect (gui classes) and isHuman() call 2013-07-08 22:14:59 +00:00
Sloth
d030b09c51 - moveToLibrary now redirects to changeZone. 2013-07-08 20:52:04 +00:00
Sloth
454557a468 - Improved Charm AI for Tormentor Exarch. 2013-07-08 20:43:36 +00:00
Sloth
1c7a1e3d8f - Improved AI using Tormentor Exarch. 2013-07-08 19:58:17 +00:00
Sloth
e3e937354b - Fixed chooseOptionsAi causing NPE's. 2013-07-08 19:38:55 +00:00
Sloth
83936a924e - Fixed Effects not leaving Command zone. 2013-07-08 19:25:51 +00:00
Maxmtg
0c74043668 transformed cards generate gameeventcardchanged 2013-07-08 17:41:20 +00:00
swordshine
4a7cee412c - Fixed Quicken 2013-07-08 14:47:23 +00:00
Sloth
b7972342dc - Fixed setTriggeringObjects of AttackerBlockedTrigger. 2013-07-08 14:06:09 +00:00
swordshine
7e0f5e1401 - M14: Added Tenacious Dead and Xathrid Necromance 2013-07-08 14:00:21 +00:00
swordshine
d55ced465d - M14: Added Dismiss into Dream, Elite Arcanist, Tidebinder Mage, Zephyr Charge 2013-07-08 12:29:50 +00:00
Chris
8d2bf7571a - Added new card names to changes.txt. 2013-07-08 12:29:05 +00:00
moomarc
764da32cba - Fixed Polluted Bonds for multiplayer games 2013-07-08 11:54:07 +00:00
jsv
1d6a015939 Fix Tolarian Entrancer's script 2013-07-08 10:18:03 +00:00
swordshine
68a9f55f53 - M14: Added Voracious Wurm 2013-07-08 07:24:32 +00:00
swordshine
e638e7f2c9 - M14: Added Angelic Accord 2013-07-08 07:15:04 +00:00
swordshine
d3aef40bb3 - Fixed a bug when searching a card in the library and put it on the top 2013-07-08 01:05:11 +00:00
Sol
e081e66a13 - Only reset quest new cards at the beginning of the match, not the end of each game 2013-07-08 00:15:54 +00:00
Sol
7f055ddb4b - Adding some references to two scripts 2013-07-08 00:15:04 +00:00
Maxmtg
79f8704a00 PhaseHandler: added a missing check for gameover state between SBA and givePriorityToPlayer (handles draws properly)
Zone, GameAction: inlined some single-use very short functions
2013-07-07 22:58:02 +00:00
Maxmtg
df3b938ed0 changed order or actions performed on declare blockers step: declare, pay extra costs, fire event, then fire triggers
EventVisualizer.java will be able to play sounds when ai is blocking
2013-07-07 22:09:20 +00:00
Sloth
cf27269f08 - Added SVar:RemAIDeck:True to cards with banding. 2013-07-07 19:41:42 +00:00
Maxmtg
4d0b02e049 BlockersDeclaredEvent causes redraw of all blocker cards (they'll get icons this way) 2013-07-07 19:33:36 +00:00
Maxmtg
f8bb07ec35 Zone.add(Card) is now a shortcut to zone.add(card, Integer). This allows to remove a couple of if's in GameAction 2013-07-07 19:32:17 +00:00
Sloth
601d789662 - Implemented official rules for tokens leaving the battlefield (fixes Cloudshift). 2013-07-07 16:47:49 +00:00
Sloth
54b7e8f1b1 - Fixed two trigger descriptions. 2013-07-07 15:30:29 +00:00
Sloth
33df962e70 - Fixed triggers with targets and a cost not being removed from the stack when the cost is not payed. 2013-07-07 15:23:23 +00:00
Maxmtg
ab894eeca3 newly declared attackers and defenders are highlighted at once 2013-07-07 14:45:06 +00:00
Maxmtg
bf4e21933c Added another event bus to MatchUI. Attached sound system to this bus
Attack/Block inputs use this bus to request sounds playback and UI updates
SoundSystem - remove mostly duplicated play/playSync calls - now there's one call with a single mandatory parameter.
corrected tabs into spaces somewhere in sound system (why can't Agetian just tune up his IDE?)
2013-07-07 14:26:09 +00:00
Chris
0ea254e94c - Added new card names to changes.txt. 2013-07-07 13:11:53 +00:00
Sloth
94ae69813f - Improved AI using mana sources with Combo Any. 2013-07-07 12:51:03 +00:00
Maxmtg
f6782893e7 GameAction - using a couple of variables to cache toBattlefield, fromBattlefield, extracted method to fix attachments 2013-07-07 12:44:50 +00:00
Maxmtg
54ba881dd2 remove unused import 2013-07-07 12:31:58 +00:00
Sloth
2cd7cece85 - First steps towards AI canceling payment of a SpellAbility when it fails to pay (instead of throwing an error). 2013-07-07 11:56:49 +00:00
Sloth
74e2bcfc37 - More NPE prevention of cards without sets in preparePlayerLibrary. 2013-07-07 11:37:11 +00:00
Maxmtg
d3f5758df8 Fixing typo 2013-07-07 11:08:29 +00:00
swordshine
da052c02e2 - Fixed mana ability (Deathrite Shaman's first ability is not a mana ability) 2013-07-07 09:55:35 +00:00
Agetian
f063f52981 - Properly fixing Discard effect for cards like Last Rites. 2013-07-07 07:53:20 +00:00
swordshine
2646d7e656 - M14: Added Pyromancer's Gauntlet 2013-07-07 07:43:00 +00:00
Agetian
0e22f73d11 - Trying to fix a bug with the DiscardEffect that won't function properly for cards asking to discard more than 1 card (e.g. Last Rites). NOTE: This is an experimental hack, please review line 395 in PlayerControllerHuman, not sure how to properly resolve that part. 2013-07-07 06:28:37 +00:00
swordshine
2d7ada5106 - Fixed a bug that tokens don't move to library 2013-07-07 06:03:56 +00:00
Maxmtg
c8524485bb PlayerController.playSaNoStack - removed obvious parameter (player) 2013-07-06 23:28:37 +00:00
Maxmtg
191a8e4e43 This restores Valacut - Scapeshift combo
Have to figure out how this influences on OpeningHandEffects
2013-07-06 23:16:34 +00:00
Maxmtg
4f3e058d64 Game event log also reports elements from call trace 2013-07-06 22:32:26 +00:00
Maxmtg
da33b4f406 Witch-maw nephilim: trigger is unconditional, the ability is checking for conditions instead 2013-07-06 21:29:55 +00:00
Sloth
d5851fc4ed - Fix for Soul's Fire. 2013-07-06 20:56:49 +00:00
Sloth
de9adadf04 - Another fix for Deadshot. 2013-07-06 20:54:06 +00:00
Sloth
08f1ba8186 - Fixed more cards calculating with LKI values. 2013-07-06 20:45:41 +00:00
Sloth
135239eabe - Fixed Deadshot. 2013-07-06 20:11:55 +00:00
Maxmtg
ec838bb8a1 reverted checkstatic abilities after resolving a subability 2013-07-06 19:38:47 +00:00
Chris
52bc9b6326 - Added new card names to changes.txt. 2013-07-06 12:50:46 +00:00
Maxmtg
e7eff63585 added call to checkStaticAbilities to changeZone - this will take into consideration creatures' static abilities before firing ETB trigger.
removed same calls where they would be duplicate (player.playLand, AbilityUtils.resolveSubAbilities)
2013-07-06 09:22:15 +00:00
Agetian
21222511dd - Added proper AI battlefield conditions for Akoum.
- Minor comment modification.
2013-07-06 09:00:26 +00:00
Agetian
ffb7924585 - Code simplification in RollPlanarDiceAi. 2013-07-06 05:24:26 +00:00
Maxmtg
990f7ab9dc removed some excessive calls to checkStaticAbilities. (keep in mind they are always checked on priority along with state-based actions) 2013-07-05 22:55:23 +00:00
Maxmtg
30f85737c8 Rampage turned into api-based scripted effect
scripted witch_maw_nephilim.txt 2nd ability and removed hardcode
added some syntax sugar in TriggerType.java
2013-07-05 22:06:23 +00:00
Sloth
f1f196585d - Fixed Blood Tyrant. 2013-07-05 21:38:19 +00:00
Sloth
7bbeed304f - Fixed a bug in canPlayAI of ClashAI. 2013-07-05 21:36:12 +00:00
Sloth
bdbe7b25eb - Fixed Vendetta and Devour in Shadow calculating LKI toughness. 2013-07-05 21:32:04 +00:00
Maxmtg
d6e3576203 Alphabetically sorted trigger types 2013-07-05 20:56:04 +00:00
Maxmtg
c0411273a9 Flanking - converted to script (to use Pump API and it's ui updates already set up)
checkStateEffects - removed many calls leaving only the ones clearly stated by rules, in most cases calls replaced by checkStaticAbilities
in checkStateEffects - extracted some method performing certain state actions
2013-07-05 20:40:53 +00:00
Maxmtg
789cae29eb Umbra stalker - converted to script
inlined some chroma-related routines, and related to card list
2013-07-05 19:01:39 +00:00
Agetian
d668d9c3bb - Added some conditions to the AI for rolling a planar die.
- Some of the planes will now be used more intelligently by the AI depending on battlefield conditions.
- Some AI hint fixes for planes.
2013-07-05 18:49:47 +00:00
Maxmtg
4b8effe250 Added exceptions to constructor of PaperCard to prevent creation of illegal instances without set 2013-07-05 18:27:18 +00:00
Maxmtg
896a9a0a23 fix NPE happening at CHand init 2013-07-05 18:23:47 +00:00
Sloth
a28929bc36 - Fixed AI dodging the payment of AlternateAdditionalCost. 2013-07-05 18:13:53 +00:00
Sloth
59606709a6 - Fixed cards without set causing NPE's when foiled. 2013-07-05 18:05:45 +00:00
Sloth
5398d53408 - Added AI support for Fight triggers (Gruul Ragebeast). 2013-07-05 16:25:17 +00:00
Maxmtg
31e272711f Static abilities update: excludes from event cards in hidden zones like library (that won't be drawn anyway)
currentZone field added to card, it's a shortcut used to avoid enumeration of cards in all zones to find the requested one
2013-07-05 16:23:38 +00:00
Maxmtg
b12abc4533 Events are fired when static abilities recalculate 2013-07-05 15:06:15 +00:00
Maxmtg
628430f0e9 Bushido also uses cardscript with API = pump 2013-07-05 13:30:04 +00:00
Maxmtg
1f3501d8de Log_events moved to Game class (as they are submitted there)
Pump and PumpAll effects now fire update card stats event - for both start of effect and end of it.
Exalted effect - refactored to use scripted ability (the script is hardcoded)
toString routines for some events
2013-07-05 13:07:54 +00:00
Agetian
7e3858ef31 - Added a way to deprioritize the AI planar die roll compared to casting spells for mana.
- Made the AI roll the die for some of the planes multiple times (but only after casting spells).
- Some other optimizations and modifications of the plane AI hints.
2013-07-05 12:59:51 +00:00
jsv
b8613c5cdf Fixed Imperiosaur's cost restriction. 2013-07-05 06:37:18 +00:00
Agetian
8b8bb25717 - Added info about the Planechase AI extension to the list of changes. 2013-07-05 05:34:37 +00:00
Agetian
3871508385 - Fixed the AI hint for Grixis. 2013-07-05 05:23:06 +00:00
Agetian
32a5f4389b - Consolidating AI hints for planes in Planechase into a single "AIRollPlanarDieParams" parameter.
- Adding a foundation for the condition specifications in AI hints for planes.
- Code simplification in RollPlanarDiceAi.
2013-07-05 05:20:40 +00:00
Maxmtg
fadaedc382 excessive calls to SBE check removed 2013-07-05 05:19:14 +00:00
Agetian
1772faae3f - Restructured the logic of AI planar die rolls a little bit.
- Added a way to specify the minimum turn in which it is viable to start rolling a planar die for a particular plane. Added this setting to some planes which require a bit more context on the battlefield before their Chaos rolls start to make sense.
- Added an AI profile variable specifying the minimum turn in which the AI will start rolling the planar die in general unless the plane has an override specified (default AI - on its second turn, reckless AI - on its first turn).
2013-07-04 18:05:07 +00:00
Sloth
37d4245363 - Fixed Soul's Fire. 2013-07-04 16:41:04 +00:00
Sloth
2e8bb882eb - Fixed AnimateAi. 2013-07-04 16:09:15 +00:00
Agetian
73834a4455 - Added an extra break to the planar die AI logic (so that part doesn't break inadvertently with further changes). 2013-07-04 15:48:55 +00:00
Agetian
abf7382520 - Fixed the logic for the AI planar die roll chance.
- Added an ability to set a chance for the AI hesitating to roll a planar die (default AI at 10%, reckless AI at 0%).
2013-07-04 15:47:32 +00:00
Agetian
6ebfe9b630 - Adding AI hint SVars to Planechase plane cards. Most planes are set to "roll once each turn" for the AI right now, which seems to work fine for a very basic AI (better than nothing). Dangerous or unpredictable planes like Academy of Tolaria West, Isle of Vezuva, Kharasha Foothills, Minamo, Takenuma, Windriddle Palaces are currently set to "never roll" for the AI. Feel free to expand. 2013-07-04 15:40:08 +00:00
Sloth
310577f0c2 - Improved checkSacrificeCost AI saccing lands. 2013-07-04 15:31:27 +00:00
Agetian
2fe6482730 - Modified the default AI profile to account for the new properties as well as for the change of the mulligan threshold property name.
- Added a new AI profile (Reckless) that mulligans more aggressively and rolls planar dice more aggressively.
2013-07-04 15:02:39 +00:00
Sloth
10c285f081 - Added info about chosen player and hauntings to CardDetailPanel. 2013-07-04 15:02:06 +00:00
Agetian
9d1b5833a9 - Minor fixes to the planar dice roll AI.
- Default max rolls per turn and chance to roll are now tied to AI profile properties.
2013-07-04 15:01:51 +00:00
Agetian
eb1234832e - Max AI planar die rolls now correctly check for the number of planar die rolls instead of spell ability activations. 2013-07-04 14:36:02 +00:00
Agetian
3eac899af5 - Minor code cleanup. 2013-07-04 14:24:35 +00:00
Agetian
5195708028 - Fixed the random chance for AI planar die rolls. Removed a debug line. 2013-07-04 14:17:28 +00:00
Agetian
00977986df - Default max number of planar die rolls per turn for the AI is 1. The AI will prefer to roll the planar die in Main 2 unless the AIHintRollDieInMain1:True AI hint SVar is set. 2013-07-04 14:10:28 +00:00
Chris
a5887f7dd6 - Added new card names to changes.txt. 2013-07-04 12:18:06 +00:00
Maxmtg
05cc118282 updated library creation code to generate a single event for the whole library (instead of events on per-card basis) 2013-07-04 09:41:42 +00:00
Maxmtg
cb42cf6ceb added event 'card state changed' to un-animate command 2013-07-04 09:34:40 +00:00
Agetian
8f4dd0225b - Added an override for chkAIDrawback in RollPlanarDiceAi in case it may be necessary in the future. 2013-07-04 08:14:04 +00:00
Maxmtg
e15e7d5ecc Fix possible NPE 2013-07-04 08:11:27 +00:00
Agetian
02d9eaa21b - Renamed a SVar in RollPlanarDiceAi for consistency. 2013-07-04 08:09:50 +00:00
Agetian
982a1c1fd3 - Renamed the SVars for RollPlanarDiceAi, added a possibility to define the maximum number of rolls per turn for the AI. 2013-07-04 08:05:11 +00:00
Sloth
d2067be9d1 - Possible fix for NPE in getCardsAddedThisTurn (wasn't able to reproduce it, so can't check whether it's fixed). 2013-07-04 08:03:13 +00:00
Agetian
2a46a6a9d0 - Added the foundation of the AI for rolling planar dice. By default it does nothing and behaves as the old functionality (never roll the planar die). SVars can be specified signaling if and how often the AI should roll the planar die. Currently limited as I have no idea how to make the AI, for instance, to only use the ability to roll the die once per turn. Feel free to expand this AI as necessary. 2013-07-04 07:30:32 +00:00
Agetian
816c5bb040 - Sound System: fixed the "life loss" sound playing when the player gains life.
- Sound System: added a separate sound (linked to the file "life_gain.wav") for when the player gains life.
2013-07-04 06:37:52 +00:00
jsv
356d9170f0 A small fix for Starfire 3 duel deck (wrong header line resulting in NPE) 2013-07-04 06:31:25 +00:00
swordshine
0d5afe48a8 - M14: Added Bogbrew Witch, Bubbling Cauldron, Festering Newt,, Kalonian Hydra, and Syphon Sliver 2013-07-04 00:27:46 +00:00
Sloth
0eac173451 - Added some SVars to the denizens. 2013-07-03 20:42:03 +00:00
moomarc
355c2e78ec - Added Fractured Powerstone 2013-07-03 19:05:49 +00:00
Agetian
4722471b08 - Specifying which sets always have a foil card in the common slot in boosters. 2013-07-03 19:03:38 +00:00
Agetian
1eed542f46 - Adding a field to specify whether the booster has a foil always in the common slot (FoilAlwaysInCommonSlot=True) or in the slot belonging to the rarity of the card (FoilAlwaywsInCommonSlot=False). 2013-07-03 19:02:44 +00:00
jendave
bb1444b7f9 Bump freemarker dep. Start work on new osx profile. 2013-07-03 18:28:51 +00:00
Maxmtg
4c7ab1a47f rename field in CardDamagedEvent
fix possible "weird NPE" at CMatchUI.java:344
2013-07-03 18:10:02 +00:00
Chris
b67a84800b - Added new card names to changes.txt. 2013-07-03 12:26:23 +00:00
Sloth
7d3ffe324a - Fixed AI's static abilities bypassing addAndUnfreeze (and miss ActivationNumber increase). 2013-07-03 12:17:56 +00:00
Maxmtg
f6ef39867c Implemented partial updates for sincle cards in battlefield 2013-07-03 12:10:34 +00:00
Maxmtg
7a3b82e40b deck lists are properlu updated on click to radiobutton (not hover) 2013-07-03 10:54:43 +00:00
Maxmtg
c3c847c5ff * Zone classes cleanup, they now have reference to game, can contain only cards, used shared code to add cards, generate GameEventZone 2013-07-03 10:45:01 +00:00
Maxmtg
2e4ec0e402 added UI updates in PumpEffect and on Attachment changes 2013-07-03 08:44:01 +00:00
jsv
cca6e94a71 Fixed morphs causing an NPE in AiController.getSpellAbilityToPlay. 2013-07-03 07:07:20 +00:00
Agetian
20addc10ac - Setting the chance of a foil in Modern Masters booster to 100% (does not currently apply as it's not hooked to booster generator yet). 2013-07-03 05:39:33 +00:00
Maxmtg
2a49c009c0 Removed MyObservable, components now recieve updates from game event bus.
Please report UI not updating on time
2013-07-02 23:30:26 +00:00
Sloth
077e4916fc - Fixed type of Ghoulcaller's Chant. 2013-07-02 20:29:56 +00:00
Sloth
ae21ba28c7 - Fixed Legion's Initiative. 2013-07-02 18:39:45 +00:00
Sloth
d5cf59cb16 - Fixed The Very Soil Shall Shake. 2013-07-02 18:24:56 +00:00
Agetian
ba3bb79b52 - Set the default foil chance in booster to 16% (approximately 1/6) which seems to be the average for the majority of sets. Can be overridden in edition definition files via FoilChanceInBooster option. Not currently used by the booster generator. 2013-07-02 17:09:26 +00:00
Sloth
4aed00d954 - Fixed cards moving to the library not creating CombatLKI's. 2013-07-02 15:29:00 +00:00
Chris
1052537fc6 - Added a fluff piece to the changes.txt file. 2013-07-02 12:23:52 +00:00
Maxmtg
6d30afb166 fix npe parsing quest challenges without difficulty 2013-07-02 10:55:54 +00:00
Sloth
60c2ab84d8 - Updated some SVars. 2013-07-01 21:17:54 +00:00
Sloth
4d9b270d3a - Fixed confirmTrigger sometimes revealing hidden information. 2013-07-01 16:43:41 +00:00
Sloth
86bf9f2a28 - Fixed paying mana with Elvish Spirit Guide. 2013-07-01 16:31:55 +00:00
Sloth
ed1e99353f - Expanded NonStackingAttachEffects (R-V). 2013-07-01 16:25:54 +00:00
Sloth
4d7749e265 - Fixed AI attacking with a single Hero of Bladehold twice. 2013-07-01 16:25:13 +00:00
Agetian
368e3c36b9 - fixed the way the foil overlay is drawn over the card picture panel, simplified the related code a little bit. 2013-07-01 14:13:20 +00:00
Agetian
ef44922aa6 - potential NPE prevention. 2013-07-01 12:16:56 +00:00
jsv
84abcc565d Add missing sideboards to M13 intro decks. 2013-07-01 10:07:56 +00:00
Agetian
b3b54ffe00 - Foil cards will now show up as foil in the card picture panel during the match (but not in the deck editor, at least for now). 2013-07-01 10:05:54 +00:00
Agetian
43dae4915f - A more appropriate name for the field representing foil chance in booster packs. 2013-07-01 07:36:33 +00:00
Agetian
990f93a34e - Changed the way foil rate in booster packs is represented in edition definition files (now it's an integer that represents a chance of a foil appearing in a booster pack out of 100%). 2013-07-01 07:24:11 +00:00
Agetian
17b1d4004a - Added preliminary support for metadata that defines if boosters for a particular edition may contain foils. 2013-07-01 03:54:31 +00:00
Chris
41f0012dc1 - Fixed the spell description for Shadow of Doubt, looks like a simple typo. 2013-07-01 02:32:41 +00:00
Sloth
9a3282285c - Fixed possible combat == null NPE in CloneAi. 2013-06-30 21:21:23 +00:00
Sloth
2ad63e7d7f - Fixed Djinn Illuminatus giving Replicate to all spells. 2013-06-30 21:18:17 +00:00
Agetian
abaf65e185 - Adding foil style info to edition definition files. 2013-06-30 17:45:27 +00:00
Agetian
a16b8e3ffc - Updated the loading progress bar to account for the extra foil sprite sheet, part 2. 2013-06-30 17:09:01 +00:00
Agetian
fdebee9011 - Foil cards will now be drawn with black border no matter what edition they are from (this currently has the side effect of drawing early core set foils with a black border around a thin white border already present in the picture - will probably be remedied later in one way or another).
- Updated the loading progress bar to account for the extra foil sprite sheet.
2013-06-30 16:50:43 +00:00
Agetian
00d76439b2 - Card foiling now defaults to modern foil style if the card edition file does not specify the foil type (this re-enables random foiling). 2013-06-30 16:12:23 +00:00
Agetian
b90694142c - Implemented foiling based on card edition-specific information about the availability and style of foil.
- Added the ability to differentiate between old-style and new-style (modern) foils. If a separate foil sheet called sprite_old_foils.png is available, that sheet will be used for pre-8th edition cards. If not available, the same sprite sheet (sprite_foils.png) will be used for all foils.
- Note that the edition files are not yet modified with the information about availability/style of foil cards. This has the nasty temporary side effect of disabling random foiling for all sets (to be remedied in the nearest future).
2013-06-30 16:05:01 +00:00
Sloth
3dac462afd - Expanded NonStackingAttachEffects (H-Q). 2013-06-30 15:45:30 +00:00
Maxmtg
a8ffebce60 remove some duplicated lines 2013-06-30 15:05:49 +00:00
Maxmtg
4a86221e8a Cards activable from other zones now are gathered inside player class, 2013-06-30 15:05:30 +00:00
Chris
7679b05c55 - Added new card names to changes.txt. 2013-06-30 12:55:15 +00:00
Sloth
1efd93e947 - Expanded NonStackingAttachEffects (A-H). 2013-06-30 12:28:55 +00:00
Sloth
9641af3973 - Updates to Attach and Pump AI. 2013-06-30 11:43:59 +00:00
Sloth
953c62f36c - Raised tokenBonus in getBestCreatureToBounceAI. 2013-06-30 10:03:31 +00:00
Sloth
7620b42bef - Fixed NPE in getAttackersOf. 2013-06-30 08:25:21 +00:00
Sloth
f35d57b534 - Fixed NPE in reveal function. 2013-06-30 08:20:10 +00:00
Sloth
10aadd4e66 - Fixed Haunt crash. 2013-06-30 07:59:17 +00:00
Agetian
0af795d2e0 - Added preliminary support for reading foil type information from game edition definition files (doesn't affect actual foiling yet). 2013-06-30 06:13:36 +00:00
Maxmtg
80b403c881 Phase inidicators arranged into a separate control
Moved special and more complex control like DeckChooser aside from the simpliest ones (like FButton or FLabel)
2013-06-30 06:05:48 +00:00
swordshine
5d3db0dbd3 - Added Skyfire Kirin and Puppet Master 2013-06-30 04:46:35 +00:00
Sloth
d015c35912 - Fixed canPlayFromEffectAI withOutManaCost. 2013-06-29 22:15:55 +00:00
Maxmtg
c811662d6f CMessage no longer stores game as model, instead updates follow visitor pattern (which ever game called update, get its information displayed)
Remove unused imports
2013-06-29 22:04:33 +00:00
Maxmtg
8e1b3185fe adjusted splid cards transformation place 2013-06-29 21:49:20 +00:00
Sloth
d892f396fb - Improved hasACardGivingHaste AI function. 2013-06-29 21:22:11 +00:00
Maxmtg
64dfce26b1 inverted the value of variabel for HumanPlaySpellAbility
moved split cards state restoration to the depths of changeZone, removed excessive action from HumanPlaySpellAbility
2013-06-29 21:16:26 +00:00
Maxmtg
d375d5588c TargetRestictions don't need to be copied, they may be just reused 2013-06-29 21:14:42 +00:00
Maxmtg
e1fb9121af hotseat: NPE fix at the beginning of 2nd match 2013-06-29 20:27:17 +00:00
moomarc
7101dc02c4 - Added Scars of the Veteran and Sacred Boon 2013-06-29 18:44:17 +00:00
Maxmtg
8d3067a625 made card recognition insensitive to case of set (will recognize both Cancel|RTR and Cancel|rtr cards in decks and import) 2013-06-29 15:11:20 +00:00
Sloth
5b85dacfa4 - Fixed ChangeZoneAll with origin library. 2013-06-29 13:16:31 +00:00
Sloth
4ea3851fb4 - Fixed Borborygmos challenge. 2013-06-29 11:57:58 +00:00
Chris
6071121323 - Cleared out the changes.txt file, now ready for new material.
- Added new card names to changes.txt.
2013-06-29 11:42:29 +00:00
Sloth
e1fe8c8e28 - AI will now sacrifice creatures for mana before losing control EOT. 2013-06-29 10:12:06 +00:00
swordshine
708b41b8da - Added Sideswipe 2013-06-29 09:25:39 +00:00
Sloth
ec730735bc - Improved ControlGainAi. 2013-06-29 08:24:52 +00:00
swordshine
0e2c6131f6 - Added Heart of Bogardan 2013-06-29 05:34:03 +00:00
Sloth
1172a542fd - Fixed possible NPE in assignAttackersDamage. 2013-06-28 19:47:30 +00:00
moomarc
4b71ea18b8 - Added support for damage prevention shields with effects.
- Added: Candles' Glow, Temper, Test of Faith and Vengeful Archon
2013-06-28 16:56:56 +00:00
Chris
4d8d51facc [maven-release-plugin] prepare for next development iteration 2013-06-28 12:09:55 +00:00
Chris
33cbbbd162 [maven-release-plugin] prepare release forge-1.4.2 2013-06-28 12:09:45 +00:00
Chris
71fb359aec - Preparing the changes.txt file for the next beta build and release. 2013-06-28 11:57:32 +00:00
Chris
879ce2a195 - Added new card names to changes.txt. 2013-06-28 11:43:30 +00:00
jsv
e3d57641ca Added missing sideboards to a couple of event decks for the spell shop. 2013-06-28 11:17:49 +00:00
Maxmtg
6bd754e6d6 fix NPE in AttachAi.attachAIPumpPreference(AttachAi.java:781) 2013-06-28 08:55:56 +00:00
jsv
c419b8d2a6 Fixed possible IndexOutOfBoundsException in chooseCardsToRevealFromHand. 2013-06-28 08:38:16 +00:00
swordshine
77191443ec - Added Quicksilver Sea 2013-06-28 00:25:11 +00:00
Sloth
0c1b3939ea - Added the medium quest opponent Blue Devil 2. 2013-06-27 13:22:08 +00:00
Sloth
088dc4eb99 - Fixed NPE in attachAIPumpPreference caused by Fortifications. 2013-06-27 11:58:05 +00:00
Chris
3019641d9f - Added new card names to changes.txt. 2013-06-27 10:44:10 +00:00
Maxmtg
82bb17ebf9 fixing NPE in CCombat.getCombatDescription. CCombat is given its own copy of combat that cannot be taken away by a different thread. 2013-06-27 08:39:13 +00:00
Sloth
67ee42dcda - Script cosmetics. 2013-06-26 21:47:44 +00:00
Maxmtg
0387d9a82e restore targeting arcs 2013-06-26 21:24:36 +00:00
Sloth
bb22cc6ba9 - Converted the second ability of Fastbond to script. 2013-06-26 21:19:20 +00:00
Sloth
9d78336096 - Time Spiral Timeshifted cards are now modern legal. 2013-06-26 16:14:41 +00:00
Sloth
07590fba08 - Fixed more possible NPE's caused by combat == null. 2013-06-26 14:19:33 +00:00
Sloth
f280ba4e05 - Fixed possible NPE in combatTriggerWillTrigger. 2013-06-26 13:44:11 +00:00
Chris
6e111aab3a - Added a fluff piece to the changes.txt file. 2013-06-26 13:03:08 +00:00
swordshine
5fad51e876 - Added Bloodlord of Vaasgoth (scripted by moomarc) 2013-06-26 12:36:13 +00:00
Chris
df11323434 - Added new card names to changes.txt. 2013-06-26 12:19:15 +00:00
Maxmtg
2c98474e16 Read foiled cards from deck (they mush have a + sign appended right to name, ex: Island+|ZEN) 2013-06-26 07:57:09 +00:00
swordshine
6e2803a614 - Added Herald of Leshrac 2013-06-26 06:24:23 +00:00
swordshine
6ea8469189 - Updated token images 2013-06-26 04:20:32 +00:00
swordshine
0a8064d7b5 - Added Urborg Panther 2013-06-26 01:08:00 +00:00
jendave
ad294fa15a add osx command file as workaround for .app issue 2013-06-25 22:35:32 +00:00
jendave
bebeb43a25 Update dmg builder 2013-06-25 21:27:23 +00:00
Maxmtg
72600d2e84 missing Oracle text for kithkin mourncaller 2013-06-25 20:59:31 +00:00
Maxmtg
193d740133 Removed abstract about not working Abu Ja'far and his friends
Removed abstract about potential Java 7 compatibility. Now it's a must.
2013-06-25 20:56:10 +00:00
Sloth
2e4278a89e - Added an AI SVar. 2013-06-25 20:50:01 +00:00
Maxmtg
2717c0d494 LKI for defenders (part 2 - final). Abu Ja'far now works as intended 2013-06-25 20:26:40 +00:00
Maxmtg
cf3dac5a7d kithkin mourncaller - seems to work now 2013-06-25 19:26:28 +00:00
Maxmtg
56ca218826 CombatLki - part 1. 2013-06-25 19:25:47 +00:00
Sloth
7cbef74401 - Changed the icon name of the The Nac Mac Feegle quest deck to the one downloaded. 2013-06-25 16:15:22 +00:00
Sloth
a228e18669 - Updated the quest deck Oreius 4. 2013-06-25 16:07:28 +00:00
jsv
3f24909423 Fix Master of the Wild Hunt waiting forever in cases when all his wolves have died before damage allocation is complete. 2013-06-25 12:30:42 +00:00
Chris
72c7cb38b6 - Added new card names to changes.txt. 2013-06-25 12:09:41 +00:00
jsv
54983e52c5 Fixed Lazav, Dimir Mastermind loosing his ability. 2013-06-25 11:34:59 +00:00
jsv
6ddf9c6817 Fixed a typo in Spire Tracer's type. 2013-06-25 10:57:22 +00:00
Sloth
3c20f384f5 - Added Joven's Ferrets. 2013-06-25 08:59:39 +00:00
Sloth
f9f4a27c6a - Fixed SacrificeEffect not remembering proper LKI copies. 2013-06-25 08:22:37 +00:00
Sloth
ef8af1a2b6 - Fixed IllegalArgumentException caused by multiple origins in ChangeZoneAll AI. 2013-06-25 08:03:09 +00:00
Sloth
3f4839cfe5 - Fixed Nettling Imp. 2013-06-25 07:41:55 +00:00
Maxmtg
7be40800c1 disabled that groovy compiler for it does not work today. Using regular javac now 2013-06-25 07:05:06 +00:00
Maxmtg
78938459b5 fixed 'blocked' variable of AttackingBand for propper Ninjutsu 2013-06-25 05:56:01 +00:00
Sloth
e2ef4b497c - Fixed description of "CantBeBlockedByAmount GT" keyword. 2013-06-24 20:59:09 +00:00
Sloth
d78b59b9cd - Added "CARDNAME must be blocked if able." to NonStackingKWList.txt 2013-06-24 18:28:01 +00:00
Maxmtg
1908ad7583 added inCombat check to controllerChangeZoneCorrection 2013-06-24 16:10:08 +00:00
Maxmtg
b20da90917 cp.getMatchingForgeCard() hand no owner and belonged to no game - that's why it didn't pass the test invoked by Card.isValid 2013-06-24 16:08:56 +00:00
Maxmtg
69d5be5bd9 getProtectionList static method moved to ProtectEffect.java
ProtectEffect uses game.notifyOfValue to avoid direct calls to Gui
2013-06-24 16:07:57 +00:00
Sloth
8e8ee4bb5c - Fixed prompt of "At the beginning of your upkeep, sacrifice" keywords. 2013-06-24 14:58:04 +00:00
Sloth
7bb5f45c82 - Little script updates. 2013-06-24 14:56:27 +00:00
Maxmtg
b074af6d41 correct the choice out of available flip results 2013-06-24 12:53:22 +00:00
Maxmtg
5038d5e838 Removed calls to GUI and to isHuman in ChooseNumber and FlipCoin effects 2013-06-24 12:48:52 +00:00
Chris
da234f5fcf - Added new card names to changes.txt. 2013-06-24 12:18:01 +00:00
Maxmtg
6ff8ba6682 moved Combat & CombatUtil to package forge.card.combat Sol has created.
removed EndOfCombat and Cleanup classes as they don't add anything specific to base class. Base class Phase is no longer abstract, also it does not need reference to game instance any longer
2013-06-24 10:54:46 +00:00
Maxmtg
dfc630aa23 orderMultipleBlockers and orderBlockingMultipleAttackers - moved into Combat class.
Combat - adjusted visibility of methods, moved some methods closer to caller
2013-06-24 10:40:56 +00:00
Maxmtg
74059bda82 Combat instance lifespan limited to Combat phase (for the rest combat = null, checks will return 'not attacking', 'not blocking'), the very object is stored in PhaseHandler
Card: removed methods to test if card is attacking/blocking, because these properties are related to combat, not the card itself.
AiAttackController - no longer creates Combat. Instead it uses a provided instance and fills attackers there
ComputerUtilBlock.java became non-static class AiBlockController, also modifies the provided Combat instance
2013-06-24 09:33:19 +00:00
swordshine
394a322fbe - Fixed SpellDescription of Time Spiral 2013-06-24 00:27:41 +00:00
Sloth
46786907b6 - Added "Mandatory$ True" to some more card scripts. 2013-06-23 19:09:02 +00:00
Sloth
b11179bc84 - Fixed See Beyond. 2013-06-23 18:32:18 +00:00
Sol
d8115e1cec - Added Nalathni Dragon 2013-06-23 17:49:40 +00:00
Sol
52a26ba4a5 - Added Urza's Engine, Icatian Skirmishers, Camel 2013-06-23 17:20:44 +00:00
Chris
72c7a54879 - Added new card names to changes.txt. 2013-06-23 16:13:57 +00:00
Sloth
9c66737813 - Added Dark Sphere by squee1968. 2013-06-23 13:32:57 +00:00
Sloth
4f159471d7 - Added some AI blocking against creatures with "can't be blocked except by X or more creatures". 2013-06-23 12:15:05 +00:00
Sloth
e63d418b03 - Fixed a NPE in canPlayLand AI. 2013-06-23 12:11:25 +00:00
Sloth
5f3f859b81 - Added Gaea's Touch. 2013-06-23 11:01:35 +00:00
Sloth
90cffa7b37 - M14 rules changes to Indestructible. 2013-06-23 09:55:52 +00:00
Sloth
770a7d20a8 - Fixed DebuffEffect. 2013-06-23 09:35:31 +00:00
Sloth
6b04ca78f9 - Converted Modular to macro script. 2013-06-23 09:18:55 +00:00
Sloth
e5ad11748f - Fixed modular keyword. 2013-06-23 09:02:52 +00:00
Maxmtg
fa38216eaa a minor brush up (use EnumSet instead of switch-case) 2013-06-23 08:04:41 +00:00
Sol
c94e8a395f - Added Bands with others support
- Add 5 Legends Bands with Other lands, Master of the Hunt, Shelkin Brownie, Tolaria
- Small fixes to Combat and CCombat
2013-06-23 01:09:43 +00:00
Chris
dddd7972fb - Added new card names to changes.txt. 2013-06-22 12:11:19 +00:00
Chris
3e4323d10c Updated the org.eclipse.jdt.core.prefs and .classpath files to make them Java 7 compatible. 2013-06-22 12:09:49 +00:00
Sloth
197ca7cf4a - Added the medium quest opponent Hookah-Smoking Caterpillar 2 by Nordos. 2013-06-22 11:52:46 +00:00
swordshine
41827bb653 - some other api with tgtPlayers 2013-06-22 11:09:28 +00:00
swordshine
e7656f3be5 - Additional fix about tgtPlayers 2013-06-22 10:55:21 +00:00
Sloth
17f10cafbc - Fixed not being able to block creatures attacking your Planeswalker. 2013-06-22 10:32:23 +00:00
swordshine
62239488c9 - revert changes in changezoneall effect, complicated situations here 2013-06-22 10:32:12 +00:00
swordshine
615abebe99 - Fixed ChangeZoneAll, TapAll, UntapAll effect 2013-06-22 10:29:43 +00:00
Sloth
b703546c80 - Fixed Anavolver and friends. 2013-06-22 10:19:24 +00:00
swordshine
c862679aac - Fixed PumpAll effect 2013-06-22 10:16:01 +00:00
Sloth
2b2bfa6389 - Fixed Hypergenesis. 2013-06-22 10:08:23 +00:00
Sloth
8e50d42099 - Fixed spells without costs being playable. 2013-06-22 10:08:03 +00:00
Maxmtg
2fd6fde9b5 remove setinfos, part a 2013-06-22 08:49:38 +00:00
Maxmtg
47606cf46c remove setinfos, part z 2013-06-22 08:45:19 +00:00
Maxmtg
2ab15ba0d1 remove setinfos, part y 2013-06-22 08:44:53 +00:00
Maxmtg
0bd68b9b3e remove setinfos, part x 2013-06-22 08:44:39 +00:00
Maxmtg
6cfb6f60f5 remove setinfos, part w 2013-06-22 08:44:32 +00:00
Maxmtg
be1886179f remove setinfos, part v 2013-06-22 08:41:49 +00:00
Maxmtg
65f2368050 remove setinfos, part u 2013-06-22 08:39:48 +00:00
Maxmtg
90a8a2e9da remove setinfos, part t 2013-06-22 08:38:56 +00:00
Maxmtg
9afd057ee2 remove setinfos, part s 2013-06-22 08:34:22 +00:00
Maxmtg
0440c2a89c remove setinfos, part r 2013-06-22 08:23:21 +00:00
Maxmtg
7245506564 remove setinfos, part q 2013-06-22 08:19:29 +00:00
Maxmtg
8c7f10b976 remove setinfos, part p 2013-06-22 08:19:10 +00:00
Maxmtg
cb2fb9e1c1 remove setinfos, part o 2013-06-22 08:15:40 +00:00
Maxmtg
1316cc6c32 remove setinfos, part n 2013-06-22 08:14:18 +00:00
Maxmtg
ddd503fc31 remove setinfos, part m 2013-06-22 08:12:39 +00:00
Maxmtg
ded1fe3db5 remove setinfos, part l 2013-06-22 08:08:05 +00:00
Maxmtg
f6dc60a9f0 remove setinfos, part k 2013-06-22 08:05:55 +00:00
Maxmtg
62e018aced remove setinfos, part j 2013-06-22 08:04:01 +00:00
Maxmtg
799b31f2aa remove setinfos, part i 2013-06-22 08:03:15 +00:00
Maxmtg
89725523d0 remove setinfos, part h 2013-06-22 08:01:36 +00:00
Maxmtg
c14fff73b2 remove setinfos, part g 2013-06-22 07:59:09 +00:00
Maxmtg
81b4156744 remove setinfos, part f 2013-06-22 07:55:07 +00:00
Maxmtg
35a02524c9 remove setinfos, part e 2013-06-22 07:51:57 +00:00
Maxmtg
a0b2bbcb1c remove setinfos, part d 2013-06-22 07:49:40 +00:00
Maxmtg
baf16a2719 remove setinfos, part c 2013-06-22 07:45:27 +00:00
Maxmtg
de15debd11 remove setinfos, part b 2013-06-22 07:40:31 +00:00
swordshine
5253f90284 - Fixed Reveal effect 2013-06-22 05:53:51 +00:00
swordshine
46f4aa8e35 - Reverted last fix, the reveal issue was related to Chancellors 2013-06-22 05:48:18 +00:00
swordshine
8d58e317aa - Fixed Infernal Tutor 2013-06-22 05:37:48 +00:00
swordshine
046836a63a - Fixed Gerrard Capashen 2013-06-22 05:13:16 +00:00
swordshine
92930d7a6f - Added Guile 2013-06-22 03:02:49 +00:00
swordshine
b49d1f3f39 - Added Phyrexian Colossus 2013-06-22 01:12:07 +00:00
swordshine
cba2fb93c9 - Added Goblin Flectomancer and Wild Ricochet 2013-06-22 00:47:59 +00:00
Maxmtg
4c40598c79 refactored 10+ calls to isComputer/isHuman 2013-06-21 22:46:00 +00:00
Maxmtg
69c36da984 added 2 simple creatures with CantBeBlockedByAmount LT3 2013-06-21 21:43:06 +00:00
Maxmtg
a75835f664 CantBeBlockedByAmount + expression used to specify number or creatures that can block given attacker 2013-06-21 21:42:26 +00:00
Sloth
06eb8e3e43 - Added a new AI SVar "NonStackingAttachEffect". 2013-06-21 21:39:55 +00:00
Maxmtg
68d3a7cdb2 more blocking-related keywords replaced with CanBeBlockedBy+expression 2013-06-21 19:13:23 +00:00
Maxmtg
fa443cea0d Text for CantBeBlockedBy is composed in runtime 2013-06-21 18:14:52 +00:00
Sloth
da1645c353 - Fixed Skymark Roc. 2013-06-21 14:51:01 +00:00
Maxmtg
1d498a5ba3 "can be blocked only by creatures with defender" now also uses a common keyword 2013-06-21 14:47:44 +00:00
Maxmtg
f3876079a9 CantBeBlockedBy - attempts to build keyword description 2013-06-21 14:08:30 +00:00
Maxmtg
dc390b796d removed keywords "CARDNAME can't be blocked by {color} creatures." 2013-06-21 14:07:17 +00:00
Maxmtg
09edb071ff removed keyword CARDNAME can't be blocked by red creatures 2013-06-21 13:38:48 +00:00
swordshine
13d28d6ecb - Fixed Timetwister and similar cards. 2013-06-21 12:58:53 +00:00
Maxmtg
b92eaa14a5 Redirect added. M13 is complete. 2 unimplemented cards in T2 remaining. 2013-06-21 12:41:21 +00:00
Chris
10c41c9dfa Updated sound file list. 2013-06-21 12:26:04 +00:00
Chris
6c6e26bcaa Added the converted version of the end_of_turn.wav sound file, thank you jsv 2013-06-21 12:21:20 +00:00
Chris
a75ad8080d - Added new card names to changes.txt. 2013-06-21 12:05:59 +00:00
Maxmtg
1834182d2e add comment, remove unused variable, make simple overload to chooseSingleSpellAbility in AI part of the effect 2013-06-21 11:49:59 +00:00
Maxmtg
a395adc2b6 CopySpellAbilityEffect refactored: fixed Precursor Golem (and hopefully all similiar spells), removed calls to isHuman/isComputer
PlayerController: added chooseSingleSpellForEffect
2013-06-21 11:28:16 +00:00
Sloth
5fe795059b - Fixed targeted triggers not being removed from the stack (again). 2013-06-21 10:52:04 +00:00
Maxmtg
292df0c8de TargetChoice clone = added lost field 2013-06-21 06:49:10 +00:00
Maxmtg
c3e752f98f rearrange and update comments 2013-06-21 06:47:33 +00:00
Maxmtg
56737375da Spellskite script uses a general clause 'ChangeSingleTarget', uses 'Defined' to specify new target
SpellAbility.canTarget now also works for SpellAbilities
2013-06-21 06:31:44 +00:00
swordshine
5fe182f3c4 - Another fix 2013-06-21 06:19:39 +00:00
Maxmtg
3242d396a9 Haunt now resolves, but its trigger won't leave stack 2013-06-21 06:06:55 +00:00
swordshine
390a23d88e - A quick fix the script of Spellskite 2013-06-21 06:06:51 +00:00
Maxmtg
00ddfed039 spellskite added - please test 2013-06-21 04:16:59 +00:00
Maxmtg
775588b300 applied auto fix layout to deck editor 2013-06-21 01:06:25 +00:00
Maxmtg
8a50df0e06 Gideon from GTC - 1st ability will work 2013-06-20 17:46:47 +00:00
Sloth
9c5a38ac70 - Added the hard quest opponent Doctor John Zoidberg 3. 2013-06-20 15:05:12 +00:00
Sloth
ce7a8bb1f1 - Fixed targeted triggers not being removed from the stack. 2013-06-20 14:29:47 +00:00
Chris
77dcb26372 - Added a fluff piece to the changes.txt file. 2013-06-20 11:45:18 +00:00
Chris
0aecaec778 - Added new card names to changes.txt. 2013-06-20 11:41:59 +00:00
Maxmtg
90b48b5447 addition 2013-06-20 06:06:13 +00:00
Maxmtg
89be097c3f fixed missing assignment in PumpEffect 2013-06-20 06:03:34 +00:00
Maxmtg
4fdb9ef7f9 fix endless loop for counterspell 2013-06-20 05:52:26 +00:00
swordshine
68dba80b9c - Added AITgts to Arachnus Web 2013-06-20 02:45:12 +00:00
Sloth
13615dc15a - Fixed possible NPE in getBlockers. 2013-06-19 20:59:42 +00:00
Sloth
8820a45312 - Improved AI's first land drop decision. 2013-06-19 20:39:23 +00:00
Sloth
b5186a367a - Fixed NPE caused by spells without target. 2013-06-19 20:37:37 +00:00
Sloth
24ee2cba60 - Fixed possible NPE's in doPayment functions. 2013-06-19 16:58:38 +00:00
Maxmtg
ade7bed52f SpellAbility holds separate TargetRestricions and TargetChoices in separate members.
Some APIs might become broken, please report
2013-06-19 14:51:21 +00:00
Sloth
3c3ab8138b - Fixed AttackerUnblocked triggers. 2013-06-19 12:42:08 +00:00
Sloth
85c1fc457c - Cleanup of Card class. 2013-06-19 12:34:05 +00:00
Sloth
9525581631 - Improved Stack description of DestroyAll effects. 2013-06-19 12:11:12 +00:00
Sol
9856588fa8 - AiAttackController will use it's own Random object instead of the primary game one 2013-06-19 01:47:02 +00:00
Sloth
eb85f56534 - Fixed AI not attacking planeswalkers. 2013-06-18 20:44:23 +00:00
Sloth
8cce641e43 - Moved isNegativeCounter to ComputerUtil and improved it. 2013-06-18 18:39:03 +00:00
jendave
be237b402c Update windows jar wrapper 2013-06-18 18:35:42 +00:00
jendave
26b9fa20be Update deps 2013-06-18 17:58:49 +00:00
Sloth
9c7efa9037 - Optional triggers will now grant additional info when the human is prompted. 2013-06-18 15:08:20 +00:00
Sloth
2fa0e11ebb - Improved Sigil Blessing stack description. 2013-06-18 14:39:13 +00:00
Sloth
db40ad80ae - Fixed Grave Bramble. 2013-06-18 14:23:17 +00:00
asepetci
11262acafc updated rankings.txt 2013-06-18 13:27:35 +00:00
Maxmtg
b41147b7f6 fixes compile error 2013-06-18 12:56:57 +00:00
Maxmtg
de9c9ff3f3 jsv's fix for problem "I have several gauntlets in progress. No matter which one I select, when I press "Start" it's always the first one in the list that gets loaded." 2013-06-18 11:36:28 +00:00
Maxmtg
7a0d57997d commented out javafx dependency to make sure the rest works 2013-06-18 11:18:44 +00:00
Maxmtg
74aa0a4917 cleanup in Target constructors 2013-06-18 10:04:18 +00:00
Maxmtg
c39bf4ee34 'Target' class no longer uses card in ctor and fields 2013-06-18 09:09:49 +00:00
Maxmtg
25edd60ac5 Using ITargetable instead of Object to return targets of an ability 2013-06-18 08:21:26 +00:00
Sloth
28a94982fe - Copies of spells will now copy the payment that has been made for the original (rule 706.10). 2013-06-18 08:05:50 +00:00
Maxmtg
7c1adf1c2a Added generic types to Swing components that needed them (with transition to Java 7) 2013-06-18 07:59:39 +00:00
Sloth
f6dc001e3a - Fixed type of Infernal Plunge. 2013-06-18 07:41:49 +00:00
Sloth
bff37b60d5 - Fixed canPlayLand not working with "May be played by your opponent". 2013-06-18 06:21:36 +00:00
Maxmtg
f8b5e238f4 use java compiler from JDK 7, use jre 7 in launch4j and pmd 2013-06-18 05:22:00 +00:00
swordshine
56de452158 - Fixed Pulmonic Sliver 2013-06-18 04:29:54 +00:00
swordshine
0d18289699 - Fixed Clash of Realities 2013-06-18 01:04:54 +00:00
Sol
7819893f81 - Improve Combat Panel for banding and blockers that have been removed 2013-06-18 00:10:57 +00:00
Sol
7073eb5494 - Convert Balance to script, Simplify Balancing Act
- Add Restore Balance
- Adding a Balance Effect API
2013-06-18 00:06:51 +00:00
Sloth
9996b26eba - Added Wall of Shards. 2013-06-17 21:51:42 +00:00
Sloth
d2e205a3fc - payManaOptional will now pass on the spellability to payCostDuringAbilityResolve.
- Added support for CostGainLife in payCostDuringAbilityResolve.
2013-06-17 21:48:45 +00:00
Sloth
ae1e2dbbcb - Added Djinn Illuminatus. 2013-06-17 21:05:35 +00:00
Sloth
4105614645 - Added support for Djinn Illuminatus. 2013-06-17 21:02:09 +00:00
Sloth
3753d989b7 - Removed some unnecessary Replicate stuff. 2013-06-17 20:28:36 +00:00
Sloth
fb2d08032d - The AI can now use Delve. 2013-06-17 19:56:26 +00:00
Sloth
1dcd260feb - Fixed Delve description on Death Rattle. 2013-06-17 19:00:33 +00:00
Sloth
fc3ae7bfe9 - Fixed cards dodging destruction during controller changes. 2013-06-17 15:36:47 +00:00
Sloth
dd9715761c - Fixed set of the infestation precon. 2013-06-17 14:03:23 +00:00
Chris
2b35f0d714 - Added new card names to changes.txt. 2013-06-17 10:34:15 +00:00
Maxmtg
18a84c0c6e fixed event dispatch moment - fire only if it won't be replaced. 2013-06-17 07:38:08 +00:00
Maxmtg
39a88cd4d1 fix NPE in public SoundEffectType visit(GameEventCardChangeZone event) 2013-06-17 07:33:50 +00:00
Maxmtg
502a087962 fixed sign for rounded corners 2013-06-17 07:31:48 +00:00
Maxmtg
9de9d4ca53 some cleanup in CardPanel 2013-06-17 06:53:18 +00:00
swordshine
d5a2ef88df - "AddReplacementEffects" in static ability (experimental)
- Added Pulmonic Sliver
2013-06-17 05:33:46 +00:00
swordshine
abcb758a56 - Updated token images
- Added Darksteel Garrison
2013-06-17 00:21:53 +00:00
Maxmtg
2c88d952d2 finer look of cards (no more moire on corners)
white-bordered cards have 1px black outline
2013-06-16 23:53:07 +00:00
Maxmtg
373ce84268 removed specific events that can be generalized by change zone 2013-06-16 23:20:04 +00:00
Maxmtg
9aff5237ea a good general game event for card change zone 2013-06-16 23:12:49 +00:00
Maxmtg
58a333ef99 removed unused classes,
removed literals for basic lands
2013-06-16 22:26:38 +00:00
Maxmtg
5506af61ab Uses more reliable way to detect sets with all basic lands present 2013-06-16 21:41:40 +00:00
Sloth
56df11005b - Prevent NPE in getDefenderByAttacker. 2013-06-16 21:00:56 +00:00
Agetian
f6f80da995 - Sound System: added a new sound event (exile a card), uses the sound file res/sound/exile.wav. 2013-06-16 19:44:51 +00:00
Sloth
8d5f633884 - NPE check with debug output added to TriggerSpellAbilityCast. 2013-06-16 18:09:05 +00:00
Sloth
15b3599a05 - Fixed Replicate. 2013-06-16 18:00:14 +00:00
Sloth
f089ef0c60 - Fixed "X Can't be 0." costs always showing cancel. 2013-06-16 16:49:30 +00:00
Sloth
c513f93329 - Fixed "CARDNAME untaps during each other player's untap step." working on your own untap step. 2013-06-16 14:15:35 +00:00
Sloth
00f55f4044 - Fixed AI ignoring mana restrictions (Myr Superion etc.). 2013-06-16 14:01:47 +00:00
Chris
7741d9f65d - Added new card names to changes.txt. 2013-06-16 12:23:31 +00:00
Sloth
b6418401b3 - Fixed possible NPE in assignAttackersDamage. 2013-06-16 11:24:33 +00:00
swordshine
b7d6f32b89 - Added Urza's Avenger 2013-06-16 08:51:40 +00:00
swordshine
789af07ebe - Added 30 banding cards 2013-06-16 04:23:55 +00:00
Sloth
33981efab1 - Improved AI gaining Threshold. 2013-06-15 21:08:42 +00:00
Sloth
0d05da4e0a - The AI will no longer deck itself with Dig spells. 2013-06-15 14:24:13 +00:00
Chris
97c75209f3 - Added new card names to changes.txt. 2013-06-15 12:38:29 +00:00
Chris
bd7d643f07 - Cleared out the changes.txt file, now ready for new material. 2013-06-15 12:26:32 +00:00
Sloth
ee8049c3bf - Updated some SVars. 2013-06-15 07:43:56 +00:00
Sloth
6821546d51 - Fixed filter in tapPrefTargeting. 2013-06-15 06:51:49 +00:00
swordshine
c188296a82 - Cleanup 2013-06-15 00:44:12 +00:00
swordshine
19d93f9e34 - Added Mindlock Orb and Shadow of Doubt 2013-06-15 00:31:43 +00:00
Sloth
a8b9c92207 - Fixed UnmodifiableCollection.remove call caused by Balance. 2013-06-14 21:55:06 +00:00
Sloth
eaa5a35f47 - Removed unnecessary RuntimeException in getUnlockableEditions. 2013-06-14 21:38:49 +00:00
Sloth
c12c5939c0 - Fixed Ground Seal not working for the AI's ChangeZone abilities. 2013-06-14 21:35:11 +00:00
Sloth
4174317f57 - Added the quest opponent Mystique 2 by Nordos. 2013-06-14 21:21:48 +00:00
Sol
5f508e5d17 - Human may now declare attacks in a band
- Added Benalish Hero
2013-06-14 15:19:21 +00:00
Sol
8eedf4b3f1 - Two small fixes for Damage Assignment related to Banding creatures 2013-06-14 14:21:52 +00:00
Sol
786650f660 - Initial checkin for Combat refactor.
- Introduction of AttackingBands which group Attackers, Blockers and Blocked state.
2013-06-14 12:56:05 +00:00
Sloth
dea4a38a6c - Fixed possible min > max error. 2013-06-14 11:42:30 +00:00
Sloth
7298cbbe0d - Fixed chooseSingleCardForEffect for human player. 2013-06-14 11:26:15 +00:00
Sloth
a0f4ac195d - Fixed optional triggers declined by the AI not being removed from the stack. 2013-06-14 11:18:11 +00:00
Chris
7ee57a381a [maven-release-plugin] prepare for next development iteration 2013-06-14 11:07:00 +00:00
17811 changed files with 140044 additions and 128176 deletions

View File

@@ -1,9 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<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"/>

30618
.gitattributes vendored

File diff suppressed because it is too large Load Diff

26
.gitignore vendored
View File

@@ -2,20 +2,28 @@
/*.iml
/*.tmp
/.metadata
forge-ai/forge-ai.iml
forge-ai/target
forge-core/forge-core.iml
forge-core/target
forge-game/target
forge-gui/forge-gui.iml
forge-gui/forge.profile.properties
forge-gui/res/*.log
forge-gui/res/PerSetTrackingResults
forge-gui/res/cardsfolder/*.bat
forge-gui/res/decks
forge-gui/res/layouts
forge-gui/res/pics*
forge-gui/res/pics_product
forge-gui/target
forge-gui/tools/PerSetTrackingResults
forge-gui/tools/oracleScript.log
/forge.profile.properties
/nbactions.xml
/pom.xml.next
/pom.xml.releaseBackup
/pom.xml.tag
/release.properties
res/*.log
res/PerSetTrackingResults
res/cardsfolder/*.bat
res/decks
res/layouts
res/pics*
res/pics_product
/target
/test-output
tools/PerSetTrackingResults
tools/oracleScript.log

View File

@@ -4,36 +4,7 @@
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
</natures>
</projectDescription>

View File

@@ -1,16 +1,15 @@
#Wed Jul 27 18:40:11 EDT 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.compiler.source=1.7
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0

View File

@@ -1,219 +0,0 @@
Forge Beta: 06-14-2013 ver 1.4.1
12819 cards in total.
-------------
Release Notes
-------------
- Java 7 -
The devs are discussing a plan to update the battlefield display code with Java FX 2.2 and this should help to improve a few things. Java FX 2.2 requires Java 7 so please update your Java runtime environment in the nearest future. At some point a new version of Forge will no longer run under Java 6.
- New M14 cards -
We have added a branch to our SVN for the new cards that are currently being scripted. These cards are not yet available in this build of forge. Please be patient and they will soon become available.
- Match and Deck Editor Layout problems -
The match and deck editor windows contain panels that can be moved and/or resized. The changes that you make are saved to files that are named "editor.xml" and "match.xml". These files can be found in your userDir/preferences/ directory.
Sometimes people will decide that they do not like the changes that they made and wish to go back to the original layout. To reset layouts to deafult, go to the Game Settings -> Preferences -> Troubleshooting section. You will find at this location two buttons that will reset the match layout and the deck editor layouts.
Also use the mentioned measure if your match or deckeditor won't start - it would help in 90% of the cases.
- The AI Drafting has been improved -
The AI evaluated the basic lands higher than anything else. Fixed. The AI would pick cards with RemAIDeck but only at a much lowered pick rate. For example the best pick in a 250 card set would become the 75th best pick, the 20th best pick would become the 95th and so on. Divided this factor by 3 (so the first pick would become the 25th pick). Please test whether this has improved the draft experience.
---------
New Cards
---------
Amulet of Quoz
Aphetto Dredging
Archive Trap
Battlefield Scrounger
Chain Stasis
Chancellor of the Annex
Chisei, Heart of Oceans
Choking Vines
Cobra Trap
Defensive Formation
Dream Chisel
Dream Leash
Exiled Doomsayer
Fossil Find
Gemstone Caverns
Grave Consequences
Grimoire Thief
Hankyu
Hibernation's End
Indentured Djinn
Ion Storm
Jester's Scepter
Jetting Glasskite
Jotun Grunt
Kira, Great Glass Spinner
Kithkin Armor
Krark's Thumb
Leashling
Liquid Fire
Martyr of Bones
Master Warcraft
Melee
Minion of Leshrac
Odric, Master Tactician
Patron of the Akki
Patron of the Kitsune
Patron of the Moon
Patron of the Nezumi
Patron of the Orochi
Penance
Power Conduit
Prowling Pangolin
Psychic Vortex
Research // Development
Search for Survivors
Shimmering Glasskite
Spinning Darkness
Summoning Trap
Tainted Specter
Teferi's Curse
Temporary Truce
Thelon's Chant
Thought Lash
Thran Turbine
Tidal Influence
Time and Tide
Tourach's Chant
Truce
Uba Mask
Void Maw
----------
New Planes
----------
Furnace Layer
Kharasha Foothills
Mimano
Mirrored Depths
--------------------
New M14 branch Cards
--------------------
Accursed Spirit
Advocate of the Beast
Ajani's Chosen
Archangel of Thune
Awaken the Ancient
Battle Sliver
Blur Sliver
Bonescythe Sliver
Charging Grffin
Corpse Hauler
Dawnstrike Paladin
Deathgaze Cockatrice
Devout Invocation
Elvish Mystic
Enlarge
Fleshpulper Giant
Glimpse the Future
Grim Return
Groundshaker Sliver
Guardian of the Ages
Hive Stirrings
Hunt the Weak
Into the Wilds
Jace's Mindseeker
Kalonian Tusker
Liliana's Reaver
Marauding Maulhorn
Master of Diversion
Megantic Sliver
Molten Birth
Ogre Battledriver
Predatory Sliver
Primeval Bounty
Regathan Firecat
Ring of Three Wishes
Rise of the Dark Realms
Scourge of Valkas
Sentinel Sliver
Seraph of the Sword
Shadowborn Apostle
Shadowborn Demon
Sliver Construct
Soulmender
Sporemound
Staff of the Death Magus
Staff of the Flame Magus
Staff of the Mind Magus
Staff of the Wild Magus
Steelform Sliver
Stonehorn Chanter
Striking Sliver
Thorncaster Sliver
Undead Minotaur
Vampire Warlord
Vastwood Hydra
Vial of Poison
Windreader Sphinx
Woodborn Behemoth
Young Pyromancer
------------
Known Issues
------------
A small number of cards including Wall of Corpses, Abu Ja'far and others with a similar ability are not functional. The common issue here is actually that they check the blocker/attacker after being removed from the battlefield. Probably need to use LKI. Regular destroy/destroy all effects work just fine. The problem cards are caring about battlefield specific properties, that no longer apply when the base card is no longer on the battlefield.
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.
Forge is likely to be compatible with Java 7 at this time. Some people have used forge with Java 7 and have not reported any problems that are related to Java 7. If you would like to upgrade to Java 7 and have held off because of Forge then you may upgrade as we do not think that it will cause an incompatibility type of problem. We will continue to try to maintain compatibility with Java 6 for the foreseeable future.
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
----------------------------
Agetian
Asepetci
Diogenes
Gos
Hellfish
Marc
Max
Nordos
RedDeckWins
Sidereal
Sloth
Sol
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
View 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
View 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>

View 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

View 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

View File

@@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

28
forge-ai/pom.xml Normal file
View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>forge</artifactId>
<groupId>forge</groupId>
<version>1.5.6</version>
</parent>
<artifactId>forge-ai</artifactId>
<name>Forge AI</name>
<dependencies>
<dependency>
<groupId>forge</groupId>
<artifactId>forge-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>forge</groupId>
<artifactId>forge-game</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -24,7 +24,11 @@ package forge.game.ai;
* from the text file.
*/
public enum AiProps { /** */
AI_MULLIGAN_THRESHOLD ("5"); /** */
DEFAULT_MAX_PLANAR_DIE_ROLLS_PER_TURN ("1"), /** */
DEFAULT_MIN_TURN_TO_ROLL_PLANAR_DIE ("3"), /** */
DEFAULT_PLANAR_DIE_ROLL_CHANCE ("50"), /** */
MULLIGAN_THRESHOLD ("5"), /** */
PLANAR_DIE_ROLL_HESITATION_CHANCE ("10"); /** */
private final String strDefaultVal;

9
forge-core/.classpath Normal file
View 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
View 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>

View 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

View 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

View File

@@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

27
forge-core/pom.xml Normal file
View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>forge</artifactId>
<groupId>forge</groupId>
<version>1.5.6</version>
</parent>
<artifactId>forge-core</artifactId>
<name>Forge Core</name>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>14.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,375 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.commons.lang3.time.StopWatch;
import forge.card.CardRules;
import forge.util.FileUtil;
import forge.util.ThreadUtil;
/**
* <p>
* CardReader class.
* </p>
*
* @author Forge
* @version $Id: CardStorageReader.java 23742 2013-11-22 16:32:56Z Max mtg $
*/
public class CardStorageReader {
public interface Observer {
public void cardLoaded(CardRules rules, List<String> lines, File fileOnDisk);
}
public interface ProgressObserver{
void setOperationName(String name, boolean usePercents);
void report(int current, int total);
// does nothing, used when they pass null instead of an instance
public final static ProgressObserver emptyObserver = new ProgressObserver() {
@Override public void setOperationName(String name, boolean usePercents) {}
@Override public void report(int current, int total) {}
};
}
private static final String CARD_FILE_DOT_EXTENSION = ".txt";
/** Default charset when loading from files. */
public static final String DEFAULT_CHARSET_NAME = "US-ASCII";
private final boolean useThreadPool = ThreadUtil.isMultiCoreSystem();
private final static int NUMBER_OF_PARTS = 25;
private final ProgressObserver progressObserver;
private transient File cardsfolder;
private transient ZipFile zip;
private final transient Charset charset;
private final Observer observer;
// 8/18/11 10:56 PM
/**
* <p>
* Constructor for CardReader.
* </p>
*
* @param theCardsFolder
* indicates location of the cardsFolder
* @param useZip
* if true, attempts to load cards from a zip file, if one
* exists.
*/
public CardStorageReader(String cardDataDir, CardStorageReader.ProgressObserver progressObserver, Observer observer) {
this.progressObserver = progressObserver != null ? progressObserver : CardStorageReader.ProgressObserver.emptyObserver;
this.cardsfolder = new File(cardDataDir);
this.observer = observer;
// These read data for lightweight classes.
if (!cardsfolder.exists()) {
throw new RuntimeException("CardReader : constructor error -- " + cardsfolder.getAbsolutePath() + " file/folder not found.");
}
if (!cardsfolder.isDirectory()) {
throw new RuntimeException("CardReader : constructor error -- not a directory -- " + cardsfolder.getAbsolutePath());
}
final File zipFile = new File(cardsfolder, "cardsfolder.zip");
if (zipFile.exists()) {
try {
this.zip = new ZipFile(zipFile);
} catch (final Exception exn) {
System.err.printf("Error reading zip file \"%s\": %s. Defaulting to txt files in \"%s\".%n", zipFile.getAbsolutePath(), exn, cardsfolder.getAbsolutePath());
}
}
this.charset = Charset.forName(CardStorageReader.DEFAULT_CHARSET_NAME);
} // CardReader()
private final List<CardRules> loadCardsInRange(final List<File> files, int from, int to) {
CardRules.Reader rulesReader = new CardRules.Reader();
List<CardRules> result = new ArrayList<CardRules>();
for(int i = from; i < to; i++) {
File cardTxtFile = files.get(i);
result.add(this.loadCard(rulesReader, cardTxtFile));
}
return result;
}
private final List<CardRules> loadCardsInRangeFromZip(final List<ZipEntry> files, int from, int to) {
CardRules.Reader rulesReader = new CardRules.Reader();
List<CardRules> result = new ArrayList<CardRules>();
for(int i = from; i < to; i++) {
ZipEntry ze = files.get(i);
// if (ze.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION)) // already filtered!
result.add(this.loadCard(rulesReader, ze));
}
return result;
}
/**
* Starts reading cards into memory until the given card is found.
*
* After that, we save our place in the list of cards (on disk) in case we
* need to load more.
*
* @return the Card or null if it was not found.
*/
public final Iterable<CardRules> loadCards() {
progressObserver.setOperationName("Loading cards, examining folder", true);
// Iterate through txt files or zip archive.
// Report relevant numbers to progress monitor model.
Set<CardRules> result = new TreeSet<CardRules>(new Comparator<CardRules>() {
@Override
public int compare(CardRules o1, CardRules o2) {
return String.CASE_INSENSITIVE_ORDER.compare(o1.getName(), o2.getName());
}
});
final List<File> allFiles = collectCardFiles(new ArrayList<File>(), this.cardsfolder);
if(!allFiles.isEmpty()) {
int fileParts = zip == null ? NUMBER_OF_PARTS : 1 + NUMBER_OF_PARTS / 3;
if( allFiles.size() < fileParts * 100)
fileParts = allFiles.size() / 100; // to avoid creation of many threads for a dozen of files
final CountDownLatch cdlFiles = new CountDownLatch(fileParts);
List<Callable<List<CardRules>>> taskFiles = makeTaskListForFiles(allFiles, cdlFiles);
progressObserver.setOperationName("Loading cards from folders", true);
progressObserver.report(0, taskFiles.size());
StopWatch sw = new StopWatch();
sw.start();
executeLoadTask(result, taskFiles, cdlFiles);
sw.stop();
final long timeOnParse = sw.getTime();
System.out.printf("Read cards: %s files in %d ms (%d parts) %s%n", allFiles.size(), timeOnParse, taskFiles.size(), useThreadPool ? "using thread pool" : "in same thread");
}
if( this.zip != null ) {
final CountDownLatch cdlZip = new CountDownLatch(NUMBER_OF_PARTS);
List<Callable<List<CardRules>>> taskZip = new ArrayList<>();
ZipEntry entry;
List<ZipEntry> entries = new ArrayList<ZipEntry>();
// zipEnum was initialized in the constructor.
Enumeration<? extends ZipEntry> zipEnum = this.zip.entries();
while (zipEnum.hasMoreElements()) {
entry = zipEnum.nextElement();
if (entry.isDirectory() || !entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION))
continue;
entries.add(entry);
}
taskZip = makeTaskListForZip(entries, cdlZip);
progressObserver.setOperationName("Loading cards from archive", true);
progressObserver.report(0, taskZip.size());
StopWatch sw = new StopWatch();
sw.start();
executeLoadTask(result, taskZip, cdlZip);
sw.stop();
final long timeOnParse = sw.getTime();
System.out.printf("Read cards: %s archived files in %d ms (%d parts) %s%n", this.zip.size(), timeOnParse, taskZip.size(), useThreadPool ? "using thread pool" : "in same thread");
}
return result;
} // loadCardsUntilYouFind(String)
private void executeLoadTask(Collection<CardRules> result, final List<Callable<List<CardRules>>> tasks, CountDownLatch cdl) {
try {
if ( useThreadPool ) {
final ExecutorService executor = ThreadUtil.getComputingPool(0.5f);
final List<Future<List<CardRules>>> parts = executor.invokeAll(tasks);
executor.shutdown();
cdl.await();
for(Future<List<CardRules>> pp : parts) {
result.addAll(pp.get());
}
} else {
for(Callable<List<CardRules>> c : tasks) {
result.addAll(c.call());
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (Exception e) { // this clause comes from non-threaded branch
throw new RuntimeException(e);
}
}
private List<Callable<List<CardRules>>> makeTaskListForZip(final List<ZipEntry> entries, final CountDownLatch cdl) {
int totalFiles = entries.size();
final int maxParts = (int) cdl.getCount();
int filesPerPart = totalFiles / maxParts;
final List<Callable<List<CardRules>>> tasks = new ArrayList<Callable<List<CardRules>>>();
for (int iPart = 0; iPart < maxParts; iPart++) {
final int from = iPart * filesPerPart;
final int till = iPart == maxParts - 1 ? totalFiles : from + filesPerPart;
tasks.add(new Callable<List<CardRules>>() {
@Override
public List<CardRules> call() throws Exception{
List<CardRules> res = loadCardsInRangeFromZip(entries, from, till);
cdl.countDown();
progressObserver.report(maxParts - (int)cdl.getCount(), maxParts);
return res;
}
});
}
return tasks;
}
private List<Callable<List<CardRules>>> makeTaskListForFiles(final List<File> allFiles, final CountDownLatch cdl) {
int totalFiles = allFiles.size();
final int maxParts = (int) cdl.getCount();
int filesPerPart = totalFiles / maxParts;
final List<Callable<List<CardRules>>> tasks = new ArrayList<Callable<List<CardRules>>>();
for (int iPart = 0; iPart < maxParts; iPart++) {
final int from = iPart * filesPerPart;
final int till = iPart == maxParts - 1 ? totalFiles : from + filesPerPart;
tasks.add(new Callable<List<CardRules>>() {
@Override
public List<CardRules> call() throws Exception{
List<CardRules> res = loadCardsInRange(allFiles, from, till);
cdl.countDown();
progressObserver.report(maxParts - (int)cdl.getCount(), maxParts);
return res;
}
});
}
return tasks;
}
public static List<File> collectCardFiles(List<File> accumulator, File startDir) {
String[] list = startDir.list();
for (String filename : list) {
File entry = new File(startDir, filename);
if (!entry.isDirectory()) {
if (entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION))
accumulator.add(entry);
continue;
}
if (filename.startsWith(".")) {
continue;
}
collectCardFiles(accumulator, entry);
}
return accumulator;
}
private List<String> readScript(final InputStream inputStream) {
return FileUtil.readAllLines(new InputStreamReader(inputStream, this.charset), true);
}
/**
* Load a card from a txt file.
*
* @param pathToTxtFile
* the full or relative path to the file to load
*
* @return a new Card instance
*/
protected final CardRules loadCard(final CardRules.Reader reader, final File file) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);
reader.reset();
List<String> lines = readScript(fileInputStream);
CardRules rules = reader.readCard(lines);
if ( null != observer )
observer.cardLoaded(rules, lines, file);
return rules;
} catch (final FileNotFoundException ex) {
throw new RuntimeException("CardReader : run error -- file not found: " + file.getPath(), ex);
} finally {
try {
fileInputStream.close();
} catch (final IOException ignored) {
// 11:08
// PM
}
}
}
/**
* Load a card from an entry in a zip file.
*
* @param entry
* to load from
*
* @return a new Card instance
*/
protected final CardRules loadCard(final CardRules.Reader rulesReader, final ZipEntry entry) {
InputStream zipInputStream = null;
try {
zipInputStream = this.zip.getInputStream(entry);
rulesReader.reset();
CardRules rules = rulesReader.readCard(readScript(zipInputStream));
return rules;
} catch (final IOException exn) {
throw new RuntimeException(exn);
// PM
} finally {
try {
if (zipInputStream != null) {
zipInputStream.close();
}
} catch (final IOException ignored) {
// 11:08
// PM
}
}
}
}

View 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;
}
}

View File

@@ -34,10 +34,10 @@ import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.Singletons;
import forge.StaticData;
import forge.item.PaperCard;
import forge.item.IPaperCard;
import forge.item.PrintSheet;
import forge.item.SealedProduct;
import forge.util.TextUtil;
/**
@@ -50,26 +50,15 @@ import forge.util.TextUtil;
*/
public class BoosterGenerator {
private static final String LAND = "Land";
public static final String ANY = "Any";
public static final String COMMON = "Common";
public static final String UNCOMMON = "Uncommon";
public static final String UNCOMMON_RARE = "UncommonRare";
public static final String RARE = "Rare";
public static final String RARE_MYTHIC = "RareMythic";
public static final String MYTHIC = "Mythic";
public static final String BASIC_LAND = "BasicLand";
public static final String TIME_SHIFTED = "TimeShifted";
private final static Map<String, PrintSheet> cachedSheets = new TreeMap<String, PrintSheet>(String.CASE_INSENSITIVE_ORDER);
private static final synchronized PrintSheet getPrintSheet(String key) {
if( !cachedSheets.containsKey(key) )
cachedSheets.put(key, makeSheet(key, CardDb.instance().getAllCards()));
cachedSheets.put(key, makeSheet(key, StaticData.instance().getCommonCards().getAllCards()));
return cachedSheets.get(key);
}
public static final List<PaperCard> getBoosterPack(SealedProductTemplate booster) {
public static final List<PaperCard> getBoosterPack(SealedProduct.Template booster) {
List<PaperCard> result = new ArrayList<PaperCard>();
for(Pair<String, Integer> slot : booster.getSlots()) {
String slotType = slot.getLeft(); // add expansion symbol here?
@@ -77,7 +66,7 @@ public class BoosterGenerator {
String[] sType = TextUtil.splitWithParenthesis(slotType, ' ');
String setCode = sType.length == 1 && booster.getEdition() != null ? booster.getEdition() : null;
String sheetKey = Singletons.getModel().getEditions().contains(setCode) ? slotType.trim() + " " + setCode: slotType.trim();
String sheetKey = StaticData.instance().getEditions().contains(setCode) ? slotType.trim() + " " + setCode: slotType.trim();
PrintSheet ps = getPrintSheet(sheetKey);
result.addAll(ps.random(numCards, true));
@@ -100,7 +89,7 @@ public class BoosterGenerator {
String mainCode = itMod.next();
if ( mainCode.regionMatches(true, 0, "fromSheet", 0, 9)) { // custom print sheet
String sheetName = StringUtils.strip(mainCode.substring(9), "()\" ");
src = Singletons.getModel().getPrintSheets().get(sheetName).toFlatList();
src = StaticData.instance().getPrintSheets().get(sheetName).toFlatList();
setPred = Predicates.alwaysTrue();
} else if (mainCode.startsWith("promo")) { // get exactly the named cards, that's a tiny inlined print sheet
@@ -108,7 +97,7 @@ public class BoosterGenerator {
String[] cardNames = TextUtil.splitWithParenthesis(list, ',', '"', '"');
List<PaperCard> srcList = new ArrayList<PaperCard>();
for(String cardName: cardNames)
srcList.add(CardDb.instance().getCard(cardName));
srcList.add(StaticData.instance().getCommonCards().getCard(cardName));
src = srcList;
setPred = Predicates.alwaysTrue();
@@ -121,18 +110,18 @@ public class BoosterGenerator {
// only special operators should remain by now - the ones that could not be turned into one predicate
String mainCode = operators.isEmpty() ? null : operators.get(0).trim();
if( null == mainCode || mainCode.equalsIgnoreCase(ANY) ) { // no restriction on rarity
if( null == mainCode || mainCode.equalsIgnoreCase(BoosterSlots.ANY) ) { // no restriction on rarity
Predicate<PaperCard> predicate = Predicates.and(setPred, extraPred);
ps.addAll(Iterables.filter(src, predicate));
} else if ( mainCode.equalsIgnoreCase(UNCOMMON_RARE) ) { // for sets like ARN, where U1 cards are considered rare and U3 are uncommon
} else if ( mainCode.equalsIgnoreCase(BoosterSlots.UNCOMMON_RARE) ) { // for sets like ARN, where U1 cards are considered rare and U3 are uncommon
Predicate<PaperCard> predicateRares = Predicates.and(setPred, IPaperCard.Predicates.Presets.IS_RARE, extraPred);
ps.addAll(Iterables.filter(src, predicateRares));
Predicate<PaperCard> predicateUncommon = Predicates.and( setPred, IPaperCard.Predicates.Presets.IS_UNCOMMON, extraPred);
ps.addAll(Iterables.filter(src, predicateUncommon), 3);
} else if ( mainCode.equalsIgnoreCase(RARE_MYTHIC) ) {
} else if ( mainCode.equalsIgnoreCase(BoosterSlots.RARE_MYTHIC) ) {
// Typical ratio of rares to mythics is 53:15, changing to 35:10 in smaller sets.
// To achieve the desired 1:8 are all mythics are added once, and all rares added twice per print sheet.
@@ -168,13 +157,13 @@ public class BoosterGenerator {
Predicate<PaperCard> toAdd = null;
if( operator.equalsIgnoreCase("dfc") ) { toAdd = Predicates.compose(CardRulesPredicates.splitType(CardSplitType.Transform), PaperCard.FN_GET_RULES);
} else if ( operator.equalsIgnoreCase(LAND) ) { toAdd = Predicates.compose(CardRulesPredicates.Presets.IS_LAND, PaperCard.FN_GET_RULES);
} else if ( operator.equalsIgnoreCase(BASIC_LAND)) { toAdd = IPaperCard.Predicates.Presets.IS_BASIC_LAND;
} else if ( operator.equalsIgnoreCase(TIME_SHIFTED)) { toAdd = IPaperCard.Predicates.Presets.IS_SPECIAL;
} else if ( operator.equalsIgnoreCase(MYTHIC)) { toAdd = IPaperCard.Predicates.Presets.IS_MYTHIC_RARE;
} else if ( operator.equalsIgnoreCase(RARE)) { toAdd = IPaperCard.Predicates.Presets.IS_RARE;
} else if ( operator.equalsIgnoreCase(UNCOMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_UNCOMMON;
} else if ( operator.equalsIgnoreCase(COMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_COMMON;
} else if ( operator.equalsIgnoreCase(BoosterSlots.LAND) ) { toAdd = Predicates.compose(CardRulesPredicates.Presets.IS_LAND, PaperCard.FN_GET_RULES);
} else if ( operator.equalsIgnoreCase(BoosterSlots.BASIC_LAND)) { toAdd = IPaperCard.Predicates.Presets.IS_BASIC_LAND;
} else if ( operator.equalsIgnoreCase(BoosterSlots.TIME_SHIFTED)) { toAdd = IPaperCard.Predicates.Presets.IS_SPECIAL;
} else if ( operator.equalsIgnoreCase(BoosterSlots.MYTHIC)) { toAdd = IPaperCard.Predicates.Presets.IS_MYTHIC_RARE;
} else if ( operator.equalsIgnoreCase(BoosterSlots.RARE)) { toAdd = IPaperCard.Predicates.Presets.IS_RARE;
} else if ( operator.equalsIgnoreCase(BoosterSlots.UNCOMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_UNCOMMON;
} else if ( operator.equalsIgnoreCase(BoosterSlots.COMMON)) { toAdd = IPaperCard.Predicates.Presets.IS_COMMON;
} else if ( operator.startsWith("name(") ) {
operator = StringUtils.strip(operator.substring(4), "() ");
String[] cardNames = TextUtil.splitWithParenthesis(operator, ',', '"', '"');

View 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";
}

View File

@@ -1,4 +1,4 @@
package forge;
package forge.card;
/**
* TODO: Write javadoc for this type.

View File

@@ -0,0 +1,423 @@
/*
* 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.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.TreeMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import forge.card.CardEdition.CardInSet;
import forge.item.PaperCard;
import forge.util.Aggregates;
import forge.util.CollectionSuppliers;
import forge.util.Lang;
import forge.util.MyRandom;
public final class CardDb implements ICardDatabase {
public final static String foilSuffix = "+";
private final static int foilSuffixLength = foilSuffix.length();
// 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 Map<String, PaperCard> uniqueCardsByName = new TreeMap<String, PaperCard>(String.CASE_INSENSITIVE_ORDER);
private final Map<String, CardRules> rulesByName;
private final List<PaperCard> allCards = new ArrayList<PaperCard>();
private final List<PaperCard> roAllCards = Collections.unmodifiableList(allCards);
private final Collection<PaperCard> roUniqueCards = Collections.unmodifiableCollection(uniqueCardsByName.values());
private final CardEdition.Collection editions;
public CardDb(Map<String, CardRules> rules, CardEdition.Collection editions0, boolean logMissingCards) {
this.rulesByName = rules;
this.editions = editions0;
List<String> missingCards = new ArrayList<String>();
for(CardEdition e : editions.getOrderedEditions()) {
boolean worthLogging = logMissingCards && ( e.getType() == CardEdition.Type.CORE || e.getType() == CardEdition.Type.EXPANSION || e.getType() == CardEdition.Type.REPRINT );
if(worthLogging)
System.out.print(e.getName() + " (" + e.getCards().length + " cards)");
String lastCardName = null;
int artIdx = 0;
for(CardEdition.CardInSet cis : e.getCards()) {
if ( cis.name.equals(lastCardName) )
artIdx++;
else {
artIdx = 0;
lastCardName = cis.name;
}
CardRules cr = rulesByName.get(lastCardName);
if( cr != null )
addCard(new PaperCard(cr, e.getCode(), cis.rarity, artIdx));
else if (worthLogging)
missingCards.add(cis.name);
}
if(worthLogging) {
if(missingCards.isEmpty())
System.out.println(" ... 100% ");
else {
int missing = (e.getCards().length - missingCards.size()) * 10000 / e.getCards().length;
System.out.printf(" ... %.2f%% (%s missing: %s )%n", missing * 0.01f, Lang.nounWithAmount(missingCards.size(), "card"), StringUtils.join(missingCards, " | ") );
}
missingCards.clear();
}
}
for(CardRules cr : rulesByName.values()) {
if( !allCardsByName.containsKey(cr.getName()) )
{
System.err.println("The card " + cr.getName() + " was not assigned to any set. Adding it to UNKNOWN set... to fix see res/cardeditions/ folder. ");
addCard(new PaperCard(cr, CardEdition.UNKNOWN.getCode(), CardRarity.Special, 0));
}
}
reIndex();
}
private void addCard(PaperCard paperCard) {
allCardsByName.put(paperCard.name, paperCard);
}
private void reIndex() {
uniqueCardsByName.clear();
allCards.clear();
for(Entry<String, Collection<PaperCard>> kv : allCardsByName.asMap().entrySet()) {
uniqueCardsByName.put(kv.getKey(), Iterables.getFirst(kv.getValue(), null));
allCards.addAll(kv.getValue());
}
}
/**
* Splits cardname into Name and set whenever deck line reads as name|set.
*/
private static ImmutablePair<String, String> splitCardName(final String name) {
String cardName = name; // .trim() ?
final int pipePos = cardName.indexOf('|');
if (pipePos >= 0) {
final String setName = cardName.substring(pipePos + 1).trim();
cardName = cardName.substring(0, pipePos);
// only if set is not blank try to load it
if (StringUtils.isNotBlank(setName) && !"???".equals(setName)) {
return new ImmutablePair<String, String>(cardName, setName);
}
}
return new ImmutablePair<String, String>(cardName, null);
}
private boolean isFoil(final String cardName) {
return cardName.toLowerCase().endsWith(CardDb.foilSuffix);
}
/**
* Removes the foil suffix.
*
* @param cardName the card name
* @return the string
*/
public String removeFoilSuffix(final String cardName) {
return cardName.toLowerCase().endsWith(CardDb.foilSuffix) ? cardName.substring(0, cardName.length() - CardDb.foilSuffixLength) : cardName;
}
@Override
public PaperCard tryGetCard(final String cardName0) {
return tryGetCard(cardName0, true);
}
@Override
public PaperCard tryGetCard(final String cardName0, boolean fromLastSet) {
if (null == cardName0) {
return null; // obviously
}
final boolean isFoil = this.isFoil(cardName0);
final String cardName = isFoil ? this.removeFoilSuffix(cardName0) : cardName0;
final ImmutablePair<String, String> nameWithSet = CardDb.splitCardName(cardName);
final PaperCard res = nameWithSet.right == null
? ( fromLastSet ? this.uniqueCardsByName.get(nameWithSet.left) : Aggregates.random(this.allCardsByName.get(nameWithSet.left)) )
: tryGetCard(nameWithSet.left, nameWithSet.right);
return null != res && isFoil ? getFoiled(res) : res;
}
@Override
public PaperCard tryGetCardPrintedByDate(final String name0, final boolean fromLatestSet, final Date printedBefore) {
final boolean isFoil = this.isFoil(name0);
final String cardName = isFoil ? this.removeFoilSuffix(name0) : name0;
final ImmutablePair<String, String> nameWithSet = CardDb.splitCardName(cardName);
PaperCard res = null;
if (null != nameWithSet.right) // set explicitly requested, should return card from it and disregard the date
res = tryGetCard(nameWithSet.left, nameWithSet.right);
else {
Collection<PaperCard> cards = this.allCardsByName.get(nameWithSet.left); // cards are sorted by datetime desc
int idxRightSet = 0;
for (PaperCard card : cards) {
if (editions.get(card.getEdition()).getDate().after(printedBefore))
idxRightSet++;
else
break;
}
res = fromLatestSet ? Iterables.get(cards, idxRightSet, null) : Aggregates.random(Iterables.skip(cards, idxRightSet));
}
return null != res && isFoil ? getFoiled(res) : res;
}
@Override
public PaperCard tryGetCard(final String cardName, String setName) {
return tryGetCard(cardName, setName, -1);
}
@Override
public PaperCard tryGetCard(final String cardName0, String setName, int index) {
final boolean isFoil = this.isFoil(cardName0);
final String cardName = isFoil ? this.removeFoilSuffix(cardName0) : cardName0;
Collection<PaperCard> cards = allCardsByName.get(cardName);
if ( null == cards ) return null;
CardEdition edition = editions.get(setName);
if ( null == edition )
return tryGetCard(cardName, true); // set not found, try to get the same card from just any set.
String effectiveSet = edition.getCode();
PaperCard result = null;
if ( index < 0 ) { // this stands for 'random art'
PaperCard[] candidates = new PaperCard[9]; // 9 cards with same name per set is a maximum of what has been printed (Arnchenemy)
int cnt = 0;
for( PaperCard pc : cards ) {
if( pc.getEdition().equalsIgnoreCase(effectiveSet) )
candidates[cnt++] = pc;
}
if (cnt == 0 ) return null;
result = cnt == 1 ? candidates[0] : candidates[MyRandom.getRandom().nextInt(cnt)];
} else
for( PaperCard pc : cards ) {
if( pc.getEdition().equalsIgnoreCase(effectiveSet) && index == pc.getArtIndex() ) {
result = pc;
break;
}
}
if ( result == null ) return null;
return isFoil ? getFoiled(result) : result;
}
public PaperCard getFoiled(PaperCard card0) {
// Here - I am still unsure if there should be a cache Card->Card from unfoiled to foiled, to avoid creation of N instances of single plains
return new PaperCard(card0.getRules(), card0.getEdition(), card0.getRarity(), card0.getArtIndex(), true);
}
@Override
public int getPrintCount(String cardName, String edition) {
int cnt = 0;
for( PaperCard pc : allCardsByName.get(cardName) ) {
if( pc.getEdition().equals(edition) )
cnt++;
}
return cnt;
}
@Override
public int getMaxPrintCount(String cardName) {
int max = -1;
for( PaperCard pc : allCardsByName.get(cardName) ) {
if ( max < pc.getArtIndex() )
max = pc.getArtIndex();
}
return max + 1;
}
// Single fetch
@Override
public PaperCard getCard(final String name) {
return this.getCard(name, false);
}
@Override
public PaperCard getCard(final String name0, final boolean fromLatestSet) {
// Sometimes they read from decks things like "CardName|Set" - but we
// can handle it
final PaperCard result = tryGetCard(name0, fromLatestSet);
if (null == result) {
throw new NoSuchElementException(String.format("Card '%s' not found in our database.", name0));
}
return result;
}
@Override
public PaperCard getCardPrintedByDate(final String name0, final boolean fromLatestSet, Date printedBefore ) {
// Sometimes they read from decks things like "CardName|Set" - but we
// can handle it
final PaperCard result = tryGetCard(name0, fromLatestSet);
if (null == result) {
throw new NoSuchElementException(String.format("Card '%s' released before %s not found in our database.", name0, printedBefore.toString()));
}
return result;
}
// Advanced fetch by name+set
@Override
public PaperCard getCard(final String name, final String set) {
return this.getCard(name, set, -1);
}
@Override
public PaperCard getCard(final String name, final String set, final int artIndex) {
final PaperCard result = tryGetCard(name, set, artIndex);
if (null == result) {
final String message = String.format("Asked for '%s' from '%s' #%d: db didn't find that copy.", name, set, artIndex);
throw new NoSuchElementException(message);
}
return result;
}
// returns a list of all cards from their respective latest editions
@Override
public Collection<PaperCard> getUniqueCards() {
return roUniqueCards;
}
@Override
public List<PaperCard> getAllCards() {
return roAllCards;
}
/** Returns a modifiable list of cards matching the given predicate */
@Override
public List<PaperCard> getAllCards(Predicate<PaperCard> predicate) {
return Lists.newArrayList(Iterables.filter(this.roAllCards, predicate));
}
@Override
public Iterator<PaperCard> iterator() {
return this.roAllCards.iterator();
}
public Predicate<? super PaperCard> wasPrintedInSets(List<String> setCodes) {
return new PredicateExistsInSets(setCodes);
}
private class PredicateExistsInSets implements Predicate<PaperCard> {
private final List<String> sets;
public PredicateExistsInSets(final List<String> wantSets) {
this.sets = wantSets; // maybe should make a copy here?
}
@Override
public boolean apply(final PaperCard subject) {
Collection<PaperCard> cc = allCardsByName.get(subject.getName());
for(PaperCard c : cc)
if (sets.contains(c.getEdition()))
return true;
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;
}
}
}

View File

@@ -0,0 +1,455 @@
/*
* 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.io.File;
import java.io.FilenameFilter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.StaticData;
import forge.item.SealedProduct;
import forge.util.Aggregates;
import forge.util.FileSection;
import forge.util.FileUtil;
import forge.util.IItemReader;
import forge.util.storage.StorageBase;
import forge.util.storage.StorageReaderBase;
import forge.util.storage.StorageReaderFolder;
/**
* <p>
* CardSet class.
* </p>
*
* @author Forge
* @version $Id: CardSet.java 9708 2011-08-09 19:34:12Z jendave $
*/
public final class CardEdition implements Comparable<CardEdition> { // immutable
public enum Type {
UNKNOWN,
CORE,
EXPANSION,
REPRINT,
STARTER,
DUEL_DECKS,
PREMIUM_DECK_SERIES,
FROM_THE_VAULT,
OTHER,
THIRDPARTY // custom sets
}
public enum FoilType {
NOT_SUPPORTED, // sets before Urza's Legacy
OLD_STYLE, // sets between Urza's Legacy and 8th Edition
MODERN // 8th Edition and newer
}
public static class CardInSet {
public final CardRarity rarity;
public final String name;
public CardInSet(final String name, final CardRarity rarity) {
this.rarity = rarity;
this.name = name;
}
}
/** The Constant unknown. */
private final static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
public static final CardEdition UNKNOWN = new CardEdition("1990-01-01", "??", "???", Type.UNKNOWN, "Undefined", FoilType.NOT_SUPPORTED, new CardInSet[]{});
private Date date;
private String code2;
private String code;
private Type type;
private String name;
private String alias = null;
private boolean whiteBorder = false;
private FoilType foilType = FoilType.NOT_SUPPORTED;
private int foilChanceInBooster = 0;
private boolean foilAlwaysInCommonSlot = false;
private final CardInSet[] cards;
private int boosterArts = 1;
private SealedProduct.Template boosterTpl = null;
private CardEdition(CardInSet[] cards) {
this.cards = cards;
}
/**
* Instantiates a new card set.
*
* @param index indicates order of set release date
* @param code2 the 2 (usually) letter code used for image filenames/URLs distributed by the HQ pics team that
* use Magic Workstation-type edition codes. Older sets only had 2-letter codes, and some of the 3-letter
* codes they use now aren't the same as the official list of 3-letter codes. When Forge downloads set-pics,
* it uses the 3-letter codes for the folder no matter the age of the set.
* @param code the MTG 3-letter set code
* @param type the set type
* @param name the name of the set
* @param an optional secondary code alias for the set
*/
private CardEdition(String date, String code2, String code, Type type, String name, FoilType foil, CardInSet[] cards) {
this(cards);
this.code2 = code2;
this.code = code;
this.type = type;
this.name = name;
this.date = parseDate(date);
this.foilType = foil;
}
private static Date parseDate(String date) {
if( date.length() <= 7 )
date = date + "-01";
try {
return formatter.parse(date);
} catch (ParseException e) {
return new Date();
}
}
public Date getDate() { return date; }
public String getCode2() { return code2; }
public String getCode() { return code; }
public Type getType() { return type; }
public String getName() { return name; }
public String getAlias() { return alias; }
public FoilType getFoilType() { return foilType; }
public int getFoilChanceInBooster() { return foilChanceInBooster; }
public boolean getFoilAlwaysInCommonSlot() { return foilAlwaysInCommonSlot; }
public CardInSet[] getCards() { return cards; }
/** The Constant fnGetName. */
public static final Function<CardEdition, String> FN_GET_CODE = new Function<CardEdition, String>() {
@Override
public String apply(final CardEdition arg1) {
return arg1.getCode();
}
};
@Override
public int compareTo(final CardEdition o) {
if (o == null) {
return 1;
}
return date.compareTo(o.date);
}
@Override
public int hashCode() {
return (this.code.hashCode() * 17) + this.name.hashCode();
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final CardEdition other = (CardEdition) obj;
return other.name.equals(this.name) && this.code.equals(other.code);
}
@Override
public String toString() {
return this.name + " (set)";
}
/**
* @return the whiteBorder
*/
public boolean isWhiteBorder() {
return whiteBorder;
}
public int getCntBoosterPictures() {
return boosterArts;
}
public SealedProduct.Template getBoosterTemplate() {
return boosterTpl;
}
public boolean hasBoosterTemplate() {
return boosterTpl != null;
}
public static class Reader extends StorageReaderFolder<CardEdition> {
public Reader(File path) {
super(path, CardEdition.FN_GET_CODE);
}
public final static CardInSet[] arrCards = new CardInSet[] {};
@Override
protected CardEdition read(File file) {
final Map<String, List<String>> contents = FileSection.parseSections(FileUtil.readFile(file));
List<CardEdition.CardInSet> processedCards = new ArrayList<CardEdition.CardInSet>();
for(String line : contents.get("cards")) {
if (StringUtils.isBlank(line))
continue;
// You may omit rarity for early development
CardRarity r = CardRarity.smartValueOf(line.substring(0, 1));
boolean hadRarity = r != CardRarity.Unknown && line.charAt(1) == ' ';
String cardName = hadRarity ? line.substring(2) : line;
CardInSet cis = new CardInSet(cardName, r);
processedCards.add(cis);
}
CardEdition res = new CardEdition(processedCards.toArray(arrCards));
FileSection section = FileSection.parse(contents.get("metadata"), "=");
res.name = section.get("name");
res.date = parseDate(section.get("date"));
res.code = section.get("code");
res.code2 = section.get("code2");
if( res.code2 == null )
res.code2 = res.code;
res.boosterArts = section.getInt("BoosterCovers", 1);
String boosterDesc = section.get("Booster");
res.boosterTpl = boosterDesc == null ? null : new SealedProduct.Template(res.code, SealedProduct.Template.Reader.parseSlots(boosterDesc));
res.alias = section.get("alias");
res.whiteBorder = "white".equalsIgnoreCase(section.get("border"));
String type = section.get("type");
Type enumType = Type.UNKNOWN;
if (null != type && !type.isEmpty()) {
try {
enumType = Type.valueOf(type.toUpperCase(Locale.ENGLISH));
} catch (IllegalArgumentException e) {
// ignore; type will get UNKNOWN
System.err.println(String.format("Ignoring unknown type in set definitions: name: %s; type: %s", res.name, type));
}
}
res.type = enumType;
switch(section.get("foil", "newstyle").toLowerCase()) {
case "notsupported":
res.foilType = FoilType.NOT_SUPPORTED;
break;
case "oldstyle":
case "classic":
res.foilType = FoilType.OLD_STYLE;
break;
case "newstyle":
case "modern":
res.foilType = FoilType.MODERN;
break;
default:
res.foilType = FoilType.NOT_SUPPORTED;
break;
}
res.foilChanceInBooster = section.getInt("FoilChanceInBooster", 16);
res.foilAlwaysInCommonSlot = section.getBoolean("FoilAlwaysInCommonSlot", false);
return res;
}
@Override
protected FilenameFilter getFileFilter() {
return TXT_FILE_FILTER;
}
public static final FilenameFilter TXT_FILE_FILTER = new FilenameFilter() {
@Override
public boolean accept(final File dir, final String name) {
return name.endsWith(".txt");
}
};
}
public static class Collection extends StorageBase<CardEdition> {
private final Map<String, CardEdition> aliasToEdition = new TreeMap<String, CardEdition>(String.CASE_INSENSITIVE_ORDER);
public Collection(IItemReader<CardEdition> reader) {
super("Card editions", reader);
for (CardEdition ee : this) {
String alias = ee.getAlias();
if (null != alias) {
aliasToEdition.put(alias, ee);
}
aliasToEdition.put(ee.getCode2(), ee);
}
}
/**
* Gets a sets by code. It will search first by three letter codes, then by aliases and two-letter codes.
*
* @param code
* the code
* @return the sets the by code
*/
@Override
public CardEdition get(final String code) {
CardEdition baseResult = super.get(code);
return baseResult == null ? aliasToEdition.get(code) : baseResult;
}
public Iterable<CardEdition> getOrderedEditions() {
List<CardEdition> res = Lists.newArrayList(this);
Collections.sort(res);
Collections.reverse(res);
return res;
}
/**
* Gets the sets by code or throw.
*
* @param code
* the code
* @return the sets the by code or throw
*/
public CardEdition getEditionByCodeOrThrow(final String code) {
final CardEdition set = this.get(code);
if (null == set) {
throw new RuntimeException(String.format("Edition with code '%s' not found", code));
}
return set;
}
// used by image generating code
/**
* Gets the code2 by code.
*
* @param code
* the code
* @return the code2 by code
*/
public String getCode2ByCode(final String code) {
final CardEdition set = this.get(code);
return set == null ? "" : set.getCode2();
}
public final Function<String, CardEdition> FN_EDITION_BY_CODE = new Function<String, CardEdition>() {
@Override
public CardEdition apply(String code) {
return Collection.this.get(code);
};
};
/**
* TODO: Write javadoc for this method.
* @return
*/
public IItemReader<SealedProduct.Template> getBoosterGenerator() {
// TODO Auto-generated method stub
return new StorageReaderBase<SealedProduct.Template>(null) {
@Override
public Map<String, SealedProduct.Template> readAll() {
Map<String, SealedProduct.Template> map = new TreeMap<String, SealedProduct.Template>(String.CASE_INSENSITIVE_ORDER);
for(CardEdition ce : Collection.this) {
map.put(ce.getCode(), ce.getBoosterTemplate());
}
return map;
}
@Override
public String getItemKey(SealedProduct.Template item) {
return item.getEdition();
}
};
}
}
public static class Predicates {
/** The Constant canMakeBooster. */
public static final Predicate<CardEdition> CAN_MAKE_BOOSTER = new CanMakeBooster();
private static class CanMakeBooster implements Predicate<CardEdition> {
@Override
public boolean apply(final CardEdition subject) {
return subject.hasBoosterTemplate();
}
}
public final static CardEdition getRandomSetWithAllBasicLands(Iterable<CardEdition> allEditions) {
return Aggregates.random(Iterables.filter(allEditions, hasBasicLands));
}
public static final Predicate<CardEdition> HAS_TOURNAMENT_PACK = new CanMakeStarter();
private static class CanMakeStarter implements Predicate<CardEdition> {
@Override
public boolean apply(final CardEdition subject) {
return StaticData.instance().getTournamentPacks().contains(subject.getCode());
}
}
public static final Predicate<CardEdition> HAS_FAT_PACK = new CanMakeFatPack();
private static class CanMakeFatPack implements Predicate<CardEdition> {
@Override
public boolean apply(final CardEdition subject) {
return StaticData.instance().getFatPacks().contains(subject.getCode());
}
}
public static final Predicate<CardEdition> hasBasicLands = new Predicate<CardEdition>() {
@Override
public boolean apply(CardEdition ed) {
for(String landName : MagicColor.Constant.BASIC_LANDS) {
if (null == StaticData.instance().getCommonCards().tryGetCard(landName, ed.getCode(), 0))
return false;
}
return true;
};
};
}
}

View File

@@ -22,6 +22,13 @@ import forge.card.mana.ManaCost;
*/
final class CardFace implements ICardFace {
public enum FaceSelectionMethod { //
USE_ACTIVE_FACE,
USE_PRIMARY_FACE,
COMBINE;
}
private final static List<String> emptyList = Collections.unmodifiableList(new ArrayList<String>());
private final static Map<String, String> emptyMap = Collections.unmodifiableMap(new TreeMap<String, String>());

View File

@@ -0,0 +1,478 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.card;
import java.util.List;
import java.util.StringTokenizer;
import org.apache.commons.lang3.StringUtils;
import forge.card.mana.IParserManaCost;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostShard;
/**
* A collection of methods containing full
* meta and gameplay properties of a card.
*
* @author Forge
* @version $Id: CardRules.java 9708 2011-08-09 19:34:12Z jendave $
*/
public final class CardRules implements ICardCharacteristics {
private CardSplitType splitType;
private ICardFace mainPart;
private ICardFace otherPart;
private CardAiHints aiHints;
private ColorSet colorIdentity = null;
private CardRules(ICardFace[] faces, CardSplitType altMode, CardAiHints cah) {
splitType = altMode;
mainPart = faces[0];
otherPart = faces[1];
aiHints = cah;
//Calculate Color Identity
byte colMask = calculateColorIdentity(mainPart);
if(otherPart != null)
{
colMask |= calculateColorIdentity(otherPart);
}
colorIdentity = ColorSet.fromMask(colMask);
}
void reinitializeFromRules(CardRules newRules) {
if(!newRules.getName().equals(this.getName()))
throw new UnsupportedOperationException("You cannot rename the card using the same CardRules object");
splitType = newRules.splitType;
mainPart = newRules.mainPart;
otherPart = newRules.otherPart;
aiHints = newRules.aiHints;
colorIdentity = newRules.colorIdentity;
}
private byte calculateColorIdentity(ICardFace face) {
byte res = face.getColor().getColor();
boolean isReminder = false;
boolean isSymbol = false;
String oracleText = face.getOracleText();
int len = oracleText.length();
for(int i = 0; i < len; i++) {
char c = oracleText.charAt(i); // This is to avoid needless allocations performed by toCharArray()
switch(c) {
case('('): isReminder = i > 0; break; // if oracle has only reminder, consider it valid rules (basic and true lands need this)
case(')'): isReminder = false; break;
case('{'): isSymbol = true; break;
case('}'): isSymbol = false; break;
default:
if(isSymbol && !isReminder) {
switch(c) {
case('W'): res |= MagicColor.WHITE; break;
case('U'): res |= MagicColor.BLUE; break;
case('B'): res |= MagicColor.BLACK; break;
case('R'): res |= MagicColor.RED; break;
case('G'): res |= MagicColor.GREEN; break;
}
}
break;
}
}
return res;
}
public boolean isVariant() {
CardType t = getType();
return t.isVanguard() || t.isScheme() || t.isPlane() || t.isPhenomenon();
}
public CardSplitType getSplitType() {
return splitType;
}
public ICardFace getMainPart() {
return mainPart;
}
public ICardFace getOtherPart() {
return otherPart;
}
public String getName() {
switch(splitType.getAggregationMethod()) {
case COMBINE:
return mainPart.getName() + " // " + otherPart.getName();
default:
return mainPart.getName();
}
}
public CardAiHints getAiHints() {
return aiHints;
}
@Override
public CardType getType() {
switch(splitType.getAggregationMethod()) {
case COMBINE: // no cards currently have different types
return CardType.combine(mainPart.getType(), otherPart.getType());
default:
return mainPart.getType();
}
}
@Override
public ManaCost getManaCost() {
switch(splitType.getAggregationMethod()) {
case COMBINE:
return ManaCost.combine(mainPart.getManaCost(), otherPart.getManaCost());
default:
return mainPart.getManaCost();
}
}
@Override
public ColorSet getColor() {
switch(splitType.getAggregationMethod()) {
case COMBINE:
return ColorSet.fromMask(mainPart.getColor().getColor() | otherPart.getColor().getColor());
default:
return mainPart.getColor();
}
}
@Override public int getIntPower() { return mainPart.getIntPower(); }
@Override public int getIntToughness() { return mainPart.getIntToughness(); }
@Override public String getPower() { return mainPart.getPower(); }
@Override public String getToughness() { return mainPart.getToughness(); }
@Override public int getInitialLoyalty() { return mainPart.getInitialLoyalty(); }
@Override
public String getOracleText() {
switch(splitType.getAggregationMethod()) {
case COMBINE:
return mainPart.getOracleText() + "\r\n\r\n" + otherPart.getOracleText();
default:
return mainPart.getOracleText();
}
}
// public Set<String> getSets() { return this.setsPrinted.keySet(); }
// public CardInSet getEditionInfo(final String setCode) {
// final CardInSet result = this.setsPrinted.get(setCode);
// return result; // if returns null, String.format("Card '%s' was never printed in set '%s'", this.getName(), setCode);
// }
// vanguard card fields, they don't use sides.
private int deltaHand;
private int deltaLife;
public int getHand() { return deltaHand; }
public int getLife() { return deltaLife; }
public void setVanguardProperties(String pt) {
final int slashPos = pt == null ? -1 : pt.indexOf('/');
if (slashPos == -1) {
throw new RuntimeException(String.format("Vanguard '%s' has bad hand/life stats", this.getName()));
}
this.deltaHand = Integer.parseInt(pt.substring(0, slashPos).replace("+", ""));
this.deltaLife = Integer.parseInt(pt.substring(slashPos+1).replace("+", ""));
}
// Downloadable image
private String dlUrl;
private String dlUrlOtherSide;
public String getPictureUrl(boolean backface ) { return backface ? dlUrlOtherSide : dlUrl; }
public void setDlUrls(String[] dlUrls) { this.dlUrl = dlUrls[0]; this.dlUrlOtherSide = dlUrls[1]; }
public final List<String> getReplacements() {
return null;
}
public final List<String> getTriggers() {
return null;
}
public final List<String> getStaticAbilities() {
return null;
}
public final List<String> getAbilities() {
return null;
}
public ColorSet getColorIdentity() {
return colorIdentity;
}
/** Instantiates class, reads a card. For batch operations better create you own reader instance. */
public static CardRules fromScript(Iterable<String> script) {
Reader crr = new Reader();
for(String line : script) {
crr.parseLine(line);
}
return crr.getCard();
}
// Reads cardname.txt
public static class Reader {
// fields to build
private CardFace[] faces = new CardFace[] { null, null };
private String[] pictureUrl = new String[] { null, null };
private int curFace = 0;
private CardSplitType altMode = CardSplitType.None;
private String handLife = null;
// fields to build CardAiHints
private boolean removedFromAIDecks = false;
private boolean removedFromRandomDecks = false;
private DeckHints hints = null;
private DeckHints needs = null;
/**
* Reset all fields to parse next card (to avoid allocating new CardRulesReader N times)
*/
public final void reset() {
this.curFace = 0;
this.faces[0] = null;
this.faces[1] = null;
this.pictureUrl[0] = null;
this.pictureUrl[1] = null;
this.handLife = null;
this.altMode = CardSplitType.None;
this.removedFromAIDecks = false;
this.removedFromRandomDecks = false;
this.needs = null;
this.hints = null;
}
/**
* Gets the card.
*
* @return the card
*/
public final CardRules getCard() {
CardAiHints cah = new CardAiHints(removedFromAIDecks, removedFromRandomDecks, hints, needs );
faces[0].assignMissingFields();
if (null != faces[1]) faces[1].assignMissingFields();
final CardRules result = new CardRules(faces, altMode, cah);
result.setDlUrls(pictureUrl);
if (StringUtils.isNotBlank(handLife))
result.setVanguardProperties(handLife);
return result;
}
public final CardRules readCard(final Iterable<String> script) {
this.reset();
for (String line : script) {
if (line.isEmpty() || line.charAt(0) == '#') {
continue;
}
this.parseLine(line);
}
return this.getCard();
}
/**
* Parses the line.
*
* @param line
* the line
*/
public final void parseLine(final String line) {
int colonPos = line.indexOf(':');
String key = colonPos > 0 ? line.substring(0, colonPos) : line;
String value = colonPos > 0 ? line.substring(1+colonPos).trim() : null;
switch(key.charAt(0)) {
case 'A':
if ("A".equals(key))
this.faces[curFace].addAbility(value);
else if ("AlternateMode".equals(key)) {
//System.out.println(faces[curFace].getName());
this.altMode = CardSplitType.smartValueOf(value);
} else if ("ALTERNATE".equals(key)) {
this.curFace = 1;
}
break;
case 'C':
if ("Colors".equals(key)) {
// This is forge.card.CardColor not forge.CardColor.
// Why do we have two classes with the same name?
ColorSet newCol = ColorSet.fromNames(value.split(","));
this.faces[this.curFace].setColor(newCol);
}
break;
case 'D':
if ("DeckHints".equals(key)) {
hints = new DeckHints(value);
} else if ("DeckNeeds".equals(key)) {
needs = new DeckHints(value);
}
break;
case 'H':
if ("HandLifeModifier".equals(key)) {
handLife = value;
}
break;
case 'K':
if ("K".equals(key)) {
this.faces[this.curFace].addKeyword(value);
}
break;
case 'L':
if ("Loyalty".equals(key)) {
this.faces[this.curFace].setInitialLoyalty(Integer.valueOf(value));
}
break;
case 'M':
if ("ManaCost".equals(key)) {
this.faces[this.curFace].setManaCost("no cost".equals(value) ? ManaCost.NO_COST
: new ManaCost(new ManaCostParser(value)));
}
break;
case 'N':
if ("Name".equals(key)) {
this.faces[this.curFace] = new CardFace(value);
}
break;
case 'O':
if ("Oracle".equals(key)) {
this.faces[this.curFace].setOracleText(value);
}
break;
case 'P':
if ("PT".equals(key)) {
this.faces[this.curFace].setPtText(value);
}
break;
case 'R':
if ("R".equals(key)) {
this.faces[this.curFace].addReplacementEffect(value);
}
break;
case 'S':
if ("S".equals(key)) {
this.faces[this.curFace].addStaticAbility(value);
} else if ( "SVar".equals(key) ) {
if ( null == value ) throw new IllegalArgumentException("SVar has no variable name");
colonPos = value.indexOf(':');
String variable = colonPos > 0 ? value.substring(0, colonPos) : value;
value = colonPos > 0 ? value.substring(1+colonPos) : null;
if ( "RemAIDeck".equals(variable) ) {
this.removedFromAIDecks = "True".equalsIgnoreCase(value);
} else if ( "RemRandomDeck".equals(variable) ) {
this.removedFromRandomDecks = "True".equalsIgnoreCase(value);
} else if ( "Picture".equals(variable) ) {
this.pictureUrl[this.curFace] = value;
} else if ( "Rarity".equals(variable) ) {
// discard that, they should supply it in SetInfo
} else
this.faces[curFace].addSVar(variable, value);
} else if ("SetInfo".equals(key)) {
// deprecated
}
break;
case 'T':
if ("T".equals(key)) {
this.faces[this.curFace].addTrigger(value);
} else if ("Types".equals(key)) {
this.faces[this.curFace].setType(CardType.parse(value));
} else if ("Text".equals(key) && !"no text".equals(value) && StringUtils.isNotBlank(value)) {
this.faces[this.curFace].setNonAbilityText(value);
}
break;
}
}
/**
* The Class ParserCardnameTxtManaCost.
*/
private static class ManaCostParser implements IParserManaCost {
private final StringTokenizer st;
private int colorlessCost;
public ManaCostParser(final String cost) {
st = new StringTokenizer(cost, " ");
this.colorlessCost = 0;
}
@Override
public final int getTotalColorlessCost() {
if (this.hasNext()) {
throw new RuntimeException("Colorless cost should be obtained after iteration is complete");
}
return this.colorlessCost;
}
/*
* (non-Javadoc)
*
* @see java.util.Iterator#hasNext()
*/
@Override
public final boolean hasNext() {
return st.hasMoreTokens();
}
/*
* (non-Javadoc)
*
* @see java.util.Iterator#next()
*/
@Override
public final ManaCostShard next() {
final String unparsed = st.nextToken();
// System.out.println(unparsed);
try {
int iVal = Integer.parseInt(unparsed);
this.colorlessCost += iVal;
return null;
}
catch (NumberFormatException nex) { }
return ManaCostShard.parseNonGeneric(unparsed);
}
/*
* (non-Javadoc)
*
* @see java.util.Iterator#remove()
*/
@Override
public void remove() {
} // unsuported
}
}
}

View File

@@ -170,7 +170,7 @@ public final class CardRulesPredicates {
*/
public static Predicate<CardRules> coreType(final boolean isEqual, final String what) {
try {
return CardRulesPredicates.coreType(isEqual, Enum.valueOf(CardCoreType.class, what));
return CardRulesPredicates.coreType(isEqual, Enum.valueOf(CardType.CoreType.class, what));
} catch (final Exception e) {
return com.google.common.base.Predicates.alwaysFalse();
}
@@ -185,7 +185,7 @@ public final class CardRulesPredicates {
* the type
* @return the predicate
*/
public static Predicate<CardRules> coreType(final boolean isEqual, final CardCoreType type) {
public static Predicate<CardRules> coreType(final boolean isEqual, final CardType.CoreType type) {
return new PredicateCoreType(type, isEqual);
}
@@ -200,7 +200,7 @@ public final class CardRulesPredicates {
*/
public static Predicate<CardRules> superType(final boolean isEqual, final String what) {
try {
return CardRulesPredicates.superType(isEqual, Enum.valueOf(CardSuperType.class, what));
return CardRulesPredicates.superType(isEqual, Enum.valueOf(CardType.SuperType.class, what));
} catch (final Exception e) {
return com.google.common.base.Predicates.alwaysFalse();
}
@@ -215,7 +215,7 @@ public final class CardRulesPredicates {
* the type
* @return the predicate
*/
public static Predicate<CardRules> superType(final boolean isEqual, final CardSuperType type) {
public static Predicate<CardRules> superType(final boolean isEqual, final CardType.SuperType type) {
return new PredicateSuperType(type, isEqual);
}
@@ -396,7 +396,7 @@ public final class CardRulesPredicates {
}
private static class PredicateCoreType implements Predicate<CardRules> {
private final CardCoreType operand;
private final CardType.CoreType operand;
private final boolean shouldBeEqual;
@Override
@@ -407,14 +407,14 @@ public final class CardRulesPredicates {
return this.shouldBeEqual == card.getType().typeContains(this.operand);
}
public PredicateCoreType(final CardCoreType type, final boolean wantEqual) {
public PredicateCoreType(final CardType.CoreType type, final boolean wantEqual) {
this.operand = type;
this.shouldBeEqual = wantEqual;
}
}
private static class PredicateSuperType implements Predicate<CardRules> {
private final CardSuperType operand;
private final CardType.SuperType operand;
private final boolean shouldBeEqual;
@Override
@@ -422,7 +422,7 @@ public final class CardRulesPredicates {
return this.shouldBeEqual == card.getType().superTypeContains(this.operand);
}
public PredicateSuperType(final CardSuperType type, final boolean wantEqual) {
public PredicateSuperType(final CardType.SuperType type, final boolean wantEqual) {
this.operand = type;
this.shouldBeEqual = wantEqual;
}
@@ -448,21 +448,21 @@ public final class CardRulesPredicates {
/** The Constant isCreature. */
public static final Predicate<CardRules> IS_CREATURE = CardRulesPredicates
.coreType(true, CardCoreType.Creature);
.coreType(true, CardType.CoreType.Creature);
public static final Predicate<CardRules> IS_LEGENDARY = CardRulesPredicates
.superType(true, CardSuperType.Legendary);
.superType(true, CardType.SuperType.Legendary);
/** The Constant isArtifact. */
public static final Predicate<CardRules> IS_ARTIFACT = CardRulesPredicates
.coreType(true, CardCoreType.Artifact);
.coreType(true, CardType.CoreType.Artifact);
/** The Constant isEquipment. */
public static final Predicate<CardRules> IS_EQUIPMENT = CardRulesPredicates
.subType("Equipment");
/** The Constant isLand. */
public static final Predicate<CardRules> IS_LAND = CardRulesPredicates.coreType(true, CardCoreType.Land);
public static final Predicate<CardRules> IS_LAND = CardRulesPredicates.coreType(true, CardType.CoreType.Land);
/** The Constant isBasicLand. */
public static final Predicate<CardRules> IS_BASIC_LAND = new Predicate<CardRules>() {
@@ -480,31 +480,17 @@ public final class CardRulesPredicates {
}
};
/** The Constant isPlaneswalker. */
public static final Predicate<CardRules> IS_PLANESWALKER = CardRulesPredicates.coreType(true,
CardCoreType.Planeswalker);
/** The Constant isInstant. */
public static final Predicate<CardRules> IS_INSTANT = CardRulesPredicates.coreType(true, CardCoreType.Instant);
/** The Constant isSorcery. */
public static final Predicate<CardRules> IS_SORCERY = CardRulesPredicates.coreType(true, CardCoreType.Sorcery);
/** The Constant isEnchantment. */
public static final Predicate<CardRules> IS_ENCHANTMENT = CardRulesPredicates.coreType(true, CardCoreType.Enchantment);
public static final Predicate<CardRules> IS_PLANE = CardRulesPredicates.coreType(true, CardCoreType.Plane);
public static final Predicate<CardRules> IS_PHENOMENON = CardRulesPredicates.coreType(true, CardCoreType.Phenomenon);
public static final Predicate<CardRules> IS_PLANESWALKER = CardRulesPredicates.coreType(true, CardType.CoreType.Planeswalker);
public static final Predicate<CardRules> IS_INSTANT = CardRulesPredicates.coreType(true, CardType.CoreType.Instant);
public static final Predicate<CardRules> IS_SORCERY = CardRulesPredicates.coreType(true, CardType.CoreType.Sorcery);
public static final Predicate<CardRules> IS_ENCHANTMENT = CardRulesPredicates.coreType(true, CardType.CoreType.Enchantment);
public static final Predicate<CardRules> IS_PLANE = CardRulesPredicates.coreType(true, CardType.CoreType.Plane);
public static final Predicate<CardRules> IS_PHENOMENON = CardRulesPredicates.coreType(true, CardType.CoreType.Phenomenon);
public static final Predicate<CardRules> IS_PLANE_OR_PHENOMENON = Predicates.or(IS_PLANE, IS_PHENOMENON);
public static final Predicate<CardRules> IS_SCHEME = CardRulesPredicates.coreType(true, CardCoreType.Scheme);
public static final Predicate<CardRules> IS_VANGUARD = CardRulesPredicates.coreType(true, CardCoreType.Vanguard);
/** The Constant isNonLand. */
public static final Predicate<CardRules> IS_NON_LAND = CardRulesPredicates.coreType(false, CardCoreType.Land);
/** The Constant isNonCreatureSpell. */
public static final Predicate<CardRules> IS_NON_CREATURE_SPELL = Predicates.not(Predicates.or(
Presets.IS_CREATURE, Presets.IS_LAND));
public static final Predicate<CardRules> IS_SCHEME = CardRulesPredicates.coreType(true, CardType.CoreType.Scheme);
public static final Predicate<CardRules> IS_VANGUARD = CardRulesPredicates.coreType(true, CardType.CoreType.Vanguard);
public static final Predicate<CardRules> IS_NON_LAND = CardRulesPredicates.coreType(false, CardType.CoreType.Land);
public static final Predicate<CardRules> IS_NON_CREATURE_SPELL = Predicates.not(Predicates.or(Presets.IS_CREATURE, Presets.IS_LAND));
/** The Constant IS_NONCREATURE_SPELL_FOR_GENERATOR. **/
@SuppressWarnings("unchecked")

View File

@@ -0,0 +1,36 @@
package forge.card;
import forge.card.CardFace.FaceSelectionMethod;
public enum CardSplitType
{
None(FaceSelectionMethod.USE_PRIMARY_FACE, null),
Transform(FaceSelectionMethod.USE_ACTIVE_FACE, CardCharacteristicName.Transformed),
Split(FaceSelectionMethod.COMBINE, CardCharacteristicName.RightSplit),
Flip(FaceSelectionMethod.USE_PRIMARY_FACE, CardCharacteristicName.Flipped),
// used by 12 licid creatures to switch type into enchantment aura
Licid(FaceSelectionMethod.USE_PRIMARY_FACE, CardCharacteristicName.Licid);
private CardSplitType(FaceSelectionMethod calcMode, CardCharacteristicName stateName) {
method = calcMode;
this.changedStateName = stateName;
}
public FaceSelectionMethod getAggregationMethod() {
return method;
}
private final FaceSelectionMethod method;
private final CardCharacteristicName changedStateName;
public static CardSplitType smartValueOf(String text) {
if ("DoubleFaced".equals(text)) return Transform;
// Will throw exceptions here if bad text passed
CardSplitType res = CardSplitType.valueOf(text);
return res;
}
public CardCharacteristicName getChangedStateName() {
return changedStateName;
}
}

View File

@@ -0,0 +1,389 @@
/*
* 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.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
/**
* <p>
* Immutable Card type. Can be build only from parsing a string.
* </p>
*
* @author Forge
* @version $Id: CardType.java 9708 2011-08-09 19:34:12Z jendave $
*/
public final class CardType implements Comparable<CardType> {
public enum CoreType {
/** The Artifact. */
Artifact,
/** The Creature. */
Creature,
/** The Enchantment. */
Enchantment,
/** The Instant. */
Instant,
/** The Land. */
Land,
/** The Plane. */
Plane,
/** The Planeswalker. */
Planeswalker,
/** The Scheme. */
Scheme,
/** The Sorcery. */
Sorcery,
/** The Tribal. */
Tribal,
/** The Vanguard. */
Vanguard,
/** The Phenomenon. */
Phenomenon
}
public enum SuperType {
/** The Basic. */
Basic,
/** The Legendary. */
Legendary,
/** The Snow. */
Snow,
/** The Ongoing. */
Ongoing,
/** The World. */
World
}
private final List<String> subType = new ArrayList<String>();
private final EnumSet<CardType.CoreType> coreType = EnumSet.noneOf(CardType.CoreType.class);
private final EnumSet<CardType.SuperType> superType = EnumSet.noneOf(CardType.SuperType.class);
private String calculatedType = null; // since obj is immutable, this is
// calc'd once
// This will be useful for faster parses
private static HashMap<String, CardType.CoreType> stringToCoreType = new HashMap<String, CardType.CoreType>();
private static HashMap<String, CardType.SuperType> stringToSuperType = new HashMap<String, CardType.SuperType>();
static {
for (final CardType.SuperType st : CardType.SuperType.values()) {
CardType.stringToSuperType.put(st.name(), st);
}
for (final CardType.CoreType ct : CardType.CoreType.values()) {
CardType.stringToCoreType.put(ct.name(), ct);
}
}
private CardType() { }
// TODO: Debug this code
public static CardType parse(final String typeText) {
// Most types and subtypes, except "Serra's Realm" and
// "Bolas's Meditation Realm" consist of only one word
final char space = ' ';
final CardType result = new CardType();
int iTypeStart = 0;
int iSpace = typeText.indexOf(space);
boolean hasMoreTypes = typeText.length() > 0;
while (hasMoreTypes) {
final String type = typeText.substring(iTypeStart, iSpace == -1 ? typeText.length() : iSpace);
hasMoreTypes = iSpace != -1;
if (!CardType.isMultiwordType(type) || !hasMoreTypes) {
iTypeStart = iSpace + 1;
result.parseAndAdd(type);
}
iSpace = typeText.indexOf(space, iSpace + 1);
}
return result;
}
public static CardType combine(final CardType a, final CardType b) {
CardType result = new CardType();
result.superType.addAll(a.superType);
result.superType.addAll(b.superType);
result.coreType.addAll(a.coreType);
result.coreType.addAll(b.coreType);
result.subType.addAll(a.subType);
result.subType.addAll(b.subType);
return result;
}
private static boolean isMultiwordType(final String type) {
final String[] multiWordTypes = { "Serra's Realm", "Bolas's Meditation Realm" };
// no need to loop for only 2 exceptions!
if (multiWordTypes[0].startsWith(type) && !multiWordTypes[0].equals(type)) {
return true;
}
if (multiWordTypes[1].startsWith(type) && !multiWordTypes[1].equals(type)) {
return true;
}
return false;
}
private void parseAndAdd(final String type) {
if ("-".equals(type)) {
return;
}
final CardType.CoreType ct = CardType.stringToCoreType.get(type);
if (ct != null) {
this.coreType.add(ct);
return;
}
final CardType.SuperType st = CardType.stringToSuperType.get(type);
if (st != null) {
this.superType.add(st);
return;
}
// If not recognized by super- and core- this must be subtype
this.subType.add(type);
}
public boolean subTypeContains(final String operand) {
return this.subType.contains(operand);
}
public boolean typeContains(final CardType.CoreType operand) {
return this.coreType.contains(operand);
}
public boolean superTypeContains(final CardType.SuperType operand) {
return this.superType.contains(operand);
}
public boolean isCreature() {
return this.coreType.contains(CardType.CoreType.Creature);
}
public boolean isPlaneswalker() {
return this.coreType.contains(CardType.CoreType.Planeswalker);
}
public boolean isLand() {
return this.coreType.contains(CardType.CoreType.Land);
}
public boolean isArtifact() {
return this.coreType.contains(CardType.CoreType.Artifact);
}
public boolean isInstant() {
return this.coreType.contains(CardType.CoreType.Instant);
}
public boolean isSorcery() {
return this.coreType.contains(CardType.CoreType.Sorcery);
}
public boolean isVanguard() {
return this.coreType.contains(CardType.CoreType.Vanguard);
}
public boolean isScheme() {
return this.coreType.contains(CardType.CoreType.Scheme);
}
public boolean isEnchantment() {
return this.coreType.contains(CardType.CoreType.Enchantment);
}
public boolean isBasic() {
return this.superType.contains(CardType.SuperType.Basic);
}
public boolean isLegendary() {
return this.superType.contains(CardType.SuperType.Legendary);
}
public boolean isBasicLand() {
return this.isBasic() && this.isLand();
}
@Override
public String toString() {
if (null == this.calculatedType) {
this.calculatedType = this.toStringImpl();
}
return this.calculatedType;
}
private String toStringImpl() {
if (this.subType.isEmpty()) {
return StringUtils.join(this.getTypesBeforeDash(), ' ');
} else {
return String.format("%s - %s", StringUtils.join(this.getTypesBeforeDash(), ' '), StringUtils.join(this.subType, " "));
}
}
public List<String> getTypesBeforeDash() {
final ArrayList<String> types = new ArrayList<String>();
for (final CardType.SuperType st : this.superType) {
types.add(st.name());
}
for (final CardType.CoreType ct : this.coreType) {
types.add(ct.name());
}
return types;
}
@Override
public int compareTo(final CardType o) {
return this.toString().compareTo(o.toString());
}
public List<String> getSubTypes() {
return this.subType;
}
public boolean sharesSubTypeWith(CardType ctOther) {
for (String t : ctOther.getSubTypes()) {
if (this.subTypeContains(t)) {
return true;
}
}
return false;
}
public boolean isPlane() {
return this.coreType.contains(CardType.CoreType.Plane);
}
public boolean isPhenomenon() {
return this.coreType.contains(CardType.CoreType.Phenomenon);
}
/**
* The Interface CardTypes.
*/
public static class Constant {
/** The loaded. */
public static final boolean[] LOADED = { false };
/** The card types. */
public static final List<String> CARD_TYPES = new ArrayList<String>();
/** The super types. */
public static final List<String> SUPER_TYPES = new ArrayList<String>();
/** The basic types. */
public static final List<String> BASIC_TYPES = new ArrayList<String>();
/** The land types. */
public static final List<String> LAND_TYPES = new ArrayList<String>();
/** The creature types. */
public static final List<String> CREATURE_TYPES = new ArrayList<String>();
/** The instant types. */
public static final List<String> INSTANT_TYPES = new ArrayList<String>();
/** The sorcery types. */
public static final List<String> SORCERY_TYPES = new ArrayList<String>();
/** The enchantment types. */
public static final List<String> ENCHANTMENT_TYPES = new ArrayList<String>();
/** The artifact types. */
public static final List<String> ARTIFACT_TYPES = new ArrayList<String>();
/** The walker types. */
public static final List<String> WALKER_TYPES = new ArrayList<String>();
}
///////// Utility methods
public static boolean isACardType(final String cardType) {
return CardType.getAllCardTypes().contains(cardType);
}
public static ArrayList<String> getAllCardTypes() {
final ArrayList<String> types = new ArrayList<String>();
// types.addAll(getCardTypes());
types.addAll(Constant.CARD_TYPES);
// not currently used by Forge
types.add("Plane");
types.add("Scheme");
types.add("Vanguard");
return types;
}
public static ArrayList<String> getBasicTypes() {
final ArrayList<String> types = new ArrayList<String>();
types.addAll(Constant.BASIC_TYPES);
return types;
}
public static ArrayList<String> getLandTypes() {
final ArrayList<String> types = new ArrayList<String>();
types.addAll(Constant.BASIC_TYPES);
types.addAll(Constant.LAND_TYPES);
return types;
}
public static ArrayList<String> getCreatureTypes() {
final ArrayList<String> types = new ArrayList<String>();
types.addAll(Constant.CREATURE_TYPES);
return types;
}
public static boolean isASuperType(final String cardType) {
return (Constant.SUPER_TYPES.contains(cardType));
}
public static boolean isASubType(final String cardType) {
return (!CardType.isASuperType(cardType) && !CardType.isACardType(cardType));
}
public static boolean isACreatureType(final String cardType) {
return (Constant.CREATURE_TYPES.contains(cardType));
}
public static boolean isALandType(final String cardType) {
return (Constant.LAND_TYPES.contains(cardType));
}
public static boolean isAPlaneswalkerType(final String cardType) {
return (Constant.WALKER_TYPES.contains(cardType));
}
public static boolean isABasicLandType(final String cardType) {
return (Constant.BASIC_TYPES.contains(cardType));
}
}

View File

@@ -17,7 +17,6 @@
*/
package forge.card;
import forge.Constant;
import forge.card.mana.ManaCost;
import forge.util.BinaryUtil;
@@ -253,7 +252,7 @@ public final class ColorSet implements Comparable<ColorSet> {
return "n/a";
}
String toReturn = MagicColor.toLongString(myColor);
if (toReturn == Constant.Color.COLORLESS && myColor != 0) {
if (toReturn == MagicColor.Constant.COLORLESS && myColor != 0) {
return "multi";
}
return toReturn;

View File

@@ -0,0 +1,34 @@
package forge.card;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import com.google.common.base.Predicate;
import forge.item.PaperCard;
public interface ICardDatabase extends Iterable<PaperCard> {
PaperCard tryGetCard(String cardName);
PaperCard tryGetCard(String cardName, boolean fromLastSet);
PaperCard tryGetCard(String cardName, String edition);
PaperCard tryGetCard(String cardName, String edition, int artIndex);
PaperCard tryGetCardPrintedByDate(String name0, boolean fromLatestSet, Date printedBefore);
PaperCard getCard(String cardName);
PaperCard getCard(String cardName, boolean fromLastSet);
PaperCard getCard(String cardName, String edition);
PaperCard getCard(String cardName, String edition, int artIndex);
PaperCard getCardPrintedByDate(String name0, boolean fromLatestSet, Date printedBefore);
PaperCard getFoiled(PaperCard cpi);
int getPrintCount(String cardName, String edition);
int getMaxPrintCount(String cardName);
Collection<PaperCard> getUniqueCards();
List<PaperCard> getAllCards();
List<PaperCard> getAllCards(Predicate<PaperCard> predicate);
Predicate<? super PaperCard> wasPrintedInSets(List<String> allowedSetCodes);
}

View 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");
}
}

View File

@@ -1,5 +1,6 @@
package forge.item;
package forge.card;
import java.io.File;
import java.util.List;
import java.util.Map.Entry;
import java.util.ArrayList;
@@ -7,7 +8,9 @@ import java.util.Collection;
import com.google.common.base.Function;
import forge.util.ItemPool;
import forge.deck.CardPool;
import forge.item.PaperCard;
import forge.util.MyRandom;
import forge.util.storage.StorageReaderFileSections;
@@ -30,7 +33,7 @@ public class PrintSheet {
this(name0, null);
}
private PrintSheet(String name0, ItemPool<PaperCard> pool) {
public PrintSheet(String name0, ItemPool<PaperCard> pool) {
name = name0;
cardsWithWeights = pool != null ? pool : new ItemPool<PaperCard>(PaperCard.class);
}
@@ -105,9 +108,17 @@ public class PrintSheet {
return result;
}
public boolean isEmpty() {
return cardsWithWeights.isEmpty();
}
public Iterable<PaperCard> toFlatList() {
return cardsWithWeights.toFlatList();
}
public static class Reader extends StorageReaderFileSections<PrintSheet> {
public Reader(String fileName) {
super(fileName, PrintSheet.FN_GET_KEY);
public Reader(File file) {
super(file, PrintSheet.FN_GET_KEY);
}
@Override
@@ -117,13 +128,4 @@ public class PrintSheet {
}
public boolean isEmpty() {
return cardsWithWeights.isEmpty();
}
public Iterable<PaperCard> toFlatList() {
return cardsWithWeights.toFlatList();
}
}

View File

@@ -10,13 +10,15 @@ import org.apache.commons.lang3.tuple.Pair;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.StaticData;
import forge.item.PaperCard;
import forge.item.ItemPoolView;
import forge.item.PrintSheet;
import forge.item.SealedProduct;
import forge.util.ItemPoolView;
public class UnOpenedProduct implements IUnOpenedProduct {
private final SealedProductTemplate tpl;
private final SealedProduct.Template tpl;
private final Map<String, PrintSheet> sheets;
private boolean poolLimited = false; // if true after successful generation cards are removed from printsheets.
@@ -30,24 +32,24 @@ public class UnOpenedProduct implements IUnOpenedProduct {
// Means to select from all unique cards (from base game, ie. no schemes or avatars)
public UnOpenedProduct(SealedProductTemplate template) {
public UnOpenedProduct(SealedProduct.Template template) {
tpl = template;
sheets = null;
}
// Invoke this constructor only if you are sure that the pool is not equal to deafult carddb
public UnOpenedProduct(SealedProductTemplate template, ItemPoolView<PaperCard> pool) {
public UnOpenedProduct(SealedProduct.Template template, ItemPoolView<PaperCard> pool) {
this(template, pool.toFlatList());
}
public UnOpenedProduct(SealedProductTemplate template, Iterable<PaperCard> cards) {
public UnOpenedProduct(SealedProduct.Template template, Iterable<PaperCard> cards) {
tpl = template;
sheets = new TreeMap<String, PrintSheet>();
prebuildSheets(cards);
}
public UnOpenedProduct(SealedProductTemplate sealedProductTemplate, Predicate<PaperCard> filterPrinted) {
this(sealedProductTemplate, Iterables.filter(CardDb.instance().getAllCards(), filterPrinted));
public UnOpenedProduct(SealedProduct.Template sealedProductTemplate, Predicate<PaperCard> filterPrinted) {
this(sealedProductTemplate, Iterables.filter(StaticData.instance().getCommonCards().getAllCards(), filterPrinted));
}
private void prebuildSheets(Iterable<PaperCard> sourceList) {

View File

@@ -97,22 +97,19 @@ public final class ManaCost implements Comparable<ManaCost> {
return "no cost";
}
if (this.shards.isEmpty()) {
return Integer.toString(this.genericCost);
return "{" + this.genericCost + "}";
}
final StringBuilder sb = new StringBuilder();
boolean isFirst = true;
if (this.genericCost > 0) {
sb.append(this.genericCost);
isFirst = false;
sb.append("{" + this.genericCost + "}");
}
for (final ManaCostShard s : this.shards) {
if (!isFirst) {
sb.append(' ');
if (s == ManaCostShard.X) {
sb.insert(0, s.toString());
} else {
isFirst = false;
sb.append(s.toString());
}
sb.append(s.toString());
}
return sb.toString();
}
@@ -287,5 +284,4 @@ public final class ManaCost implements Comparable<ManaCost> {
res.sealClass(sh);
return res;
}
}

View File

@@ -11,6 +11,17 @@ public class ManaCostParser implements IParserManaCost {
private int nextToken;
private int colorlessCost;
/**
* Parse the given cost and output formatted cost string
*
* @param cost
*/
public static String parse(final String cost) {
final ManaCostParser parser = new ManaCostParser(cost);
final ManaCost manaCost = new ManaCost(parser);
return manaCost.toString();
}
/**
* Instantiates a new parser cardname txt mana cost.
*
@@ -54,7 +65,6 @@ public class ManaCostParser implements IParserManaCost {
*/
@Override
public final ManaCostShard next() {
final String unparsed = this.cost[this.nextToken++];
// System.out.println(unparsed);
if (StringUtils.isNumeric(unparsed)) {

View File

@@ -35,14 +35,14 @@ public enum ManaCostShard implements Comparable<ManaCostShard> {
/* Hybrid */
WU(ManaAtom.WHITE | ManaAtom.BLUE, "W/U", "WU"),
WB(ManaAtom.WHITE | ManaAtom.BLACK, "W/B", "WB"),
WR(ManaAtom.WHITE | ManaAtom.RED, "W/R", "RW"),
WG(ManaAtom.WHITE | ManaAtom.GREEN, "W/G", "GW"),
UB(ManaAtom.BLUE | ManaAtom.BLACK, "U/B", "UB"),
UR(ManaAtom.BLUE | ManaAtom.RED, "U/R", "UR"),
UG(ManaAtom.BLUE | ManaAtom.GREEN, "U/G", "GU"),
BR(ManaAtom.BLACK | ManaAtom.RED, "B/R", "BR"),
BG(ManaAtom.BLACK | ManaAtom.GREEN, "B/G", "BG"),
RW(ManaAtom.RED | ManaAtom.WHITE, "R/W", "RW"),
RG(ManaAtom.RED | ManaAtom.GREEN, "R/G", "RG"),
GW(ManaAtom.GREEN | ManaAtom.WHITE, "G/W", "GW"),
GU(ManaAtom.GREEN | ManaAtom.BLUE, "G/U", "GU"),
/* Or 2 colorless */
W2(ManaAtom.WHITE | ManaAtom.OR_2_COLORLESS, "2/W", "2W"),
@@ -102,15 +102,12 @@ public enum ManaCostShard implements Comparable<ManaCostShard> {
this.shard = value;
this.cmc = this.getCMC();
this.cmpc = this.getCmpCost();
this.stringValue = sValue;
this.stringValue = "{" + sValue + "}";
this.imageKey = imgKey;
}
public static final int COLORS_SUPERPOSITION = ManaAtom.WHITE | ManaAtom.BLUE | ManaAtom.BLACK | ManaAtom.RED | ManaAtom.GREEN;
private int getCMC() {
if (0 != (this.shard & ManaAtom.IS_X)) {
return 0;

View File

@@ -18,7 +18,6 @@
package forge.deck;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -26,10 +25,9 @@ import java.util.NoSuchElementException;
import org.apache.commons.lang3.StringUtils;
import forge.Card;
import forge.card.CardDb;
import forge.StaticData;
import forge.item.PaperCard;
import forge.item.ItemPool;
import forge.util.ItemPool;
/**
* Deck section.
@@ -54,15 +52,6 @@ public class CardPool extends ItemPool<PaperCard> {
this.addAll(cards);
}
/**
* Adds the.
*
* @param card
* the card
*/
public void add(final Card card) {
this.add(CardDb.getCard(card));
}
/**
* Adds the.
@@ -84,9 +73,9 @@ public class CardPool extends ItemPool<PaperCard> {
* @param amount the amount
*/
public void add(final String cardName, final String setCode, final int amount) {
PaperCard cp = CardDb.instance().tryGetCard(cardName, setCode);
PaperCard cp = StaticData.instance().getCommonCards().tryGetCard(cardName, setCode);
if ( cp == null )
cp = CardDb.variants().tryGetCard(cardName, setCode);
cp = StaticData.instance().getVariantCards().tryGetCard(cardName, setCode);
if ( cp != null)
this.add(cp, amount);
@@ -94,18 +83,6 @@ public class CardPool extends ItemPool<PaperCard> {
throw new RuntimeException(String.format("Card %s from %s is not supported by Forge, as it's neither a known common card nor one of casual variants' card.", cardName, setCode ));
}
/**
* Adds the.
*
* @param cardList
* the card list
*/
public void add(final List<Card> cardList) {
for (final Card c : cardList) {
this.add(c);
}
}
/**
* Add all from a List of CardPrinted.
*
@@ -124,9 +101,9 @@ public class CardPool extends ItemPool<PaperCard> {
* @param cardName the card name
*/
public void add(final String cardName, int cnt) {
PaperCard cp = CardDb.instance().tryGetCard(cardName);
PaperCard cp = StaticData.instance().getCommonCards().tryGetCard(cardName);
if ( cp == null )
cp = CardDb.variants().tryGetCard(cardName);
cp = StaticData.instance().getVariantCards().tryGetCard(cardName);
if ( cp != null)
this.add(cp, cnt);

View File

@@ -27,6 +27,7 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Function;
@@ -34,12 +35,12 @@ import com.google.common.base.Function;
import forge.card.CardDb;
import forge.deck.io.DeckFileHeader;
import forge.deck.io.DeckSerializer;
import forge.gui.deckeditor.tables.TableSorter;
import forge.item.PaperCard;
import forge.item.IPaperCard;
import forge.item.ItemPoolView;
import forge.util.FileSection;
import forge.util.FileUtil;
import forge.util.ItemPoolSorter;
import forge.util.ItemPoolView;
/**
@@ -199,7 +200,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
private static List<String> writeCardPool(final ItemPoolView<PaperCard> pool) {
final List<Entry<PaperCard, Integer>> main2sort = pool.getOrderedList();
Collections.sort(main2sort, TableSorter.BY_NAME_THEN_SET);
Collections.sort(main2sort, ItemPoolSorter.BY_NAME_THEN_SET);
final List<String> out = new ArrayList<String>();
for (final Entry<PaperCard, Integer> e : main2sort) {
out.add(serializeSingleCard(e.getKey(), e.getValue()));

View File

@@ -19,11 +19,13 @@ package forge.deck;
import java.io.Serializable;
import forge.util.IHasName;
/**
* TODO: Write javadoc for this type.
*
*/
public abstract class DeckBase implements Serializable, Comparable<DeckBase> {
public abstract class DeckBase implements Serializable, Comparable<DeckBase>, IHasName {
private static final long serialVersionUID = -7538150536939660052L;
// gameType is from Constant.GameType, like GameType.Regular
@@ -36,7 +38,7 @@ public abstract class DeckBase implements Serializable, Comparable<DeckBase> {
* @param name0 the name0
*/
public DeckBase(final String name0) {
this.name = name0;
this.name = name0.replace('/', '_');
}
/* (non-Javadoc)
@@ -50,8 +52,8 @@ public abstract class DeckBase implements Serializable, Comparable<DeckBase> {
/** {@inheritDoc} */
@Override
public boolean equals(final Object o) {
if (o instanceof Deck) {
final Deck d = (Deck) o;
if (o instanceof DeckBase) {
final DeckBase d = (DeckBase) o;
return this.getName().equals(d.getName());
}
return false;

View File

@@ -22,15 +22,14 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
import org.apache.commons.lang.math.IntRange;
import forge.Singletons;
import forge.card.CardCoreType;
import forge.card.CardDb;
import org.apache.commons.lang3.Range;
import forge.StaticData;
import forge.card.CardType;
import forge.card.ColorSet;
import forge.item.PaperCard;
import forge.item.IPaperCard;
import forge.properties.ForgePreferences.FPref;
import forge.util.Aggregates;
/**
@@ -39,26 +38,21 @@ import forge.util.Aggregates;
public enum DeckFormat {
// Main board: allowed size SB: restriction Max distinct non basic cards
Constructed ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0, 15), 4),
QuestDeck ( new IntRange(40, Integer.MAX_VALUE), new IntRange(0, 15), 4),
Limited ( new IntRange(40, Integer.MAX_VALUE), null, Integer.MAX_VALUE),
Commander ( new IntRange(99), new IntRange(0, 10), 1),
Vanguard ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4),
Planechase ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4),
Archenemy ( new IntRange(60, Integer.MAX_VALUE), new IntRange(0), 4);
Constructed ( Range.between(60, Integer.MAX_VALUE), Range.between(0, 15), 4),
QuestDeck ( Range.between(40, Integer.MAX_VALUE), Range.between(0, 15), 4),
Limited ( Range.between(40, Integer.MAX_VALUE), null, Integer.MAX_VALUE),
Commander ( Range.is(99), Range.between(0, 10), 1),
Vanguard ( Range.between(60, Integer.MAX_VALUE), Range.is(0), 4),
Planechase ( Range.between(60, Integer.MAX_VALUE), Range.is(0), 4),
Archenemy ( Range.between(60, Integer.MAX_VALUE), Range.is(0), 4);
private final IntRange mainRange;
private final IntRange sideRange; // null => no check
private final Range<Integer> mainRange;
private final Range<Integer> sideRange; // null => no check
private final int maxCardCopies;
/**
* Instantiates a new game type.
*
* @param isLimited
* the is limited
*/
DeckFormat(IntRange main, IntRange side, int maxCopies) {
DeckFormat(Range<Integer> main, Range<Integer> side, int maxCopies) {
mainRange = main;
sideRange = side;
maxCardCopies = maxCopies;
@@ -90,7 +84,7 @@ public enum DeckFormat {
/**
* @return the sideRange
*/
public IntRange getSideRange() {
public Range<Integer> getSideRange() {
return sideRange;
}
@@ -98,7 +92,7 @@ public enum DeckFormat {
/**
* @return the mainRange
*/
public IntRange getMainRange() {
public Range<Integer> getMainRange() {
return mainRange;
}
@@ -118,15 +112,10 @@ public enum DeckFormat {
return "is not selected";
}
// That's really a bad dependence
if (!Singletons.getModel().getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY)) {
return null;
}
int deckSize = deck.getMain().countAll();
int min = getMainRange().getMinimumInteger();
int max = getMainRange().getMaximumInteger();
int min = getMainRange().getMinimum();
int max = getMainRange().getMaximum();
if (deckSize < min) {
return String.format("should have a minimum of %d cards", min);
@@ -189,7 +178,7 @@ public enum DeckFormat {
int phenoms = 0;
for (Entry<PaperCard, Integer> cp : planes) {
if (cp.getKey().getRules().getType().typeContains(CardCoreType.Phenomenon)) {
if (cp.getKey().getRules().getType().typeContains(CardType.CoreType.Phenomenon)) {
phenoms++;
}
if (cp.getValue() > 1) {
@@ -233,7 +222,7 @@ public enum DeckFormat {
// should group all cards by name, so that different editions of same card are really counted as the same card
for (Entry<String, Integer> cp : Aggregates.groupSumBy(tmp, PaperCard.FN_GET_NAME)) {
IPaperCard simpleCard = CardDb.instance().getCard(cp.getKey());
IPaperCard simpleCard = StaticData.instance().getCommonCards().getCard(cp.getKey());
boolean canHaveMultiple = simpleCard.getRules().getType().isBasicLand() || limitExceptions.contains(cp.getKey());
if (!canHaveMultiple && cp.getValue() > maxCopies) {
@@ -244,11 +233,11 @@ public enum DeckFormat {
// The sideboard must contain either 0 or 15 cards
int sideboardSize = deck.has(DeckSection.Sideboard) ? deck.get(DeckSection.Sideboard).countAll() : 0;
IntRange sbRange = getSideRange();
if (sbRange != null && sideboardSize > 0 && !sbRange.containsInteger(sideboardSize)) {
return sbRange.getMinimumInteger() == sbRange.getMaximumInteger()
? String.format("must have a sideboard of %d cards or no sideboard at all", sbRange.getMaximumInteger())
: String.format("must have a sideboard of %d to %d cards or no sideboard at all", sbRange.getMinimumInteger(), sbRange.getMaximumInteger());
Range<Integer> sbRange = getSideRange();
if (sbRange != null && sideboardSize > 0 && !sbRange.contains(sideboardSize)) {
return sbRange.getMinimum() == sbRange.getMaximum()
? String.format("must have a sideboard of %d cards or no sideboard at all", sbRange.getMaximum())
: String.format("must have a sideboard of %d to %d cards or no sideboard at all", sbRange.getMinimum(), sbRange.getMaximum());
}
return null;

View File

@@ -17,12 +17,15 @@
*/
package forge.deck;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import forge.card.CardDb;
import forge.card.ICardDatabase;
import forge.item.PaperCard;
/**
@@ -159,17 +162,17 @@ public class DeckRecognizer {
private static final Pattern SEARCH_NUMBERS_IN_FRONT = Pattern.compile("([\\d]{1,2})[^A-Za-wyz]*\\s+(.*)");
//private static final Pattern READ_SEPARATED_EDITION = Pattern.compile("[[\\(\\{]([a-zA-Z0-9]){1,3})[]*\\s+(.*)");
/**
* Recognize line.
*
* @param rawLine
* the raw_line
* @param newestEdition
* get the newest available edition?
*
* @return the token
*/
public static Token recognizeLine(final String rawLine, final boolean newestEdition) {
private final boolean useLastSet;
private final ICardDatabase db;
private Date recognizeCardsPrintedBefore = null;
public DeckRecognizer(boolean fromLatestSet, CardDb db) {
useLastSet = fromLatestSet;
this.db = db;
}
public Token recognizeLine(final String rawLine) {
if (StringUtils.isBlank(rawLine)) {
return new Token(TokenType.Comment, 0, rawLine);
}
@@ -181,7 +184,7 @@ public class DeckRecognizer {
if (foundNumbersInFront.matches()) {
final String cardName = foundNumbersInFront.group(2);
final int amount = Integer.parseInt(foundNumbersInFront.group(1));
result = DeckRecognizer.recognizePossibleNameAndNumber(cardName, amount, newestEdition);
result = recognizePossibleNameAndNumber(cardName, amount);
} /*
* else if (foundNumbersInBack.matches()) { String cardName =
* foundNumbersInBack.group(1); int amount =
@@ -189,17 +192,25 @@ public class DeckRecognizer {
* Token(cardName, amount); }
*/
else {
if (null != CardDb.instance().tryGetCard(line)) {
return Token.knownCard(CardDb.instance().getCard(line, newestEdition), 1);
PaperCard pc = tryGetCard(line);
if (null != pc) {
return Token.knownCard(pc, 1);
}
result = DeckRecognizer.recognizeNonCard(line, 1);
}
return result != null ? result : new Token(TokenType.UnknownText, 0, line);
}
private static Token recognizePossibleNameAndNumber(final String name, final int n, final boolean newestEdition) {
if (null != CardDb.instance().tryGetCard(name)) {
return Token.knownCard(CardDb.instance().getCard(name, newestEdition), n);
private PaperCard tryGetCard(String text) {
if(recognizeCardsPrintedBefore != null )
return db.tryGetCardPrintedByDate(text, useLastSet, recognizeCardsPrintedBefore);
return db.tryGetCard(text, useLastSet);
}
private Token recognizePossibleNameAndNumber(final String name, final int n) {
PaperCard pc = tryGetCard(name);
if (null != pc) {
return Token.knownCard(pc, n);
}
// TODO: recognize format: http://topdeck.ru/forum/index.php?showtopic=12711
@@ -260,4 +271,16 @@ public class DeckRecognizer {
return false;
}
/**
* TODO: Write javadoc for this method.
* @param month
* @param year
*/
public void setDateConstraint(int month, Integer year) {
Calendar ca = Calendar.getInstance();
ca.set(year, month, 1);
recognizeCardsPrintedBefore = ca.getTime();
}
}

View File

@@ -0,0 +1,115 @@
/*
* 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.generation;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.tuple.ImmutablePair;
import com.google.common.collect.Lists;
import forge.card.ColorSet;
import forge.card.ICardDatabase;
import forge.card.MagicColor;
import forge.item.PaperCard;
import forge.util.ItemPoolView;
/**
* <p>
* Generate2ColorDeck class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class DeckGenerator2Color extends DeckGeneratorBase {
@Override protected final float getLandsPercentage() { return 0.39f; }
@Override protected final float getCreatPercentage() { return 0.36f; }
@Override protected final float getSpellPercentage() { return 0.25f; }
@SuppressWarnings("unchecked")
final List<ImmutablePair<FilterCMC, Integer>> cmcRelativeWeights = Lists.newArrayList(
ImmutablePair.of(new FilterCMC(0, 2), 6),
ImmutablePair.of(new FilterCMC(3, 4), 4),
ImmutablePair.of(new FilterCMC(5, 6), 2),
ImmutablePair.of(new FilterCMC(7, 20), 1)
);
// mana curve of the card pool
// 20x 0 - 2
// 16x 3 - 4
// 12x 5 - 6
// 4x 7 - 20
// = 52x - card pool (before further random filtering)
/**
* <p>
* Constructor for Generate2ColorDeck.
* </p>
*
* @param clr1
* a {@link java.lang.String} object.
* @param clr2
* a {@link java.lang.String} object.
*/
public DeckGenerator2Color(ICardDatabase cardDb, final String clr1, final String clr2) {
super(cardDb);
int c1 = MagicColor.fromName(clr1);
int c2 = MagicColor.fromName(clr2);
if( c1 == 0 && c2 == 0) {
int color1 = r.nextInt(5);
int color2 = (color1 + 1 + r.nextInt(4)) % 5;
colors = ColorSet.fromMask(MagicColor.WHITE << color1 | MagicColor.WHITE << color2);
} else if ( c1 == 0 || c2 == 0 ) {
byte knownColor = (byte) (c1 | c2);
int color1 = Arrays.binarySearch(MagicColor.WUBRG, knownColor);
int color2 = (color1 + 1 + r.nextInt(4)) % 5;
colors = ColorSet.fromMask(MagicColor.WHITE << color1 | MagicColor.WHITE << color2);
} else {
colors = ColorSet.fromMask(c1 | c2);
}
}
@Override
public final ItemPoolView<PaperCard> getDeck(final int size, final boolean forAi) {
addCreaturesAndSpells(size, cmcRelativeWeights, forAi);
// Add lands
int numLands = Math.round(size * getLandsPercentage());
adjustDeckSize(size - numLands);
tmpDeck.append(String.format("Adjusted deck size to: %d, should add %d land(s)%n", size - numLands, numLands));
// Add dual lands
List<String> duals = getDualLandList();
for (String s : duals) {
this.cardCounts.put(s, 0);
}
int dblsAdded = addSomeStr((numLands / 6), duals);
numLands -= dblsAdded;
addBasicLand(numLands);
tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n");
//System.out.println(tmpDeck.toString());
return tDeck;
}
}

View File

@@ -0,0 +1,121 @@
/*
* 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.generation;
import java.util.List;
import org.apache.commons.lang3.tuple.ImmutablePair;
import com.google.common.collect.Lists;
import forge.card.ColorSet;
import forge.card.ICardDatabase;
import forge.card.MagicColor;
import forge.item.PaperCard;
import forge.util.ItemPoolView;
import forge.util.MyRandom;
/**
* <p>
* Generate3ColorDeck class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class DeckGenerator3Color extends DeckGeneratorBase {
@SuppressWarnings("unchecked")
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
ImmutablePair.of(new FilterCMC(0, 2), 12),
ImmutablePair.of(new FilterCMC(3, 5), 9),
ImmutablePair.of(new FilterCMC(6, 20), 3)
);
/**
* <p>
* Constructor for Generate3ColorDeck.
* </p>
*
* @param clr1
* a {@link java.lang.String} object.
* @param clr2
* a {@link java.lang.String} object.
* @param clr3
* a {@link java.lang.String} object.
*/
public DeckGenerator3Color(ICardDatabase cardDb, final String clr1, final String clr2, final String clr3) {
super(cardDb);
int c1 = MagicColor.fromName(clr1);
int c2 = MagicColor.fromName(clr2);
int c3 = MagicColor.fromName(clr3);
int rc = 0;
int combo = c1 | c2 | c3;
ColorSet param = ColorSet.fromMask(combo);
switch(param.countColors()) {
case 3:
colors = param;
return;
case 0:
int color1 = r.nextInt(5);
int color2 = (color1 + 1 + r.nextInt(4)) % 5;
colors = ColorSet.fromMask(MagicColor.WHITE << color1 | MagicColor.WHITE << color2).inverse();
return;
case 1:
do {
rc = MagicColor.WHITE << MyRandom.getRandom().nextInt(5);
} while ( rc == combo );
combo |= rc;
// fall-through
case 2:
do {
rc = MagicColor.WHITE << MyRandom.getRandom().nextInt(5);
} while ( (rc & combo) != 0 );
combo |= rc;
break;
}
colors = ColorSet.fromMask(combo);
}
@Override
public final ItemPoolView<PaperCard> getDeck(final int size, final boolean forAi) {
addCreaturesAndSpells(size, cmcLevels, forAi);
// Add lands
int numLands = Math.round(size * getLandsPercentage());
adjustDeckSize(size - numLands);
tmpDeck.append("numLands:").append(numLands).append("\n");
// Add dual lands
List<String> duals = getDualLandList();
for (String s : duals) {
this.cardCounts.put(s, 0);
}
int dblsAdded = addSomeStr((numLands / 4), duals);
numLands -= dblsAdded;
addBasicLand(numLands);
tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n");
return tDeck;
}
}

View File

@@ -0,0 +1,84 @@
/*
* 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.generation;
import java.util.List;
import org.apache.commons.lang3.tuple.ImmutablePair;
import com.google.common.collect.Lists;
import forge.card.ColorSet;
import forge.card.ICardDatabase;
import forge.item.PaperCard;
import forge.util.ItemPoolView;
/**
* <p>
* Generate5ColorDeck class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class DeckGenerator5Color extends DeckGeneratorBase {
@SuppressWarnings("unchecked")
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
ImmutablePair.of(new FilterCMC(0, 2), 3),
ImmutablePair.of(new FilterCMC(3, 5), 2),
ImmutablePair.of(new FilterCMC(6, 20), 1)
);
// resulting mana curve of the card pool
// 30x 0 - 2
// 20x 3 - 5
// 10x 6 - 20
// =60x - card pool
/**
* Instantiates a new generate5 color deck.
*/
public DeckGenerator5Color(ICardDatabase cardDb) {
super(cardDb);
colors = ColorSet.fromMask(0).inverse();
}
@Override
public final ItemPoolView<PaperCard> getDeck(final int size, final boolean forAi) {
addCreaturesAndSpells(size, cmcLevels, forAi);
// Add lands
int numLands = Math.round(size * getLandsPercentage());
adjustDeckSize(size - numLands);
tmpDeck.append("numLands:").append(numLands).append("\n");
// Add dual lands
List<String> duals = getDualLandList();
for (String s : duals) {
this.cardCounts.put(s, 0);
}
int dblsAdded = addSomeStr((numLands / 4), duals);
numLands -= dblsAdded;
addBasicLand(numLands);
tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n");
return tDeck;
}
}

View File

@@ -0,0 +1,405 @@
/*
* 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.generation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.TreeMap;
import org.apache.commons.lang3.tuple.ImmutablePair;
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.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.card.ColorSet;
import forge.card.ICardDatabase;
import forge.card.MagicColor;
import forge.card.mana.ManaCost;
import forge.item.PaperCard;
import forge.util.Aggregates;
import forge.util.ItemPool;
import forge.util.ItemPoolView;
import forge.util.MyRandom;
/**
* <p>
* Generate2ColorDeck class.
* </p>
*
* @author Forge
* @version $Id: Generate2ColorDeck.java 14959 2012-03-28 14:03:43Z Chris H. $
*/
public abstract class DeckGeneratorBase {
protected final Random r = MyRandom.getRandom();
protected final Map<String, Integer> cardCounts = new HashMap<String, Integer>();
protected int maxDuplicates = 4;
protected boolean useArtifacts = true;
protected ColorSet colors;
protected final ItemPool<PaperCard> tDeck = new ItemPool<PaperCard>(PaperCard.class);
protected final ICardDatabase cardDb;
// 2-colored deck generator has its own constants. The rest works fine with these ones
protected float getLandsPercentage() { return 0.44f; }
protected float getCreatPercentage() { return 0.34f; }
protected float getSpellPercentage() { return 0.22f; }
StringBuilder tmpDeck = new StringBuilder();
public DeckGeneratorBase(ICardDatabase cardDb) {
this.cardDb = cardDb;
}
public void setSingleton(boolean singleton){
this.maxDuplicates = singleton ? 1 : 4;
}
public void setUseArtifacts(boolean value) {
this.useArtifacts = value;
}
protected void addCreaturesAndSpells(int size, List<ImmutablePair<FilterCMC, Integer>> cmcLevels, boolean forAi) {
tmpDeck.append("Building deck of ").append(size).append("cards\n");
final Iterable<PaperCard> cards = selectCardsOfMatchingColorForPlayer(forAi);
// build subsets based on type
final Iterable<PaperCard> creatures = Iterables.filter(cards, Predicates.compose(CardRulesPredicates.Presets.IS_CREATURE, PaperCard.FN_GET_RULES));
final int creatCnt = (int) Math.ceil(getCreatPercentage() * size);
tmpDeck.append("Creatures to add:").append(creatCnt).append("\n");
addCmcAdjusted(creatures, creatCnt, cmcLevels);
Predicate<PaperCard> preSpells = Predicates.compose(CardRulesPredicates.Presets.IS_NONCREATURE_SPELL_FOR_GENERATOR, PaperCard.FN_GET_RULES);
final Iterable<PaperCard> spells = Iterables.filter(cards, preSpells);
final int spellCnt = (int) Math.ceil(getSpellPercentage() * size);
tmpDeck.append("Spells to add:").append(spellCnt).append("\n");
addCmcAdjusted(spells, spellCnt, cmcLevels);
tmpDeck.append(String.format("Current deck size: %d... should be %f%n", tDeck.countAll(), size * (getCreatPercentage() + getSpellPercentage())));
}
public ItemPoolView<PaperCard> getDeck(final int size, final boolean forAi) {
return null; // all but theme deck do override this method
}
protected void addSome(int cnt, List<PaperCard> source) {
for (int i = 0; i < cnt; i++) {
PaperCard cp;
int lc = 0;
int srcLen = source.size();
do {
cp = source.get(this.r.nextInt(srcLen));
lc++;
} while (this.cardCounts.get(cp.getName()) > this.maxDuplicates - 1 && lc <= 100);
if (lc > 100) {
throw new RuntimeException("Generate2ColorDeck : get2ColorDeck -- looped too much -- Cr12");
}
tDeck.add(cp);
final int n = this.cardCounts.get(cp.getName());
this.cardCounts.put(cp.getName(), n + 1);
if( n + 1 == this.maxDuplicates )
source.remove(cp);
tmpDeck.append(String.format("(%d) %s [%s]%n", cp.getRules().getManaCost().getCMC(), cp.getName(), cp.getRules().getManaCost()));
}
}
protected int addSomeStr(int cnt, List<String> source) {
int res = 0;
for (int i = 0; i < cnt; i++) {
String s;
int lc = 0;
do {
s = source.get(this.r.nextInt(source.size()));
lc++;
} 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.
tDeck.add(cardDb.getCard(s, false));
final int n = this.cardCounts.get(s);
this.cardCounts.put(s, n + 1);
tmpDeck.append(s + "\n");
res++;
}
return res;
}
protected void addBasicLand(int cnt) {
tmpDeck.append(cnt).append(" basic lands remain").append("\n");
// attempt to optimize basic land counts according to colors of picked cards
final Map<String, Integer> clrCnts = countLands(tDeck);
// total of all ClrCnts
float totalColor = 0;
for (Entry<String, Integer> c : clrCnts.entrySet()) {
totalColor += c.getValue();
tmpDeck.append(c.getKey()).append(":").append(c.getValue()).append("\n");
}
tmpDeck.append("totalColor:").append(totalColor).append("\n");
int landsLeft = cnt;
for (Entry<String, Integer> c : clrCnts.entrySet()) {
String basicLandName = c.getKey();
// calculate number of lands for each color
final int nLand = Math.min(landsLeft, Math.round(cnt * c.getValue() / totalColor));
tmpDeck.append("nLand-").append(basicLandName).append(":").append(nLand).append("\n");
// just to prevent a null exception by the deck size fixing code
this.cardCounts.put(basicLandName, nLand);
PaperCard cp = cardDb.getCard(basicLandName);
String basicLandSet = cp.getEdition();
tDeck.add(cardDb.getCard(cp.getName(), basicLandSet), nLand);
landsLeft -= nLand;
}
}
protected void adjustDeckSize(int targetSize) {
// fix under-sized or over-sized decks, due to integer arithmetic
int actualSize = tDeck.countAll();
if (actualSize < targetSize) {
final int diff = targetSize - actualSize;
addSome(diff, tDeck.toFlatList());
} else if (actualSize > targetSize) {
Predicate<PaperCard> exceptBasicLand = Predicates.not(Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard.FN_GET_RULES));
for (int i = 0; i < 3 && actualSize > targetSize; i++) {
Iterable<PaperCard> matchingCards = Iterables.filter(tDeck.toFlatList(), exceptBasicLand);
List<PaperCard> toRemove = Aggregates.random(matchingCards, actualSize - targetSize);
tDeck.removeAllFlat(toRemove);
for (PaperCard c : toRemove) {
tmpDeck.append("Removed:").append(c.getName()).append("\n");
}
actualSize = tDeck.countAll();
}
}
}
protected void addCmcAdjusted(Iterable<PaperCard> source, int cnt, List<ImmutablePair<FilterCMC, Integer>> cmcLevels) {
int totalWeight = 0;
for (ImmutablePair<FilterCMC, Integer> pair : cmcLevels) {
totalWeight += pair.getRight();
}
float variability = 0.6f; // if set to 1, you'll get minimum cards to choose from
float desiredWeight = (float)cnt / ( maxDuplicates * variability );
float desiredOverTotal = desiredWeight / totalWeight;
float requestedOverTotal = (float)cnt / totalWeight;
for (ImmutablePair<FilterCMC, Integer> pair : cmcLevels) {
Iterable<PaperCard> matchingCards = Iterables.filter(source, Predicates.compose(pair.getLeft(), PaperCard.FN_GET_RULES));
int cmcCountForPool = (int) Math.ceil(pair.getRight().intValue() * desiredOverTotal);
int addOfThisCmc = Math.round(pair.getRight().intValue() * requestedOverTotal);
tmpDeck.append(String.format("Adding %d cards for cmc range from a pool with %d cards:%n", addOfThisCmc, cmcCountForPool));
final List<PaperCard> curved = Aggregates.random(matchingCards, cmcCountForPool);
final List<PaperCard> curvedRandomized = Lists.newArrayList();
for (PaperCard c : curved) {
this.cardCounts.put(c.getName(), 0);
curvedRandomized.add(cardDb.getCard(c.getName(), false));
}
addSome(addOfThisCmc, curvedRandomized);
}
}
protected Iterable<PaperCard> selectCardsOfMatchingColorForPlayer(boolean forAi) {
// start with all cards
// remove cards that generated decks don't like
Predicate<CardRules> canPlay = forAi ? AI_CAN_PLAY : HUMAN_CAN_PLAY;
Predicate<CardRules> hasColor = new MatchColorIdentity(colors);
if (useArtifacts) {
hasColor = Predicates.or(hasColor, COLORLESS_CARDS);
}
return Iterables.filter(cardDb.getAllCards(), Predicates.compose(Predicates.and(canPlay, hasColor), PaperCard.FN_GET_RULES));
}
protected static Map<String, Integer> countLands(ItemPool<PaperCard> outList) {
// attempt to optimize basic land counts according
// to color representation
Map<String, Integer> res = new TreeMap<String, Integer>();
// count each card color using mana costs
// TODO: count hybrid mana differently?
for (Entry<PaperCard, Integer> cpe : outList) {
int profile = cpe.getKey().getRules().getManaCost().getColorProfile();
if ((profile & MagicColor.WHITE) != 0) {
increment(res, MagicColor.Constant.BASIC_LANDS.get(0), cpe.getValue());
} else if ((profile & MagicColor.BLUE) != 0) {
increment(res, MagicColor.Constant.BASIC_LANDS.get(1), cpe.getValue());
} else if ((profile & MagicColor.BLACK) != 0) {
increment(res, MagicColor.Constant.BASIC_LANDS.get(2), cpe.getValue());
} else if ((profile & MagicColor.RED) != 0) {
increment(res, MagicColor.Constant.BASIC_LANDS.get(3), cpe.getValue());
} else if ((profile & MagicColor.GREEN) != 0) {
increment(res, MagicColor.Constant.BASIC_LANDS.get(4), cpe.getValue());
}
}
return res;
}
protected static void increment(Map<String, Integer> map, String key, int delta)
{
final Integer boxed = map.get(key);
map.put(key, boxed == null ? delta : boxed.intValue() + delta);
}
public static final Predicate<CardRules> AI_CAN_PLAY = new Predicate<CardRules>() {
@Override
public boolean apply(CardRules c) {
return !c.getAiHints().getRemAIDecks() && !c.getAiHints().getRemRandomDecks();
}
};
public static final Predicate<CardRules> HUMAN_CAN_PLAY = new Predicate<CardRules>() {
@Override
public boolean apply(CardRules c) {
return !c.getAiHints().getRemRandomDecks();
}
};
public static final Predicate<CardRules> COLORLESS_CARDS = new Predicate<CardRules>() {
@Override
public boolean apply(CardRules c) {
ManaCost mc = c.getManaCost();
return c.getColorIdentity().isColorless() && !mc.isNoCost();
}
};
public static class MatchColorIdentity implements Predicate<CardRules> {
private final ColorSet allowedColor;
public MatchColorIdentity(ColorSet color) {
allowedColor = color;
}
@Override
public boolean apply(CardRules subject) {
ManaCost mc = subject.getManaCost();
return !mc.isPureGeneric() && allowedColor.containsAllColorsFrom(subject.getColorIdentity().getColor());
//return mc.canBePaidWithAvaliable(allowedColor);
// return allowedColor.containsAllColorsFrom(mc.getColorProfile());
}
}
public static class FilterCMC implements Predicate<CardRules> {
private final int min;
private final int max;
public FilterCMC(int from, int to) {
min = from;
max = to;
}
@Override
public boolean apply(CardRules c) {
ManaCost mc = c.getManaCost();
int cmc = mc.getCMC();
return cmc >= min && cmc <= max && !mc.isNoCost();
}
}
private static Map<Integer, String[]> dualLands = new HashMap<Integer, String[]>();
static {
dualLands.put(MagicColor.WHITE | MagicColor.BLUE, new String[] { "Tundra", "Hallowed Fountain", "Flooded Strand" });
dualLands.put(MagicColor.BLACK | MagicColor.BLUE, new String[] { "Underground Sea", "Watery Grave", "Polluted Delta" });
dualLands.put(MagicColor.BLACK | MagicColor.RED, new String[] { "Badlands", "Blood Crypt", "Bloodstained Mire" });
dualLands.put(MagicColor.GREEN | MagicColor.RED, new String[] { "Taiga", "Stomping Ground", "Wooded Foothills" });
dualLands.put(MagicColor.GREEN | MagicColor.WHITE, new String[] { "Savannah", "Temple Garden", "Windswept Heath" });
dualLands.put(MagicColor.WHITE | MagicColor.BLACK, new String[] { "Scrubland", "Godless Shrine", "Marsh Flats" });
dualLands.put(MagicColor.BLUE | MagicColor.RED, new String[] { "Volcanic Island", "Steam Vents", "Scalding Tarn" });
dualLands.put(MagicColor.BLACK | MagicColor.GREEN, new String[] { "Bayou", "Overgrown Tomb", "Verdant Catacombs" });
dualLands.put(MagicColor.WHITE | MagicColor.RED, new String[] { "Plateau", "Sacred Foundry", "Arid Mesa" });
dualLands.put(MagicColor.GREEN | MagicColor.BLUE, new String[] { "Tropical Island", "Breeding Pool", "Misty Rainforest" });
}
/**
* Get list of dual lands for this color combo.
*
* @param color
* the color
* @return dual land names
*/
protected List<String> getDualLandList() {
final List<String> dLands = new ArrayList<String>();
if (colors.countColors() > 3) {
dLands.add("Rupture Spire");
dLands.add("Undiscovered Paradise");
}
if (colors.countColors() > 2) {
dLands.add("Evolving Wilds");
dLands.add("Terramorphic Expanse");
}
for (Entry<Integer, String[]> dual : dualLands.entrySet()) {
if (colors.hasAllColors(dual.getKey())) {
for (String s : dual.getValue()) {
dLands.add(s);
}
}
}
return dLands;
}
/**
* Get all dual lands that do not match this color combo.
*
* @param color
* the color
* @return dual land names
*/
protected List<String> getInverseDualLandList() {
final List<String> dLands = new ArrayList<String>();
for (Entry<Integer, String[]> dual : dualLands.entrySet()) {
if (!colors.hasAllColors(dual.getKey())) {
for (String s : dual.getValue()) {
dLands.add(s);
}
}
}
return dLands;
}
}

View File

@@ -0,0 +1,98 @@
/*
* 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.generation;
import java.util.List;
import org.apache.commons.lang3.tuple.ImmutablePair;
import com.google.common.collect.Lists;
import forge.card.ColorSet;
import forge.card.ICardDatabase;
import forge.card.MagicColor;
import forge.item.PaperCard;
import forge.util.ItemPoolView;
/**
* <p>
* Generate2ColorDeck class.
* </p>
*
* @author Forge
* @version $Id: Generate2ColorDeck.java 19765 2013-02-20 03:01:37Z myk $
*/
public class DeckGeneratorMonoColor extends DeckGeneratorBase {
@Override protected final float getLandsPercentage() { return 0.39f; }
@Override protected final float getCreatPercentage() { return 0.36f; }
@Override protected final float getSpellPercentage() { return 0.25f; }
@SuppressWarnings("unchecked")
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
ImmutablePair.of(new FilterCMC(0, 2), 10),
ImmutablePair.of(new FilterCMC(3, 4), 8),
ImmutablePair.of(new FilterCMC(5, 6), 5),
ImmutablePair.of(new FilterCMC(7, 20), 3)
);
// mana curve of the card pool
// 20x 0 - 2
// 16x 3 - 4
// 12x 5 - 6
// 4x 7 - 20
// = 52x - card pool (before further random filtering)
/**
* <p>
* Constructor for Generate2ColorDeck.
* </p>
*
* @param clr1
* a {@link java.lang.String} object.
* @param clr2
* a {@link java.lang.String} object.
*/
public DeckGeneratorMonoColor(ICardDatabase cardDb, final String clr1) {
super(cardDb);
if (MagicColor.fromName(clr1) == 0) {
int color1 = r.nextInt(5);
colors = ColorSet.fromMask(MagicColor.WHITE << color1);
} else {
colors = ColorSet.fromNames(clr1);
}
}
@Override
public final ItemPoolView<PaperCard> getDeck(final int size, final boolean forAi) {
addCreaturesAndSpells(size, cmcLevels, forAi);
// Add lands
int numLands = (int) (getLandsPercentage() * size);
tmpDeck.append("numLands:").append(numLands).append("\n");
addBasicLand(numLands);
tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n");
adjustDeckSize(size);
tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n");
return tDeck;
}
}

View File

@@ -0,0 +1,3 @@
/** Forge Card Game. */
package forge.deck.generation;

View File

@@ -23,7 +23,6 @@ import java.util.TreeSet;
import org.apache.commons.lang3.StringUtils;
import forge.deck.DeckFormat;
import forge.game.player.PlayerType;
import forge.util.FileSection;
/**
@@ -48,7 +47,6 @@ public class DeckFileHeader {
private static final String PLAYER_TYPE = "PlayerType";
private final DeckFormat deckType;
private final PlayerType playerType;
private final boolean customPool;
private final String name;
@@ -56,6 +54,15 @@ public class DeckFileHeader {
private final Set<String> tags;
private final boolean intendedForAi;
/**
* @return the intendedForAi
*/
public boolean isIntendedForAi() {
return intendedForAi;
}
/**
* TODO: Write javadoc for Constructor.
*
@@ -67,8 +74,7 @@ public class DeckFileHeader {
this.comment = kvPairs.get(DeckFileHeader.COMMENT);
this.deckType = DeckFormat.smartValueOf(kvPairs.get(DeckFileHeader.DECK_TYPE), DeckFormat.Constructed);
this.customPool = kvPairs.getBoolean(DeckFileHeader.CSTM_POOL);
boolean isForAi = "computer".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER)) || "ai".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER_TYPE));
this.playerType = isForAi ? PlayerType.COMPUTER : PlayerType.HUMAN;
this.intendedForAi = "computer".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER)) || "ai".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER_TYPE));
this.tags = new TreeSet<String>();
String rawTags = kvPairs.get(DeckFileHeader.TAGS);
@@ -81,15 +87,6 @@ public class DeckFileHeader {
}
/**
* Gets the player type.
*
* @return the player type
*/
public final PlayerType getPlayerType() {
return this.playerType;
}
/**
* Checks if is custom pool.
*

View 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);
}
}

View File

@@ -0,0 +1,8 @@
/**
*
*/
/**
* @author Max
*
*/
package forge.deck.io;

View File

@@ -0,0 +1,8 @@
/**
*
*/
/**
* @author Max
*
*/
package forge.deck;

View File

@@ -20,26 +20,25 @@ package forge.item;
import com.google.common.base.Function;
import forge.Singletons;
import forge.StaticData;
import forge.card.CardEdition;
import forge.card.SealedProductTemplate;
import forge.util.MyRandom;
public class BoosterPack extends OpenablePack {
public class BoosterPack extends SealedProduct {
private final int artIndex;
private final int hash;
public static final Function<CardEdition, BoosterPack> FN_FROM_SET = new Function<CardEdition, BoosterPack>() {
@Override
public BoosterPack apply(final CardEdition arg1) {
SealedProductTemplate d = Singletons.getModel().getBoosters().get(arg1.getCode());
Template d = StaticData.instance().getBoosters().get(arg1.getCode());
return new BoosterPack(arg1.getName(), d);
}
};
public BoosterPack(final String name0, final SealedProductTemplate boosterData) {
public BoosterPack(final String name0, final Template boosterData) {
super(name0, boosterData);
int maxIdx = Singletons.getModel().getEditions().get(boosterData.getEdition()).getCntBoosterPictures();
int maxIdx = StaticData.instance().getEditions().get(boosterData.getEdition()).getCntBoosterPictures();
artIndex = MyRandom.getRandom().nextInt(maxIdx) + 1;
hash = super.hashCode() ^ artIndex;
}
@@ -58,7 +57,7 @@ public class BoosterPack extends OpenablePack {
return new BoosterPack(name, contents);
}
public SealedProductTemplate getBoosterData() {
public Template getBoosterData() {
return contents;
}

View 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();
}
}
}

View File

@@ -9,10 +9,9 @@ import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import forge.Card;
//import forge.Card;
import forge.card.CardRarity;
import forge.card.CardRules;
import forge.game.player.Player;
import forge.util.PredicateString;
public interface IPaperCard extends InventoryItem {
@@ -161,7 +160,4 @@ public interface IPaperCard extends InventoryItem {
public abstract String getItemType();
public abstract Card getMatchingForgeCard();
public abstract Card toForgeCard(Player owner);
}

View File

@@ -17,19 +17,14 @@
*/
package forge.item;
import forge.util.IHasName;
/**
* Interface to define a player's inventory may hold. Should include
* CardPrinted, Booster, Pets, Plants... etc
*/
public interface InventoryItem {
/**
* An inventory item has to provide a name.
*
* @return the name
*/
String getName();
public interface InventoryItem extends IHasName
{
/**
* Return type as a string.
*

View File

@@ -17,16 +17,10 @@
*/
package forge.item;
import java.util.HashMap;
import java.util.Map;
import com.google.common.base.Function;
import forge.Card;
import forge.card.CardRarity;
import forge.card.CardRules;
import forge.card.cardfactory.CardFactory;
import forge.game.player.Player;
/**
@@ -40,7 +34,7 @@ import forge.game.player.Player;
*/
public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet, IPaperCard {
// Reference to rules
private final transient CardRules card;
private final transient CardRules rules;
// These fields are kinda PK for PrintedCard
public final String name;
@@ -78,7 +72,7 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
@Override
public CardRules getRules() {
return this.card;
return this.rules;
}
@Override
@@ -86,15 +80,11 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
return this.rarity;
}
// @Override
// public String getImageKey() {
// return getImageLocator(getImageName(), getArtIndex(), true, false);
// }
@Override
public String getItemType() {
return "Card";
@@ -106,7 +96,7 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
public static final Function<PaperCard, CardRules> FN_GET_RULES = new Function<PaperCard, CardRules>() {
@Override
public CardRules apply(final PaperCard from) {
return from.card;
return from.rules;
}
};
public static final Function<PaperCard, String> FN_GET_NAME = new Function<PaperCard, String>() {
@@ -121,7 +111,9 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
}
public PaperCard(final CardRules c, final String edition0, final CardRarity rare, final int index, final boolean foil) {
this.card = c;
if ( edition0 == null || c == null || rare == null )
throw new IllegalArgumentException("Cannot create card without rules, edition or rarity");
this.rules = c;
this.name = c.getName();
this.edition = edition0;
this.artIndex = index;
@@ -129,10 +121,6 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
this.rarity = rare;
}
public static PaperCard makeFoiled(final PaperCard c) {
return new PaperCard(c.card, c.edition, c.rarity, c.artIndex, true);
}
// Want this class to be a key for HashTable
@Override
public boolean equals(final Object obj) {
@@ -186,34 +174,6 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
// return String.format("%s|%s", name, cardSet);
}
/**
* To forge card.
*
* @return the card
*/
private static final Map<PaperCard, Card> cp2card = new HashMap<PaperCard, Card>();
/* (non-Javadoc)
* @see forge.item.ICardPrinted#getMatchingForgeCard()
*/
@Override
public Card getMatchingForgeCard() {
Card res = cp2card.get(this);
if (null == res) {
res = toForgeCard(null);
cp2card.put(this, res);
}
return res;
}
/* (non-Javadoc)
* @see forge.item.ICardPrinted#toForgeCard(forge.game.player.Player)
*/
@Override
public Card toForgeCard(Player owner) {
final Card c = CardFactory.getCard(this, owner);
return c;
}
/*
* (non-Javadoc)
*

View File

@@ -2,12 +2,10 @@ package forge.item;
import java.util.Locale;
import forge.Card;
import forge.card.CardEdition;
import forge.card.CardRarity;
import forge.card.CardRules;
import forge.card.cardfactory.CardFactory;
import forge.game.player.Player;
public class PaperToken implements InventoryItemFromSet, IPaperCard {
private String name;
@@ -61,13 +59,6 @@ public class PaperToken implements InventoryItemFromSet, IPaperCard {
public String getImageFilename() { return imageFileName; }
@Override public String getItemType() { return "Token"; }
@Override public Card getMatchingForgeCard() { return toForgeCard(null); } // hope this won't be queried too frequently, so no cache
@Override
public Card toForgeCard(Player owner) {
final Card c = CardFactory.getCard(this, owner);
return c;
}
@Override public boolean isToken() { return true; }
}

View File

@@ -0,0 +1,149 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Nate
*
* 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.io.FilenameFilter;
import java.util.List;
import java.util.Map;
import com.google.common.base.Function;
import forge.StaticData;
import forge.deck.Deck;
import forge.deck.io.DeckSerializer;
import forge.util.FileSection;
import forge.util.FileUtil;
import forge.util.storage.StorageReaderFolder;
/**
* TODO: Write javadoc for this type.
*
*/
public class PreconDeck implements InventoryItemFromSet {
private final Deck deck;
private final String set;
private final String description;
private String imageFilename;
// private final SellRules recommendedDeals;
/*
* (non-Javadoc)
*
* @see forge.item.InventoryItemFromSet#getName()
*/
@Override
public String getName() {
return this.deck.getName();
}
/*
* (non-Javadoc)
*
* @see forge.item.InventoryItem#getType()
*/
@Override
public String getItemType() {
return "Prebuilt Deck";
}
public PreconDeck(final Deck d, String set, String description) {
deck = d;
this.set = set;
this.description = description;
}
public final Deck getDeck() {
return this.deck;
}
/**
* Gets the recommended deals.
*
* @return the recommended deals
*/
// public final SellRules getRecommendedDeals() {
// return this.recommendedDeals;
// }
public final String getImageFilename() {
return imageFilename;
}
/*
* (non-Javadoc)
*
* @see forge.item.InventoryItemFromSet#getSet()
*/
@Override
public String getEdition() {
return this.set;
}
/**
* Gets the description.
*
* @return the description
*/
public final String getDescription() {
return this.description;
}
public static final Function<PreconDeck, String> FN_NAME_SELECTOR = new Function<PreconDeck, String>() {
@Override
public String apply(PreconDeck arg1) {
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;
}
}
}

View 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]));
}
}
}
}

View File

@@ -21,23 +21,22 @@ import java.util.List;
import com.google.common.base.Function;
import forge.Singletons;
import forge.StaticData;
import forge.card.BoosterGenerator;
import forge.card.CardEdition;
import forge.card.SealedProductTemplate;
public class TournamentPack extends OpenablePack {
public class TournamentPack extends SealedProduct {
/** The Constant fnFromSet. */
public static final Function<CardEdition, TournamentPack> FN_FROM_SET = new Function<CardEdition, TournamentPack>() {
@Override
public TournamentPack apply(final CardEdition arg1) {
SealedProductTemplate d = Singletons.getModel().getTournamentPacks().get(arg1.getCode());
Template d = StaticData.instance().getTournamentPacks().get(arg1.getCode());
return new TournamentPack(arg1.getName(), d);
}
};
public TournamentPack(final String name0, final SealedProductTemplate boosterData) {
public TournamentPack(final String name0, final Template boosterData) {
super(name0, boosterData);
}

View File

@@ -0,0 +1,8 @@
/**
*
*/
/**
* @author Max
*
*/
package forge.item;

View File

@@ -0,0 +1,8 @@
/**
*
*/
/**
* @author Max
*
*/
package forge;

View File

@@ -1,4 +1,4 @@
package forge.util.maps;
package forge.util;
import java.util.ArrayList;
import java.util.HashSet;

View File

@@ -31,8 +31,6 @@ import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import forge.error.BugReporter;
/**
* <p>
* FileUtil class.
@@ -47,6 +45,18 @@ public final class FileUtil {
throw new AssertionError();
}
/**
* Takes two paths and combines them into a valid path string
* for the current OS.
* <p>
* Similar to the Path.Combine() function in .Net.
*/
public static String pathCombine (String path1, String path2) {
File file1 = new File(path1);
File file2 = new File(file1, path2);
return file2.getPath();
}
/**
* <p>
* doesFileExist.
@@ -97,17 +107,12 @@ public final class FileUtil {
}
p.close();
} catch (final Exception ex) {
BugReporter.reportException(ex);
throw new RuntimeException("FileUtil : writeFile() error, problem writing file - " + file + " : " + ex);
}
} // writeAllDecks()
public static String readFileToString(String filename) {
StringBuilder s = new StringBuilder();
for (String line : readFile(filename)) {
s.append(line).append('\n');
}
return s.toString();
return TextUtil.join(readFile(filename), "\n");
}
public static List<String> readFile(final String filename) {
@@ -133,7 +138,6 @@ public final class FileUtil {
}
return FileUtil.readAllLines(new FileReader(file), false);
} catch (final Exception ex) {
BugReporter.reportException(ex);
throw new RuntimeException("FileUtil : readFile() error, " + ex);
}
} // readFile()
@@ -168,7 +172,6 @@ public final class FileUtil {
}
in.close();
} catch (final IOException ex) {
BugReporter.reportException(ex);
throw new RuntimeException("FileUtil : readAllLines() error, " + ex);
}
return list;

View File

@@ -0,0 +1,9 @@
package forge.util;
/**
* TODO: Write javadoc for this type.
*
*/
public interface IHasName {
String getName();
}

View File

@@ -17,6 +17,7 @@
*/
package forge.util;
import java.io.File;
import java.util.Map;
/**
@@ -41,4 +42,8 @@ public interface IItemReader<T> {
* @return the item key
*/
String getItemKey(T item);
Iterable<File> getSubFolders();
IItemReader<T> getReaderForFolder(File subfolder);
}

View File

@@ -17,6 +17,8 @@
*/
package forge.util;
import java.io.File;
/**
* TODO: Write javadoc for this type.
*
@@ -37,4 +39,7 @@ public interface IItemSerializer<T> extends IItemReader<T> {
* @param unit the unit
*/
void erase(T unit);
File getDirectory();
}

View File

@@ -15,16 +15,18 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.item;
package forge.util;
import java.util.Collections;
import java.util.Map.Entry;
import forge.item.InventoryItem;
/**
* <p>
* CardPool class.
* ItemPool class.
* </p>
* Represents a list of cards with amount of each
* Represents a list of items with amount of each
*
* @param <T>
* an Object
@@ -82,59 +84,59 @@ public class ItemPool<T extends InventoryItem> extends ItemPoolView<T> {
* @return a ItemPoolView
*/
public ItemPoolView<T> getView() {
return new ItemPoolView<T>(Collections.unmodifiableMap(this.getCards()), this.getMyClass());
return new ItemPoolView<T>(Collections.unmodifiableMap(this.getItems()), this.getMyClass());
}
// Cards manipulation
// Items manipulation
/**
*
* Add Card.
* Add a single item.
*
* @param card
* @param item
* a T
*/
public void add(final T card) {
this.add(card, 1);
public void add(final T item) {
this.add(item, 1);
}
/**
*
* add method.
* Add multiple items.
*
* @param card
* @param item
* a T
* @param amount
* a int
*/
public void add(final T card, final int amount) {
public void add(final T item, final int amount) {
if (amount <= 0) {
return;
}
this.getCards().put(card, Integer.valueOf(this.count(card) + amount));
this.setListInSync(false);
this.getItems().put(item, Integer.valueOf(this.count(item) + amount));
this.isListInSync = false;
}
private void put(final T card, final int amount) {
this.getCards().put(card, amount);
this.setListInSync(false);
private void put(final T item, final int amount) {
this.getItems().put(item, amount);
this.isListInSync = false;
}
/**
* addAllCards.
* addAllFlat.
*
* @param <U>
* a InventoryItem
* @param cards
* @param items
* a Iterable<U>
*/
@SuppressWarnings("unchecked")
public <U extends InventoryItem> void addAllFlat(final Iterable<U> cards) {
for (final U cr : cards) {
public <U extends InventoryItem> void addAllFlat(final Iterable<U> items) {
for (final U cr : items) {
if (this.getMyClass().isInstance(cr)) {
this.add((T) cr);
}
}
this.setListInSync(false);
this.isListInSync = false;
}
/**
@@ -153,40 +155,40 @@ public class ItemPool<T extends InventoryItem> extends ItemPoolView<T> {
this.add((T) e.getKey(), e.getValue());
}
}
this.setListInSync(false);
this.isListInSync = false;
}
/**
*
* Remove.
*
* @param card
* @param item
* a T
*/
public boolean remove(final T card) {
return this.remove(card, 1);
public boolean remove(final T item) {
return this.remove(item, 1);
}
/**
*
* Remove.
*
* @param card
* @param item
* a T
* @param amount
* a int
*/
public boolean remove(final T card, final int amount) {
final int count = this.count(card);
public boolean remove(final T item, final int amount) {
final int count = this.count(item);
if ((count == 0) || (amount <= 0)) {
return false;
}
if (count <= amount) {
this.getCards().remove(card);
this.getItems().remove(item);
} else {
this.getCards().put(card, count - amount);
this.getItems().put(item, count - amount);
}
this.setListInSync(false);
this.isListInSync = false;
return true;
}
@@ -221,7 +223,7 @@ public class ItemPool<T extends InventoryItem> extends ItemPoolView<T> {
* Clear.
*/
public void clear() {
this.getCards().clear();
this.setListInSync(false);
this.getItems().clear();
this.isListInSync = false;
}
}

View File

@@ -0,0 +1,87 @@
/*
* 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.util;
import java.util.Comparator;
import java.util.Map.Entry;
import com.google.common.base.Function;
import forge.item.PaperCard;
/**
* <p>
* TableSorter class.
* </p>
*
* @param <T>
* the generic type
* @author Forge
* @version $Id: TableSorter.java 21966 2013-06-05 06:58:32Z Max mtg $
*/
@SuppressWarnings("unchecked")
// Comparable needs <type>
public class ItemPoolSorter<T> implements Comparator<Entry<T, Integer>> {
private final boolean ascending;
private final Function<Entry<T, Integer>, Comparable<?>> field;
/**
* <p>
* Constructor for TableSorter.
* </p>
*
* @param field
* the field
* @param inAscending
* a boolean.
*/
public ItemPoolSorter(final Function<Entry<T, Integer>, Comparable<?>> field, final boolean inAscending) {
this.field = field;
this.ascending = inAscending;
}
/** The Constant byNameThenSet. */
public static final ItemPoolSorter<PaperCard> BY_NAME_THEN_SET = new ItemPoolSorter<PaperCard>(
new Function<Entry<PaperCard, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<PaperCard, Integer> from) {
return from.getKey();
}
}, true);
/*
* (non-Javadoc)
*
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
@SuppressWarnings("rawtypes")
@Override
public final int compare(final Entry<T, Integer> arg0, final Entry<T, Integer> arg1) {
final Comparable obj1 = this.field.apply(arg0);
final Comparable obj2 = this.field.apply(arg1);
if (obj1 == null) {
return -1;
}
if (obj2 == null) {
return 1;
}
//System.out.println(String.format("%s vs %s _______ %s vs %s", arg0, arg1, obj1, obj2));
return this.ascending ? obj1.compareTo(obj2) : obj2.compareTo(obj1);
}
}

View File

@@ -0,0 +1,256 @@
/*
* 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.util;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import forge.item.InventoryItem;
/**
* <p>
* ItemPoolView class.
* </p>
*
* @param <T>
* an InventoryItem
* @author Forge
* @version $Id: ItemPoolView.java 9708 2011-08-09 19:34:12Z jendave $
*/
public class ItemPoolView<T extends InventoryItem> implements Iterable<Entry<T, Integer>> {
/** The fn to printed. */
public final transient Function<Entry<T, Integer>, T> FN_GET_KEY = new Function<Entry<T, Integer>, T>() {
@Override
public T apply(final Entry<T, Integer> from) {
return from.getKey();
}
};
/** The fn to item name. */
public final transient Function<Entry<T, Integer>, String> FN_GET_NAME = new Function<Entry<T, Integer>, String>() {
@Override
public String apply(final Entry<T, Integer> from) {
return from.getKey().getName();
}
};
/** The fn to count. */
public final transient Function<Entry<T, Integer>, Integer> FN_GET_COUNT = new Function<Entry<T, Integer>, Integer>() {
@Override
public Integer apply(final Entry<T, Integer> from) {
return from.getValue();
}
};
// Constructors
public ItemPoolView(final Class<T> cls) {
this(new Hashtable<T, Integer>(), cls);
}
public ItemPoolView(final Map<T, Integer> inMap, final Class<T> cls) {
this.items = inMap;
this.myClass = cls;
}
// Data members
/** The items. */
private final Map<T, Integer> items;
/** The my class. */
private final Class<T> myClass; // class does not keep this in runtime by
// itself
// same thing as above, it was copied to provide sorting (needed by table
// views in deck editors)
/** The items ordered. */
private final transient List<Entry<T, Integer>> itemsOrdered = new ArrayList<Map.Entry<T, Integer>>();
/** Whether list is in sync. */
protected transient boolean isListInSync = false;
/**
* iterator.
*
* @return Iterator<Entry<T, Integer>>
*/
@Override
public final Iterator<Entry<T, Integer>> iterator() {
return this.items.entrySet().iterator();
}
// Items read only operations
/**
*
* contains.
*
* @param item
* a T
* @return boolean
*/
public final boolean contains(final T item) {
if (this.items == null) {
return false;
}
return this.items.containsKey(item);
}
/**
*
* count.
*
* @param item
* a T
* @return int
*/
public final int count(final T item) {
if (this.items == null) {
return 0;
}
final Integer boxed = this.items.get(item);
return boxed == null ? 0 : boxed.intValue();
}
/**
*
* countAll.
*
* @return int
*/
public final int countAll() {
return countAll(null, myClass);
}
public final int countAll(Predicate<T> condition) {
return countAll(condition, myClass);
}
public final <U extends InventoryItem> int countAll(Predicate<U> condition, Class<U> cls) {
int result = 0;
if (this.items != null) {
final boolean isSameClass = cls == myClass;
for (final Entry<T, Integer> kv : this) {
final T key = kv.getKey();
@SuppressWarnings("unchecked")
final U castKey = isSameClass || cls.isInstance(key) ? (U)key : null;
if (null == condition || castKey != null && condition.apply(castKey))
result += kv.getValue();
}
}
return result;
}
/**
*
* countDistinct.
*
* @return int
*/
public final int countDistinct() {
return this.items.size();
}
/**
*
* isEmpty.
*
* @return boolean
*/
public final boolean isEmpty() {
return (this.items == null) || this.items.isEmpty();
}
/**
*
* getOrderedList.
*
* @return List<Entry<T, Integer>>
*/
public final List<Entry<T, Integer>> getOrderedList() {
if (!this.isListInSync) {
this.rebuildOrderedList();
}
return this.itemsOrdered;
}
private void rebuildOrderedList() {
this.itemsOrdered.clear();
if (this.items != null) {
for (final Entry<T, Integer> e : this.items.entrySet()) {
this.itemsOrdered.add(e);
}
}
this.isListInSync = true;
}
/**
*
* toFlatList.
*
* @return List<T>
*/
public final List<T> toFlatList() {
final List<T> result = new ArrayList<T>();
for (final Entry<T, Integer> e : this) {
for (int i = 0; i < e.getValue(); i++) {
result.add(e.getKey());
}
}
return result;
}
/**
* Gets the items.
*
* @return the items
*/
protected Map<T, Integer> getItems() {
return this.items;
}
/**
* Gets the my class.
*
* @return the myClass
*/
public Class<T> getMyClass() {
return this.myClass;
}
/**
* To item list string.
*
* @return the iterable
*/
public Iterable<String> toItemListString() {
final List<String> list = new ArrayList<String>();
for (final Entry<T, Integer> e : this.items.entrySet()) {
list.add(String.format("%d x %s", e.getValue(), e.getKey().getName()));
}
return list;
}
}

View File

@@ -0,0 +1,134 @@
package forge.util;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
/**
* TODO: Write javadoc for this type.
*
*/
public class Lang {
/**
* TODO: Write javadoc for this method.
* @param position
* @return
*/
public static String getOrdinal(int position) {
String[] sufixes = new String[] { "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" };
switch (position % 100) {
case 11:
case 12:
case 13:
return position + "th";
default:
return position + sufixes[position % 10];
}
}
public static <T> String joinHomogenous(String s1, String s2) {
boolean has1 = StringUtils.isNotBlank(s1);
boolean has2 = StringUtils.isNotBlank(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(Collection<T> objects) { return joinHomogenous(objects, null, "and"); }
public static <T> String joinHomogenous(Collection<T> objects, Function<T, String> accessor) {
return joinHomogenous(objects, accessor, "and");
}
public static <T> String joinHomogenous(Collection<T> objects, Function<T, String> accessor, String lastUnion) {
int remaining = objects.size();
StringBuilder sb = new StringBuilder();
for(T obj : objects) {
remaining--;
if( accessor != null )
sb.append(accessor.apply(obj));
else
sb.append(obj);
if( remaining > 1 ) sb.append(", ");
if( remaining == 1 ) sb.append(" ").append(lastUnion).append(" ");
}
return sb.toString();
}
public static <T> String joinVerb(List<T> subjects, String verb) {
return subjects.size() > 1 || !subjectIsSingle3rdPerson(Iterables.getFirst(subjects, "it").toString()) ? verb : verbs3rdPersonSingular(verb);
}
public static String joinVerb(String subject, String verb) {
return !Lang.subjectIsSingle3rdPerson(subject) ? verb : verbs3rdPersonSingular(verb);
}
public static boolean subjectIsSingle3rdPerson(String subject) {
// Will be most simple
return !"You".equalsIgnoreCase(subject);
}
public static String verbs3rdPersonSingular(String verb) {
// English is simple - just add (s) for multiple objects.
return verb + "s";
}
public static String getPlural(String noun) {
return noun + ( noun.endsWith("s") || noun.endsWith("x") ? "es" : "s");
}
public static <T> String nounWithAmount(int cnt, String noun) {
String countedForm = cnt <= 1 ? noun : getPlural(noun);
final String strCount;
if( cnt == 1 )
strCount = startsWithVowel(noun) ? "an " : "a ";
else
strCount = String.valueOf(cnt) + " ";
return strCount + countedForm;
}
public static <T> String nounWithNumeral(int cnt, String noun) {
String countedForm = cnt <= 1 ? noun : getPlural(noun);
return getNumeral(cnt) + " " + countedForm;
}
public static String getPossesive(String name) {
if ("You".equalsIgnoreCase(name)) return name + "r"; // to get "your"
return name.endsWith("s") ? name + "'" : name + "'s";
}
public static boolean startsWithVowel(String word) {
return isVowel(word.trim().charAt(0));
}
private static final char[] vowels = { 'a', 'i', 'e', 'o', 'u' };
public static boolean isVowel(char letter) {
char l = Character.toLowerCase(letter);
for(char c : vowels)
if ( c == l ) return true;
return false;
}
public final static String[] numbers0 = new String[] {
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
"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 static String getNumeral(int n) {
String prefix = n < 0 ? "minus " : "";
n = Math.abs(n);
if ( n >= 0 && n < 20 )
return prefix + numbers0[n];
if ( n < 100 ) {
int n1 = n % 10;
String ones = n1 == 0 ? "" : numbers0[n1];
return prefix + numbers20[(n / 10) - 2] + " " + ones;
}
return Integer.toString(n);
}
}

View File

@@ -99,6 +99,17 @@ public class TextUtil {
return trimParenthesis ? StringUtils.stripAll(toReturn, String.valueOf(openPar)) : toReturn;
}
public static String join(Iterable<String> strs, String delim) {
StringBuilder sb = new StringBuilder();
for (String str : strs) {
if (sb.length() > 0) {
sb.append(delim);
}
sb.append(str);
}
return sb.toString();
}
/**
* Converts an enum value to a printable label but upcasing the first letter
* and lcasing all subsequent letters

View File

@@ -0,0 +1,54 @@
package forge.util;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
public class ThreadUtil {
static {
System.out.printf("(ThreadUtil first call): Running on a machine with %d cpu core(s)%n", Runtime.getRuntime().availableProcessors() );
}
private static class WorkerThreadFactory implements ThreadFactory {
private int countr = 0;
private String prefix = "";
public WorkerThreadFactory(String prefix) {
this.prefix = prefix;
}
public Thread newThread(Runnable r) {
return new Thread(r, prefix + "-" + countr++);
}
}
private final static ExecutorService gameThreadPool = Executors.newCachedThreadPool(new WorkerThreadFactory("Game"));
private static ExecutorService getGameThreadPool() { return gameThreadPool; }
private final static ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2, new WorkerThreadFactory("Delayed"));
private static ScheduledExecutorService getScheduledPool() { return scheduledPool; }
// This pool is designed to parallel CPU or IO intensive tasks like parse cards or download images, assuming a load factor of 0.5
public final static ExecutorService getComputingPool(float loadFactor) {
return Executors.newFixedThreadPool((int)(Runtime.getRuntime().availableProcessors() / (1-loadFactor)));
}
public static boolean isMultiCoreSystem() {
return Runtime.getRuntime().availableProcessors() > 1;
}
public static void invokeInGameThread(Runnable toRun) {
getGameThreadPool().execute(toRun);
}
public static void delay(int milliseconds, Runnable inputUpdater) {
getScheduledPool().schedule(inputUpdater, milliseconds, TimeUnit.MILLISECONDS);
}
public static boolean isGameThread() {
return Thread.currentThread().getName().startsWith("Game");
}
}

View File

@@ -0,0 +1,8 @@
/**
*
*/
/**
* @author Max
*
*/
package forge.util;

View File

@@ -0,0 +1,49 @@
/*
* 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.util.storage;
import java.util.Collection;
import com.google.common.base.Predicate;
import forge.util.IHasName;
/**
* TODO: Write javadoc for this type.
*
* @param <T> the generic type
*/
public interface IStorage<T> extends Iterable<T>, IHasName {
T get(final String name);
T find(final Predicate<T> condition);
// todo: find(final Predicate<T> condition, boolean recursive).
Collection<String> getItemNames();
boolean contains(final String name);
int size();
void add(final T deck);
void delete(final String deckName);
IStorage<IStorage<T>> getFolders();
}

Some files were not shown because too many files have changed in this diff Show More