Compare commits

..

6340 Commits

Author SHA1 Message Date
Chris
a42465e9ca [maven-release-plugin] prepare release forge-1.5.35 2015-02-14 15:42:09 +00:00
Chris
0351efcc19 Preparing the changes.txt file for the next beta build and release. 2015-02-14 15:38:15 +00:00
Myrd
ed9bc163cf Optimize replacement effect lookup during AI calculating mana. 2015-02-14 15:06:14 +00:00
excessum
da74a6f70a - Fixed bug with the AI treating spells with DamageDeal SubAbility that can target players as free pings 2015-02-14 11:51:44 +00:00
Agetian
c256b29ce6 - Fix the triggered abilities still visually appearing when suppressed (e.g. with Humility). 2015-02-14 11:21:04 +00:00
Hellfish
25da751464 *Added a few provisions for Tiny Leaders 2015-02-14 09:54:14 +00:00
Agetian
17e768e85c - Fixed compilation of mobile version of Forge. 2015-02-14 09:52:54 +00:00
Hellfish
8e62e17f65 *Made Delved cards not exile until cost is fully paid 2015-02-14 09:09:04 +00:00
elcnesh
e0e38b6cc4 Add cleanup do Kheru Dreadmaw. 2015-02-14 08:38:37 +00:00
elcnesh
a6bcd59819 Fix static abilities not removing triggers. 2015-02-14 08:26:27 +00:00
excessum
8688494718 - Fixed AI for Polukranos, World Eater 2015-02-14 08:08:48 +00:00
Myrd
35881d5cf0 Switch ConcurrentSkipListMap to TreeMap, as ConcurrentSkipListMap.isEmpty() showed up in profiles and these collections aren't meant to be manipulated concurrently. 2015-02-14 07:34:22 +00:00
Myrd
b9d9678e56 Avoid double look up in map. 2015-02-14 07:18:03 +00:00
Myrd
9f03746360 Optimize static effect checks even more based on profiling. 2015-02-14 07:09:05 +00:00
Myrd
5d6f5912e3 Cache trigger constructor instead of looking it up each time createTrigger is called. This was showing up in profiles of simulation code. 2015-02-14 06:57:15 +00:00
Myrd
8aae10fedd Fix Simulation AI not being able to target some permanent types. 2015-02-14 05:59:26 +00:00
excessum
dd28144134 - Fixed AI for Chained to the Rocks 2015-02-14 03:11:12 +00:00
Myrd
b131f59976 Fix NPE with empty stack. 2015-02-13 05:41:40 +00:00
Myrd
cad21523ff Fix index out of bounds with multiple targets. 2015-02-13 05:24:25 +00:00
Myrd
edbbc582c7 Fix game copy error with monstrous with a test. 2015-02-13 05:17:22 +00:00
Myrd
0d748ed593 Don't recurse if the game is already over. 2015-02-13 04:58:13 +00:00
Myrd
2f161224b2 Simulation AI: Implement looking ahead more than one move. This allows, for example, choosing the SpellAbility to use a fetchland to get the right type of mana in order to play another spell in hand, just from simulation.
This is an initial implementation with a max recursion depth of 5.

There are many improvements that can be made - for example to speed it up, by caching the planned SA chain - so that (if things are going to plan), the chain doesn't have to be recomputed each time.

Also, the AI doesn't currently simulated both types of decisions for a fetchland (i.e. evaluate difference between fetching a Plains vs. a Forest) - it picks one arbitrarily, which sometimes causes it to miss better plays. This needs to be fixed.
2015-02-13 04:52:08 +00:00
Myrd
43005bc1e4 Copy cards in command zone too. 2015-02-13 04:15:01 +00:00
Sol
73f0377778 - Fix type of Write into Being 2015-02-13 03:17:19 +00:00
Hellfish
0c45c6ce09 *AFAICT fixed Delve-ing other players' cards. 2015-02-12 23:00:18 +00:00
Hellfish
3127b380a4 *Fixed The Fourth Sphere token amount 2015-02-12 18:15:24 +00:00
Myrd
b138ec3e1d Make CreatureEvaluator implement Function, so that a separate class isn't needed for that. 2015-02-12 05:11:55 +00:00
Myrd
5617b87c28 Re-enable test now that it's fixed. 2015-02-12 04:44:08 +00:00
drdev
15e0d372fb Update Pro Tour link 2015-02-10 15:30:06 +00:00
drdev
9e03f047a9 Update Net decks urls 2015-02-10 15:16:26 +00:00
drdev
b6f69b0762 Fix issue blocking compile of mobile app 2015-02-10 14:54:00 +00:00
Sloth
aa4ffd5551 - Added the quest decks Dracula 3 (by tojammot) and Sidisi 2. 2015-02-09 20:05:33 +00:00
Sloth
042a49aef6 - Fixed Layer of static abilities granting hidden keywords (part 3). 2015-02-09 18:46:22 +00:00
Sloth
286d065913 - Fixed Layer of static abilities granting hidden keywords (part 2). 2015-02-09 08:17:44 +00:00
Myrd
e89324537c Tweak eval scoring for cards in hand and life for Simulated AI. 2015-02-08 20:38:41 +00:00
Myrd
1963cc94ad Fix simulated AI finding wrong card in hand when simulating and add a test. 2015-02-08 20:21:23 +00:00
Myrd
2dc5d6da09 Consider planeswalkers with more loyalty counters better, so that AI will activate Liliana's discard ability even if opponent has no cards in hand. 2015-02-08 20:03:12 +00:00
Myrd
2afff9c9c0 Make game state save/restore also affect command zone. 2015-02-08 19:58:05 +00:00
Myrd
457636f2e3 Make simulated AI ignore temp power/toughness boosts in certain cases when evaluating. (Initial version - can be made quite a bit smarter based on this later.) 2015-02-08 19:43:40 +00:00
Sloth
34e4c5bdf9 - Updated some quest decks. 2015-02-08 19:33:54 +00:00
Myrd
2766caec2c Fix simulation of unmorph abilities that don't use the stack, with a test.
Also, disables a test that started to fail for some reason. Will investigate why it's failing after this commit.
2015-02-08 18:08:51 +00:00
Myrd
188ff29384 Remove println. 2015-02-08 17:50:15 +00:00
Myrd
ff18cb74c8 Fix dumping and restoring game state with morphed creatures. 2015-02-08 17:43:09 +00:00
Sloth
019a241184 - Fixed Layer of static abilities granting hidden keywords. 2015-02-08 14:37:34 +00:00
Sloth
fde826e2d9 - The trigger of Sepulchral Primordial is now optional. 2015-02-08 14:34:09 +00:00
Sloth
85f33fd336 - Fixed Ruthless Instincts. 2015-02-08 14:27:10 +00:00
Sloth
0ea7e765a0 - Improved DigAI. 2015-02-08 14:02:47 +00:00
Sloth
b5dd19867a - Cleanup and NPE protection. 2015-02-08 13:36:17 +00:00
Sol
2c2139e3d6 - Fix Sudden Reclamation 2015-02-08 13:35:54 +00:00
Sloth
74d25c7ce1 - Fixed two typos. 2015-02-08 12:59:08 +00:00
Myrd
20bd3e3ea9 Fix formatting. 2015-02-07 19:40:20 +00:00
Myrd
8e1feb1dc6 Make a helper class for evaluating a creature, so that it can be more easily customized through subclassing. 2015-02-07 19:39:40 +00:00
Myrd
8a96a479bb - Fix build that I broke.
- Commit some in-progress stack copying code that doesn't work yet (disabled).
- Throw exception when a GameObject couldn't be mapped from the orig game.
2015-02-07 19:18:37 +00:00
Myrd
859a853499 Add a somewhat hidden option in the UI to turn on simulation via a context menu on the AI radio button on desktop.
This allows choosing the AI mode without recompiling and also allows things like making a non-simulation AI play a simulation AI.
2015-02-07 18:32:02 +00:00
Myrd
4e1706ad22 Remove some assumptions about ordering of players in simulation AI code. 2015-02-07 17:54:43 +00:00
Myrd
8141b0edb2 Limit some debug output. 2015-02-07 17:52:45 +00:00
Sloth
947356b08a - Added SVar:PlayMain1:TRUE to Rakish Heir. 2015-02-07 13:25:32 +00:00
swordshine
c25555d8f0 - Fixed Warden of the First Tree and Figure of Destiny 2015-02-07 08:37:17 +00:00
swordshine
a37d3dd667 - Fixed a pic url 2015-02-07 07:58:34 +00:00
Myrd
9b40f6559b Fix some spammy output that came from my last commit. 2015-02-07 03:13:52 +00:00
Myrd
cfd38b7111 Fix game copy inconsistency with paid echo cost during simulation. 2015-02-07 02:55:48 +00:00
Myrd
62f790e9fe Add code for debugging simulation copy errors. 2015-02-07 02:31:46 +00:00
Myrd
d5d8e9a11a Tweak logic for holding off playing creature spells for M2 so that instant/sorceries aren't unfairly selected for M1, in simulation AI. 2015-02-07 01:09:18 +00:00
Hellfish
8eede91c88 *Fixed leaving planes. 2015-02-06 22:13:37 +00:00
Myrd
2c25351a2e Fix ETB effects not triggering during simulation and add a test. 2015-02-06 04:06:11 +00:00
Myrd
7a5c8fd61f Move USE_SIMULATION boolean to AIController class.
Otherwise, with the previous set up, if simulation code returned null (= "don't play anything"), the regular AI code would then choose something to play.
2015-02-06 03:02:03 +00:00
Myrd
ac81b60a1d Count cards beyond max hand size for less. 2015-02-06 02:48:30 +00:00
Myrd
4819c1e03d Fix activator being clobbered up during simulation. 2015-02-05 04:21:50 +00:00
Myrd
8b40da32de Print more info about targets chosen during simulation. 2015-02-05 04:14:23 +00:00
Myrd
be8b250d27 Making the simulation AI less eager to play instants during early phases. 2015-02-05 03:41:23 +00:00
Myrd
392e8e7008 Fix game copy error with equipment. 2015-02-05 02:52:15 +00:00
Myrd
8d5706b36e Fix copying game with static effects to not double count them along with expanded tests for this. 2015-02-03 04:43:40 +00:00
Myrd
16ac1713c5 Add a failing simulation test related to static abilities.
Will enable the test in the CL that fixes it.
2015-02-03 03:26:58 +00:00
Hellfish
464ee0252e *Fixed Alabaster Dragon's trigger description and optionalness 2015-02-01 19:23:12 +00:00
Myrd
2696f75f16 Add a text file with some high-level TODOs for the AI simulation framework. 2015-02-01 18:03:21 +00:00
Hellfish
9e1633fec9 *Fixed Planechase Phenomenon brokenness. 2015-02-01 17:52:26 +00:00
Agetian
7f16ada195 - For now, set USE_SIMULATION to false for the default AI configuration in snapshots (I assume it was turned on in r28764 accidentally... if I'm wrong please let me know or feel free to revert) 2015-02-01 05:24:23 +00:00
Maxmtg
36bc0d08e1 removed the FCollection from forge-core 2015-02-01 03:13:08 +00:00
Myrd
6db238833d Make simulation AI play creatures in MAIN2 unless they have haste or give bonuses in other ways.
Also, properly handle summoning sickness when copying game state.
2015-02-01 01:56:33 +00:00
Chris
22eac76494 Cleared out the changes.txt file, now ready for new material. Moved Net Decks support from README.txt back to CHANGES.txt. 2015-02-01 01:49:02 +00:00
Chris
9618b85dc0 Checking in the pom.xml.releaseBackup files which failed to be checked in when the maven goal ended. 2015-02-01 01:45:18 +00:00
Myrd
58b2e2b24a Add first unit test for game simulation AI - tests the fix for activations of ability triggers from my last commit. 2015-01-31 19:02:37 +00:00
Myrd
30b3644668 Moved package. 2015-01-31 17:34:41 +00:00
Myrd
8dedbf083d Fix package name.
Also, fix cast triggers not resolving during simulation.
2015-01-31 17:30:50 +00:00
Agetian
3d1f812a26 - Removed debug spam that I forgot to take out. 2015-01-31 15:17:25 +00:00
Agetian
92b3dd38c2 - Fixed a bug that prevented the AI from using pump creatures correctly. 2015-01-31 15:16:53 +00:00
Chris
3fd3b876d4 [maven-release-plugin] prepare for next development iteration 2015-01-31 15:00:24 +00:00
Chris
87d8d96c7d [maven-release-plugin] prepare release forge-1.5.34 2015-01-31 15:00:17 +00:00
Agetian
62657532ef Reverting 28752 as requested by Chris 2015-01-31 05:21:08 +00:00
Chris
0ea0288f72 test commit 2015-01-30 23:33:39 +00:00
Chris
223ca54671 Preparing the changes.txt file for the next beta build and release. 2015-01-30 13:40:14 +00:00
Maxmtg
1eeaa685db another clean-up for quest drafts (add ROE x3 drafts, fix core set drafts) 2015-01-30 07:26:48 +00:00
Agetian
0594145a4f - Fix triple draft set choices in Quest draft tournaments. 2015-01-30 05:49:17 +00:00
Maxmtg
aea1512435 ref: CardBlock offers sets as unmodifiable list, QuestEventDraft takes up less code :) 2015-01-30 05:22:09 +00:00
Sloth
38ab9ceeb2 - Added the quest deck Mr Smith 3 (by tojammot). 2015-01-29 21:31:08 +00:00
Chris
fc0e1384f1 Cleared out the changes.txt file, now ready for new material. 2015-01-29 17:31:15 +00:00
Agetian
783f9c094c - Recreate default card properties and spell abilities for cards returning to hand (fixes e.g. Genju of the Fields unplayable after returning from graveyard, Far // Away and other splits not allowing to choose another ability if mana payment was canceled, etc.). 2015-01-29 16:55:54 +00:00
Myrd
48e20a9b67 Remove assumption about having a single opponent in game scoring function for AI simulation. 2015-01-29 03:56:28 +00:00
Myrd
e332b383e9 Reduce some spam in simulation AI:
- Don't evaluate mana abilities.
  - Produce a diff of the game eval state instead of printing out two full sets.
  - Cut down on some extra evaluations.
2015-01-29 03:35:24 +00:00
Myrd
4e7565dd2a Create a LobbyPlayerAI when simulating, so that UI elements don't pop up to the human. 2015-01-29 03:02:31 +00:00
Myrd
e22029463d Commit initial version of experimental AI simulation code.
It's disabled by default. Set SpellAbilityPicker.USE_SIMULATION = true to enable.

It's nowhere near complete and there are still tons of issues to work out, but it works a lot of the time.
2015-01-29 00:27:02 +00:00
Myrd
f083b9055d Fix a NPE. 2015-01-29 00:24:49 +00:00
Sloth
145326a753 - Updated 3 AI SVars. 2015-01-28 22:49:39 +00:00
Sloth
882fdc8b82 - Updated some quest decks with FRF cards. 2015-01-28 18:46:48 +00:00
Myrd
b9005faf1c Missed a space. 2015-01-28 03:39:46 +00:00
Myrd
ee5549c489 Disambiguate triggered vs. activated abilities in game log. 2015-01-28 02:23:26 +00:00
Agetian
610c5d308c - Somewhat more meaningful and correct variable names. 2015-01-27 19:32:20 +00:00
Agetian
b112a63d22 - Fix the draft order for sets before Mirrodin Besieged in Quest draft tournaments. 2015-01-27 19:30:43 +00:00
Agetian
86b2ff054b - A little further fix for AB RemoveCounter. 2015-01-27 18:57:43 +00:00
Agetian
16100096a7 - Fixed the AB RemoveCounter not correctly remembering multiple instances of removed counters of the same type (fixes Give // Take, Delaying Shield and possibly other similar cards). 2015-01-27 18:01:34 +00:00
elcnesh
864b967465 Don't ask to delve if graveyard is empty. 2015-01-27 15:42:32 +00:00
elcnesh
5f08b5710f Use a List rather than a Set for storm count so that the same card can be counted twice. 2015-01-27 14:47:31 +00:00
elcnesh
28a92e34df Fix Grim Haruspex plus some cleanup. 2015-01-27 14:29:31 +00:00
elcnesh
f9b473c8fd - Move changed card colors to the Card rather than CardState
- Fix Kusari-Gama
2015-01-27 14:28:54 +00:00
elcnesh
4a74fe87fc Fix some possible issues with attack constraints and how the AI handles them. 2015-01-27 14:22:03 +00:00
Sloth
01b6032e93 - Updated some quest decks with FRF cards. 2015-01-27 13:26:36 +00:00
swordshine
a83df8fb94 - Fixed Homura, Human Ascendant 2015-01-27 04:55:01 +00:00
swordshine
e32030bc35 - Fixed Hardened Scales 2015-01-27 04:35:40 +00:00
Sloth
2021adb21e - Fixed difficulty of Invisible Man 4. 2015-01-26 23:01:52 +00:00
Sloth
10458c9729 - Added the quest deck Yogi Bear 2 (by tojammot). 2015-01-26 23:00:10 +00:00
elcnesh
7952bdaac0 Fix static abilities that remove a type (like those on Theros gods). 2015-01-26 13:32:50 +00:00
elcnesh
ef1b397647 Fix cards with a static ability that adds hidden keywords, like Courser of Kruphix. 2015-01-26 13:18:15 +00:00
elcnesh
92b80c69ff Refactoring changes and other updates:
- Completely refactor continuous static effects. Layers are now implemented properly in the sense that every effect applies the relevant parts in the relevant layer, while locking in the set of cards to which it applies.
- Refactor the (un)freezing of Trackable objects to a per-game Tracker object rather than static methods, to allow multiple games hosted on the same machine.
- Refactor the changing of card colours to match other parts of the code (like type and P/T changing) more closely. Also get rid of some static parameters in that code.
- Some changes in how split cards on the stack are handled to make them more robust.
- Some more minor changes/cleanup.
2015-01-26 10:41:06 +00:00
Sloth
90f88cce9d - Updated some AI SVars of FRF cards. 2015-01-25 15:44:17 +00:00
Sloth
44cf1d3bb3 - Updated some AI SVars of FRF cards. 2015-01-25 10:45:14 +00:00
Sloth
b30939d14d - Updated some AI SVars of FRF cards. 2015-01-25 09:43:50 +00:00
drdev
53cd66b7c5 Fix issue with contructor not available on Android 2015-01-25 06:35:00 +00:00
drdev
78e3cba419 Fix issue with missing function for Android 2015-01-25 05:51:53 +00:00
drdev
99b025de5f Version bump to 1.5.34.002 2015-01-25 05:36:40 +00:00
drdev
6d5416c175 Fix how net deck categories appear in select list 2015-01-25 05:12:54 +00:00
drdev
30fbe55ac3 Add Net Decks support 2015-01-25 05:10:32 +00:00
Krazy
f3a30793c5 Added foil basic lands to FRF boosters and updated the way foil cards are generated to account for multiple cards in printsheets. There should now be a more equal distribution of foil rarity. 2015-01-24 18:27:14 +00:00
drdev
31d1d7da8c Version bump to 1.5.34.001 2015-01-24 17:50:34 +00:00
Krazy
c0c4383953 Fixed land distribution for FRF. Basics have been removed entirely as per the real booster packs. Also cleaned up a bit of formatting. 2015-01-24 17:37:54 +00:00
Sloth
b4a877ccbc - Fixed Samurai of the Pale Curtain. 2015-01-24 13:29:01 +00:00
Sloth
a8c4e0f83e - Improved AI using Sultai Emissary and Ethereal Ambush. 2015-01-24 13:21:11 +00:00
swordshine
9c713adf29 - Fixed Silent-Chant Zubera 2015-01-24 08:42:05 +00:00
Agetian
e9000fa6b7 - Temporarily reintroduced the processing of !fromSheet (only in its inverted form) to fix M15 and CNS booster generation without breaking KTK/DGM booster generation (until a better solution is introduced). 2015-01-24 05:28:05 +00:00
swordshine
f21ce140b7 - Fixed Frontier Mastodon 2015-01-24 04:50:40 +00:00
Sol
b3ccaa1eae - Temur War Shaman's flip and fight ability should be optional. 2015-01-24 04:48:57 +00:00
Sol
16a4ee3dc9 - Adding basic AI for Manifest cards 2015-01-23 22:24:52 +00:00
Sol
0320e8b9cb - Don't add Unmanifest ability to noncreatures 2015-01-23 14:14:00 +00:00
Sloth
70caf4fda6 - Added the quest decks He-Man 3 and Invisible Man 4 (by tojammot). 2015-01-23 13:48:36 +00:00
Krazy
7e4cd4b717 [maven-release-plugin] prepare for next development iteration 2015-01-23 03:50:25 +00:00
Krazy
141a20570b [maven-release-plugin] prepare release forge-1.5.33 2015-01-23 03:50:15 +00:00
Agetian
d6ebdf4f77 - Updated the Imprint scripts to properly clean up upon leaving the battlefield (please review). 2015-01-22 15:28:07 +00:00
Agetian
01f2f8c29f - Fix the clean up of imprinted cards using DB CleanUp. 2015-01-22 14:59:03 +00:00
Agetian
db09562965 - For now, revert the Imprint change until a better solution is found. 2015-01-22 14:23:58 +00:00
swordshine
d6740fb18e - Fixed Wall of Nets 2015-01-22 14:09:01 +00:00
Agetian
9cc8415af7 - Fixed Imprinted cards not being cleared when a card with Imprint LTBs.
- Fixed equipment lingering on cards in graveyard.
2015-01-22 12:56:49 +00:00
Myrd
5c609d80f0 Move getValidCardsToTarget() to CardUtil from TargetSelection, so it can be re-used from elsewhere (e.g. AI code I'm currently working on). 2015-01-22 06:25:46 +00:00
swordshine
c09926a190 - Reverted changes in CopyCard to fix Bestow (please do not handle Bestow in state based action)
- Converted ZCTrigger to normal GameCommands
2015-01-22 05:19:09 +00:00
Agetian
f615293f79 - Take two: trying to fix Bestow (this should account for the Far // Away test in Fuse mode when taking down a creature enchanted with a bestowed enchantment creature). 2015-01-22 04:52:47 +00:00
swordshine
07d0e3d839 - Fixed Cloudform 2015-01-22 00:44:46 +00:00
Agetian
27d78fd106 - Fixed Boon Satyr (and possibly others) going straight to graveyard if bestowed onto a creature which then dies. 2015-01-21 19:06:45 +00:00
Agetian
54dcd5c645 - Fixed Dragonrage. 2015-01-21 15:02:12 +00:00
swordshine
248f02ae3e - Fixed Scrounge 2015-01-21 13:56:11 +00:00
swordshine
54f23f81a5 - Several cards with MillEffect will never reveal the milled cards now (e.g. Helm of Obedience/Rest in Peace combo, Painters combo) 2015-01-21 13:40:15 +00:00
swordshine
541f28c203 - Fixed Teferi's Puzzle Box 2015-01-21 13:19:49 +00:00
swordshine
57478104de - Fixed Ojutai, Soul of Winter 2015-01-21 13:09:33 +00:00
swordshine
7a073c8d94 - Fixed Mindstab Thrull 2015-01-21 12:22:27 +00:00
Agetian
e50e7f575e - Fixed the game spoiling card IDs when looking in the players' libraries, opponent's hand, etc. 2015-01-21 08:16:46 +00:00
Agetian
65be79f79f - Fixed Elite Scaleguard. 2015-01-21 07:50:11 +00:00
swordshine
b7d577bf21 - Updated some scripts 2015-01-21 07:41:04 +00:00
Agetian
c8e0dc6e5a - Added Surprise Attack precon deck to quest mode (FRF). 2015-01-21 05:31:17 +00:00
swordshine
d6ec277ced - Added Arashin War Beast 2015-01-21 05:12:52 +00:00
Krazy
54eda8a3e8 Slightly adjusted land distribution for FRF boosters. 2015-01-21 05:06:08 +00:00
Myrd
4b98b8d715 Fix: bestowed enchantments should animate into creatures when the enchanted permanent leaves the battlefield. 2015-01-21 04:50:23 +00:00
Krazy
6382dbbe76 Fixed printsheets. A bug was preventing anything other than same-set cards from appearing in any separately defined printsheets, which broke booster packs for sets such as Fate Reforged and Dragon's Maze that contain cards from other sets. Also corrected the Fate Reforged booster format to include some KTK dual lands and to not put common dual lands into the commons slots. 2015-01-21 04:36:58 +00:00
Myrd
4a90436589 Better error message to debug an exception. 2015-01-21 04:15:28 +00:00
Agetian
f32a2412b6 - Fixed a crash and other issues with the Dragons mode of Frontier Siege. 2015-01-20 18:57:07 +00:00
elcnesh
eb1694dad2 Fix Not of This World plus some cleanup. 2015-01-20 17:14:46 +00:00
Agetian
45191930f0 - Fixed the Clash effect not revealing the card to the player when asking whether to put the card on the top or on the bottom of the library (possibly also fixes other similar effects that query the player via willPutCardOnTop). 2015-01-20 16:02:41 +00:00
swordshine
a04f82237a - Updated mtg-data 2015-01-20 04:20:23 +00:00
drdev
265f7f52df Prevent Card.getType() from depending on view being updated 2015-01-20 02:11:18 +00:00
swordshine
3ac1203874 - Updated Banned and Restricted lists 2015-01-20 01:07:16 +00:00
Agetian
fd55dcfed5 - Added Planeswalker achievements for C14 planeswalkers. 2015-01-19 07:56:42 +00:00
elcnesh
24680c4aef Fix owner of token to be its initial controller. 2015-01-18 21:11:33 +00:00
elcnesh
b1d41c1336 Fix creature required to attack a nonexisting GameEntity. 2015-01-18 21:06:06 +00:00
Agetian
fd7d644eec - Attempt to fix Lim-Dul's Vault by allowing the activating player of AF DigEffect to see the cards even if they're not actually moved. 2015-01-18 20:34:21 +00:00
Sol
c7a3c51541 - Aven Surveyor was missing flying 2015-01-18 17:33:12 +00:00
Sol
6f8d674cad - Creatures without a name can't have the same name as other creatures without a name (Bile Blight + Morph) 2015-01-18 17:10:43 +00:00
drdev
d2108e26c0 Fix Momir Vig crash 2015-01-18 17:09:48 +00:00
Sol
e576dbcf93 - AI will no longer cast Bolster with no creatures on the BF
- Manifest Ability can't be activated if the original card isn't a creature
2015-01-18 17:00:03 +00:00
drdev
a87271f220 Add Dump Game State to mobile dev menu 2015-01-18 16:36:14 +00:00
Sol
a3a2bf0445 - Stop Arcbond dealing damage to non-creature permanents 2015-01-18 16:05:47 +00:00
drdev
532d304e2e Version bump to 1.5.33.003 2015-01-18 15:55:44 +00:00
Sol
0a5ea5383c - Fixing Frontier Mastodon SVar check 2015-01-18 14:32:06 +00:00
Agetian
59a4c0ec2a - Fixed NPE related to Devour. 2015-01-18 13:52:42 +00:00
swordshine
9d022fb318 - Updated scripts according to Fate Reforged Update Bulletin 2015-01-18 07:21:53 +00:00
Agetian
a29f328397 - Corrected the token image name for Mardu Strike Leader. 2015-01-18 06:22:27 +00:00
Sol
adbdcc62ac - Fixing cost of Supplant Form 2015-01-18 04:38:27 +00:00
Sol
8469554984 - Better fix for Temur Sabretooth 2015-01-18 04:10:24 +00:00
excessum
1fc8aad1cc - Fixed Temur Sabertooth 2015-01-18 02:47:58 +00:00
excessum
96bc050509 - AI will not use Dash if it can cast the creature normally 2015-01-18 02:00:21 +00:00
excessum
a32272a0d8 - AI will only use Dash if the creature is attacking 2015-01-18 01:48:02 +00:00
Chris
e2aaf464c7 Added new card names to changes.txt. 2015-01-18 01:31:34 +00:00
Sol
9b35587827 - Fixing executing trigger effect for Abzan Skycaptain 2015-01-17 21:32:43 +00:00
drdev
e5ae6f988d Version bump to 1.5.33.002 2015-01-17 17:41:29 +00:00
drdev
d3f33c5954 Fix so ETB triggers fire when use DevMode Add To Battlefield for lands 2015-01-17 17:34:10 +00:00
Sol
3d663e18e1 - Fixing Dromka CC 2015-01-17 17:19:31 +00:00
Agetian
faedf1660e - Added updated information to some javadoc comments. 2015-01-17 14:50:19 +00:00
Agetian
282a122a14 - Made the Limited AI deck generation always obey the land set code requirement for the given card pool (used not to work correctly in Sealed Deck mode, instead giving the AI lands from random sets). 2015-01-17 14:47:57 +00:00
Sol
a78d68206f - Updating Rankings for FRF 2015-01-17 14:45:35 +00:00
Agetian
3c2abe9ab2 - Added precons for KTK and FRF in quest mode. 2015-01-17 13:46:51 +00:00
Sol
f18d2955d7 = Fixing PT of sandsteppe_outcast.txt 2015-01-17 05:03:02 +00:00
swordshine
ae869616be - Added Wild Slash 2015-01-17 04:56:34 +00:00
swordshine
bb632db972 - Added Arcbond 2015-01-17 04:48:07 +00:00
swordshine
7340f6a417 - Added Winds of Qal Sisma 2015-01-17 04:09:16 +00:00
swordshine
0d09a9151d - Added Friendly Fire 2015-01-17 03:56:37 +00:00
swordshine
711290ad31 - Added Hungering Yeti 2015-01-17 03:40:38 +00:00
swordshine
d231680052 - Fixed Sandsteppe Outcast 2015-01-17 01:20:56 +00:00
Sol
80bcb30101 - Fixed Khans for Outpost Siege 2015-01-17 01:20:06 +00:00
Sol
38e57068de - Oracle FRF N-Y 2015-01-16 23:17:19 +00:00
drdev
d36b59b9b7 Fix issue with Phasing 2015-01-16 23:07:27 +00:00
Sol
25bf1dca04 - Oracle FRF F-M 2015-01-16 23:04:31 +00:00
Sol
330224281e - Oracle FRF A-E 2015-01-16 22:57:20 +00:00
elcnesh
f1745fae72 Fix bug in method body (my fault, nonfunctional) 2015-01-16 21:19:51 +00:00
Agetian
e34bf0ca7c - Added one more new card to CHANGES.txt. 2015-01-16 18:06:39 +00:00
Agetian
9bc170b7a8 - Added an achievement for Ugin, the Spirit Dragon's ultimate ability. 2015-01-16 18:04:16 +00:00
Chris
74a55b0233 Added new card names to changes.txt. 2015-01-16 18:01:20 +00:00
Agetian
c6c4265763 Added Noxious Dragon (by Marek14). 2015-01-16 17:14:35 +00:00
Sol
7a41b061df - FRF: Added Ghastly Conscription 2015-01-16 16:55:18 +00:00
Agetian
ba9452a715 - Fixed the card naming scheme. 2015-01-16 16:46:17 +00:00
Sol
d8e44a62bd - FRF: Added Dark Deal and Write Into Being 2015-01-16 16:09:56 +00:00
Agetian
4596afe9b7 - A better fix for the issue with keywords not being cleared - it seems like this part of the issue is remedied with a previously missed state update call. 2015-01-16 15:57:57 +00:00
swordshine
6355dd14ec - Added 3 FRF runemarks 2015-01-16 14:10:15 +00:00
swordshine
55f656cfa5 - Fixed Vaultbreaker 2015-01-16 13:42:13 +00:00
swordshine
c922b34c19 - Fixed a typo 2015-01-16 13:07:32 +00:00
swordshine
0d4cdbd1cb - Added FRF edition file and merged FRF branch 2015-01-16 13:02:28 +00:00
swordshine
5d8054200f - FRF: Fixed Monastery Siege 2015-01-16 12:07:30 +00:00
Agetian
e5c25f1cab - Second attempt at fixing the keywords lingering longer than necessary, looks like there were actually two related problems - the data about equipments being copied over to a temporary copy that then became a card going to graveyard *and* the keywords from enchantments and such staying on the card (even the copied one, without any enchantment info being hard-copied) when going to graveyard.
- A better fix for the second problem would be to actually find *why* (and where in the code) those keywords are not cleaned up and clean them up there, but I can't find where it is for now. Please review and update as necessary.
2015-01-16 10:44:15 +00:00
Agetian
12688a1bb1 - Do not copy equippedBy/enchantedBy/fortifiedBy information when copying a card (because two cards can't really be enchanted/equipped by the same card anyway, so it should be unique). This fixes a bug with keywords lingering longer than necessary. 2015-01-16 08:06:18 +00:00
swordshine
a27bd64d5d - FRF: Added Channel Harm 2015-01-16 07:26:08 +00:00
drdev
72a33daf87 Prevent mobile app crashing on startup 2015-01-16 03:58:13 +00:00
Myrd
47a3a173b6 Refactor helper function. 2015-01-16 03:35:52 +00:00
Myrd
03631aef2e Fix indentation. 2015-01-16 03:31:48 +00:00
drdev
06c4402cef Update mobile app to 1.5.33 2015-01-16 03:12:30 +00:00
swordshine
f3a490db3d - Tweaked "TriggeredDefendingPlayer" 2015-01-15 13:46:02 +00:00
swordshine
5e5060256a - FRF: Added Brutal Hordechief 2015-01-15 13:36:56 +00:00
swordshine
9483a889f1 - Fixed a possible ClassCastException when Septic Rats attacks a planeswalker 2015-01-15 13:10:10 +00:00
swordshine
cee0eb27f6 - FRF: Added #97-100 by Marek14 and Kapoue (tweaked CopyAttacking for Flamerush Rider) 2015-01-15 12:11:24 +00:00
swordshine
997d8795a5 - FRF: Added Tasigui, the Golden Fang and Diplomacy of the Wastes 2015-01-14 05:18:27 +00:00
Agetian
56dd767343 - Revert the last couple commits, looks like there is no unwanted console spamming if everything is set up properly. 2015-01-14 04:59:23 +00:00
Agetian
e40f374eff - Forgot to commit this file. 2015-01-13 19:57:59 +00:00
Agetian
eaa80c9583 - Avoid spamming "picture not found" messages when looking for XLHQ art. 2015-01-13 19:57:17 +00:00
Agetian
3c3a830d04 - Refactored the XLHQ card zoom code, moved GetImageXlhq to FImageUtil where it belongs more. 2015-01-13 18:04:45 +00:00
Agetian
c9e4dd9ffc - Support foiling XLHQ card images. 2015-01-13 17:55:36 +00:00
Agetian
22c6f99af8 - Correction in CHANGES.txt. 2015-01-13 17:38:47 +00:00
Agetian
1bd2aff0b1 - Added support for zooming in to XLHQ tokens (documented in CHANGES.txt). 2015-01-13 17:37:24 +00:00
Agetian
b7191150f0 - Reorganized the imports a little bit. 2015-01-13 16:56:06 +00:00
Agetian
027f0038e7 - Added a way to zoom to a XLHQ card picture if available (optional), documented it in CHANGES.txt.
- Fixed the planes and phenomena not being rotated 90 degrees when zooming in on them.
2015-01-13 16:54:12 +00:00
Agetian
3a45df9217 - Fixed the image sprite loading bar going to 116% instead of to 100%. 2015-01-13 14:29:37 +00:00
Sol
d4b74ddc31 - For some reason hasFizzled didn't have any checks to make sure spells are still on the stack 2015-01-13 00:29:01 +00:00
Chris
88a61c2023 Added new card names to changes.txt. 2015-01-12 23:50:21 +00:00
swordshine
ed444c2705 - FRF: Added Grim Contest 2015-01-12 14:14:18 +00:00
Myrd
dc3f487d6b Fix following exception at game end:
java.lang.RuntimeException: Cannot remove input InputPayManaOfCostPayment because it's not on top of stack. Stack = []
	at forge.match.input.InputQueue.removeInput(InputQueue.java:60)
	at forge.match.input.InputSyncronizedBase.stop(InputSyncronizedBase.java:49)
	at forge.match.input.InputPayMana.onStateChanged(InputPayMana.java:431)
	at forge.match.input.InputPayMana$3.run(InputPayMana.java:382)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)
2015-01-10 01:50:56 +00:00
swordshine
ed2bfcc295 - FRF: Added Soulfire Grand Master 2015-01-09 04:21:01 +00:00
Agetian
cf718c48fa - Removed an extra empty line. 2015-01-08 11:28:15 +00:00
Agetian
4305ad0612 - Visualize the information about the outcome of Scry in the log (because this info is supposed to be public - you can see whether your opponent scries to the top or to the bottom of the library). The only minor problem is that this outcome appears right before the announcement of the ability in the log (in the reverse order), not sure how to fix. 2015-01-08 11:20:06 +00:00
Chris
8058e75151 Added new card names to changes.txt. 2015-01-08 03:43:34 +00:00
Chris
a183893492 Cleared out the changes.txt file, now ready for new material. 2015-01-08 03:27:38 +00:00
Chris
cfe726e14a update poms to 1.5.33 2015-01-08 03:25:07 +00:00
Agetian
cb7820eb80 - Submitting KTK token name corrections by Xitax. 2015-01-07 06:49:26 +00:00
Sloth
8fc20a4e72 - Added the quest decks: Bullseye 2 (by Nordos) and Imperial Guard 2 (by tojammot). 2015-01-06 13:48:09 +00:00
-gz
1a5d5efebc Allow tapping of less than everything for cards which may tap any number 2015-01-06 00:56:28 +00:00
-gz
aa6c7943aa During drafting stop reporting basic lands as not found on stdout 2015-01-06 00:52:13 +00:00
Chris
05e43cf21c Preparing the changes.txt file for the next beta build and release. 2015-01-05 13:49:35 +00:00
Chris
367466df4e Added new card names to changes.txt. 2015-01-05 13:45:26 +00:00
drdev
b2a3bcaae1 Make black and red tiles more distinct 2015-01-05 02:02:54 +00:00
drdev
3e51983237 Code cleanup 2015-01-05 01:49:00 +00:00
drdev
11b8cfed8b Support better tiles 2015-01-05 00:22:32 +00:00
drdev
a809ab2546 Support rendering color tiles instead of mana icons 2015-01-04 20:31:08 +00:00
Myrd
2853af3a10 Support saving/restoring game state that has creature tokens. 2015-01-03 19:15:44 +00:00
Sol
06801023b5 - Adding Manifest effect 2015-01-02 22:48:47 +00:00
Chris
37029fd2b9 Added new card names to changes.txt. 2015-01-01 21:09:54 +00:00
Myrd
16d4cf3dad Mobile: When updating cards and re-computing stacks, first clear all existing stack linked lists. Speculative fix for game freezing sometimes due to a cycle in the linked list. 2015-01-01 16:38:57 +00:00
swordshine
e0071af437 - Fixed Tamiyo, the Moon Sage 2015-01-01 11:11:46 +00:00
Myrd
51571c667d Oops, real fix for canBeTargetted. 2014-12-31 22:28:14 +00:00
swordshine
1634c04313 - Fixed canBeTargetedBy 2014-12-31 05:16:00 +00:00
Myrd
cee81da6ee Forgot to commit this. 2014-12-31 04:28:06 +00:00
Myrd
c57af8efc5 More use of visitor pattern to avoid allocations. 2014-12-31 04:10:21 +00:00
Myrd
6d7c7fe63c Use other method name here too. 2014-12-31 03:58:30 +00:00
Myrd
c2904fa2aa More visitors for keywords and merge duplicate keyword amount methods. 2014-12-31 03:57:16 +00:00
Myrd
35a1daf116 Fix a bug and more visiting. 2014-12-31 03:33:47 +00:00
Myrd
ea9f1f3ecf Fix error from my last commit. 2014-12-31 03:23:07 +00:00
Myrd
648756d1b8 More use of Visitor pattern - allowing iteration over all cards in the game without allocating a temporary collection. 2014-12-31 03:19:41 +00:00
Myrd
9f144f175e Bump android-maven-plugin version to rc.2, since rc.1 was throwing exceptions for me. Also, lower build heap size to 1G, which is still enough and is less likely to fail if there isn't enough memory. 2014-12-31 00:44:55 +00:00
Myrd
1f5cca02dd Optimize hasKeyword() to not need to allocate and concatenate a bunch of lists together.
Instead, makes it use the visitor pattern which allows traversing all the keywords without (usually) needing to allocate any  temporary lists.
2014-12-31 00:38:45 +00:00
Myrd
45c17d35da ArrayList of Floats -> float[] to avoid a bunch of temp allocations in frequently called code. 2014-12-30 22:32:52 +00:00
Myrd
46a870a0ea Optimize more temporary allocations. 2014-12-30 22:19:54 +00:00
Myrd
b39a7d310c Use game.getCardsInGame() rather than duplicating logic in a less efficient way. 2014-12-30 21:55:54 +00:00
Myrd
4096643769 Optimization to avoid excessive allocations. 2014-12-30 21:30:25 +00:00
Myrd
1a8ab8dfd0 Move DeckHtmlSerializer.java to forge-gui-desktop from forge-gui and remove freemarker as a dependency of forge-gui.
This removes a couple thousand unused methods from the Android APK.
2014-12-30 21:03:57 +00:00
swordshine
32f52f6880 - FRF: Added Soulflayer 2014-12-30 13:03:24 +00:00
swordshine
2cd0919d29 - FRF: Added Sandsteppe Mastodon 2014-12-30 12:27:42 +00:00
swordshine
ff26173d64 - FRF: Added Kolaghan, the Storm's Fury (Keyword: Dash) 2014-12-30 10:54:52 +00:00
Myrd
b6dbf28d0b Simplify and slightly optimize some code - move updateCard() to be a method of the CardAreaPanel. 2014-12-30 06:37:15 +00:00
Myrd
41a1c9b5e5 Change recursion to iteration. This is a bit more efficient, but also I've observed a stack overflow error with this recursion - so maybe iteration will help, unless there's another underlying logic error (e.g. a cycle). 2014-12-29 17:45:52 +00:00
swordshine
3d2156b429 - Fixed an NPE 2014-12-29 05:05:07 +00:00
Myrd
bf34aec4fc Get rid of global static Card cache and hang it off the Game instead.
This paves the way for having multiple simulataneous game objects (e.g. for simulation).
2014-12-28 16:31:23 +00:00
swordshine
5fe82c5758 - Fixed Soul Nova 2014-12-27 02:54:51 +00:00
swordshine
f9b867217c - Fixed ChangeTargets effect not working in WrappedAbility (reported by mastroego: http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=16350&start=120#p170429) 2014-12-27 02:32:32 +00:00
swordshine
5034afe90b - Fixed Spirit Flare 2014-12-27 02:18:55 +00:00
swordshine
e82b5d15d6 - Fixed Arcane Denial 2014-12-27 02:10:46 +00:00
swordshine
9f02a77856 - FRF: Added Ugin, the Spirit Dragon 2014-12-25 11:13:42 +00:00
swordshine
a059b96e61 - Fixed Teferi, Temporal Archmage 2014-12-25 11:05:53 +00:00
swordshine
13b733162c - Fixed Wall of Nets 2014-12-21 12:00:25 +00:00
Agetian
9ca09f9a94 - Improve handling of split cards: Now the names of split card halves will be attached to Oracle text in the card detail box to simplify understanding which part the text is related to. Also, split cards will be shown with correct color identity and textual description when they go on stack. 2014-12-21 09:29:15 +00:00
Sloth
1230e7cbcc - Fixed chooseNumber crashing when min > max. 2014-12-21 08:28:22 +00:00
swordshine
8007750724 - Fixed Plunge into Darkness 2014-12-21 08:27:03 +00:00
swordshine
93fcf1c72d - Fixed Intet, the Dreamer 2014-12-21 05:06:24 +00:00
swordshine
8755f27f1d - Added an etb check for Putcounter effect to fix the bug when blinking walkers with Doubling Season in play by Venser, the Sojourner 2014-12-21 04:17:49 +00:00
swordshine
9bdd219266 - Fixed Forbidden Orchard and Mikokoro, Center of the Sea 2014-12-21 03:47:49 +00:00
Sol
644c8147c0 - Adding Worldknit 2014-12-19 23:21:51 +00:00
swordshine
3538974b8d - Updated 3 scripts 2014-12-19 11:19:52 +00:00
Sol
e93f47865f - Extra error check for Conspiracies that aren't Power Play. 2014-12-19 04:34:24 +00:00
swordshine
fb91d352e7 - Added Barbarian Guides 2014-12-19 03:58:36 +00:00
Sol
de1c726b3c - Added Power Play (via manual editing of draft deck) 2014-12-19 03:53:30 +00:00
swordshine
7898e84a80 - Added Infinite Authority 2014-12-19 01:16:21 +00:00
Myrd
e9be6c9152 Couple fixes to game state save/restore logic. 2014-12-18 17:50:43 +00:00
Myrd
8c97af50de Prompt before overwriting existing file. 2014-12-18 16:41:00 +00:00
Myrd
0d53b46c91 Support saving/restoring empty zones. 2014-12-18 16:40:38 +00:00
Myrd
a2ca6661df Make PhaseType.smartValueOf() able to parse both formats of phase name. 2014-12-18 16:12:25 +00:00
Myrd
af3c5459c3 Move GameState class to AI project, where it can be used both by the human AI as it is now, and (in the future) by the AI, to help with simulating / restoring game state. 2014-12-18 16:11:10 +00:00
swordshine
c4d52e85a4 - Fixed a description 2014-12-18 14:03:18 +00:00
swordshine
7425e514b3 - Added Arcum's Whistle 2014-12-18 13:59:27 +00:00
Sol
507df2929c - Fixing the casing for the target type of Krosan Groundshaker 2014-12-18 13:11:04 +00:00
swordshine
cded63fe9f - Added Three Wishes 2014-12-18 08:50:19 +00:00
swordshine
2f5b7e0744 - Converted Final Fortune's effect to a delayed trigger 2014-12-18 05:38:48 +00:00
drdev
8048b216a9 Add Ravnica test case 2014-12-18 03:23:54 +00:00
drdev
41e4479f00 Support colorless regions 2014-12-18 03:13:49 +00:00
drdev
9980926c8a Code cleanup 2014-12-18 02:53:10 +00:00
drdev
d8e146b409 Support dividing map into regions 2014-12-18 02:46:41 +00:00
swordshine
d07072af8e - Added Arcane Lighthouse 2014-12-17 14:21:12 +00:00
Sloth
c0062c260d - Added the quest decks: Eldrazi 2 (by Nordos), Trostani 2 and Waylon Smithers 3 (by tojammot). 2014-12-17 12:29:05 +00:00
drdev
da24010b0b Support assigning and rendering mana icons for each tile 2014-12-17 05:35:08 +00:00
drdev
07572b9103 Support zoom for map 2014-12-17 03:44:29 +00:00
drdev
1440645a33 Add padding around edge of map 2014-12-17 02:59:14 +00:00
drdev
b97b586d2d Fix mobile game compile errors from recent refactoring 2014-12-17 02:01:58 +00:00
Sol
d9abca9538 - Fix {R} mana symbol in Torrent of Souls 2014-12-17 01:17:24 +00:00
Myrd
30fb451a45 Remove global Player cache, instead make it hang off the Game object. 2014-12-16 21:55:33 +00:00
Myrd
6be85a1741 Fix shard sort order when deciding if a mana cost is payable.
Prior to this change, the logic would conclude that a {1}{W} cost is not payable with an untapped Scoured Barrens (w/b) and Jungle Hollow (b/g) on the field.

The code is unfortunately too tangled (has too many dependencies) to write a unit test for this. Ideally, we should refactor so it wouldn't depend on the player, etc and just take parameters that can be fed test data.
2014-12-16 20:26:41 +00:00
Myrd
8c25bfd8b7 Refactor duplicated logic into a function. 2014-12-16 20:04:57 +00:00
Myrd
3fe326bf71 Dump game state in dev menu. 2014-12-16 19:39:42 +00:00
Myrd
5af52be0c6 Layout dump game state button side by side. 2014-12-16 19:37:11 +00:00
Myrd
205699bda3 fix restoring tapped and summon sick state 2014-12-16 19:19:42 +00:00
Myrd
ff17ebbc6c Clear cards in battlefield before adding the loaded ones when using set up game state function. 2014-12-16 19:07:58 +00:00
Myrd
85e7ad50b1 Ability to dump the current game state to a file in dev mode. 2014-12-16 19:04:05 +00:00
Myrd
8e3011294e Clean up includes. 2014-12-16 17:31:59 +00:00
Myrd
07757ff5d3 Refactor dev mode game state setting to a separate class. 2014-12-16 17:30:24 +00:00
drdev
fe82ac76ac Reduce appearance of character 2014-12-16 06:05:12 +00:00
drdev
f6b7ea95f2 Add a few more empty tiles 2014-12-16 06:01:10 +00:00
drdev
e62f103ad9 Fix edges of tiles 2014-12-16 05:58:22 +00:00
drdev
b0ccdaea9d Fix rounding issues with hexagon rendering 2014-12-16 05:43:18 +00:00
drdev
8c82551adc Support laying out and drawing tile map 2014-12-16 05:20:15 +00:00
drdev
02040ee026 Start major Planar Conquest overhaul 2014-12-16 01:28:29 +00:00
Sol
d3e7051f34 - Fixing NPE in VLog and VStack that pops up 10x tournament 2014-12-15 04:49:11 +00:00
drdev
25c2e67979 Prevent fling immediately after releasing fingers from quick zoom 2014-12-15 04:19:00 +00:00
drdev
547c247732 Fix so gesture issues for mobile game 2014-12-15 03:39:07 +00:00
Sol
605e3a2501 - Fixing missing period in Hobble 2014-12-15 01:08:02 +00:00
drdev
4f565c4b0c Prevent zoom leading to fling unintentionally 2014-12-14 22:40:57 +00:00
drdev
a40a5636b8 Replace gdx.jar with specially compiled trimmed down version of libgdx so Android build can work 2014-12-14 22:37:08 +00:00
elcnesh
191b8e4e71 Add Fatespinner (AI uses it at random for now). 2014-12-14 17:00:31 +00:00
elcnesh
706a98460b Fix clone effects, among others the bug of Renegade Doppelganger doesn't change back. 2014-12-14 16:20:57 +00:00
elcnesh
4b32a86679 Add Spy Network. Add new card names to CHANGES.txt. 2014-12-14 13:22:42 +00:00
elcnesh
6fb1fd3058 Fix certain planes by triggering once for each plane left when planeswalking. 2014-12-14 13:08:26 +00:00
elcnesh
50db5c165b Fix cards that cause each player to play with the top card of their libraries revealed. 2014-12-14 12:49:29 +00:00
Sloth
7bd39f7996 - Made the easy quest deck Frodo 1 easier. 2014-12-14 12:49:11 +00:00
Sloth
db557aa016 - Updated a quest challenge (by Nordos). 2014-12-14 11:15:20 +00:00
elcnesh
89dc827756 Add Aven Soulgazer and Smoke Teller. 2014-12-14 09:39:59 +00:00
drdev
4fe3a083a5 Move down plane stat labels slightly 2014-12-14 05:37:19 +00:00
drdev
3a583e0edb Remove tail at bottom of monitor 2014-12-14 05:27:58 +00:00
drdev
e10d51fdc4 Make long press on Commander view deck 2014-12-14 05:19:03 +00:00
drdev
1d71fffc72 Prevent crash if double tap commander panel not unlocked 2014-12-14 05:16:20 +00:00
drdev
83326e397b Clean up command center UI and add double-tap to edit deck 2014-12-14 05:14:59 +00:00
drdev
7d2be88175 Add plane stats to command center screen 2014-12-14 04:39:08 +00:00
drdev
f89316603b Support displaying unlock and win ratios for region 2014-12-14 04:02:44 +00:00
Krazy
01e8dc2186 Fixed a bug that resulted in draft tokens being spent when a draft was not selected. 2014-12-14 00:21:31 +00:00
drdev
de08df303b Improve how available pool is determined for Conquest deck editor 2014-12-13 19:34:48 +00:00
drdev
6c6554008c Support deck editing for Planar Conquest 2014-12-13 18:39:06 +00:00
Myrd
23b3551ab3 In "Import Deck" dialog, uncheck "Use only core and expansion sets" when editing commander decks. 2014-12-13 17:52:08 +00:00
drdev
8ecf833a11 Add Deck and Portal buttons 2014-12-13 16:56:32 +00:00
Myrd
59c1aa95b8 Fix Satyr Wayfinder revealing the top 4 cards twice. 2014-12-13 16:50:04 +00:00
Sol
60b0a1bbb4 - Adding YouCtrl to Crowned Ceratok 2014-12-13 14:00:54 +00:00
drdev
02b13cbc89 Allow human and AI to have different planar decks 2014-12-13 06:31:11 +00:00
drdev
20b47f3b91 Support starting games with variants in Planar Conquest 2014-12-13 06:16:10 +00:00
drdev
6845df50de Fix warnings 2014-12-13 05:30:50 +00:00
drdev
7a20bd682e Support using commander as game avatar 2014-12-13 05:03:42 +00:00
elcnesh
691fd67b9c Update libgdx to 1.5.0, now including binary library files. 2014-12-12 10:44:19 +00:00
elcnesh
9283328e22 Large cleanup in game; fix some small bugs and make a lot of methods static where applicable. 2014-12-12 10:39:45 +00:00
Sol
42fc1947fd - Fix casting cost 2014-12-12 04:55:44 +00:00
Sol
aa4ed2b05c - Labyrinth Minotaur's trigger wasn't working 2014-12-12 04:30:16 +00:00
drdev
3ec1e677d8 Prevent card overlapping message bars 2014-12-11 22:22:18 +00:00
drdev
16cf2651fb Version bump to 1.5.32.007 2014-12-11 22:13:22 +00:00
drdev
8e6dc3a5f8 Allow long press to switch between one card and three card view 2014-12-11 22:11:23 +00:00
drdev
d8a098af7c Support two finger zoom to make card bigger on zoom view 2014-12-11 22:07:29 +00:00
Agetian
798c6c26ec - Also specify the ID for cards that are currently face up (e.g. when revealing them). 2014-12-11 17:20:03 +00:00
Agetian
e57881f1d9 - Remove a leftover commented line. 2014-12-11 17:10:11 +00:00
Agetian
0ea126cd5d - Make sure the names of face-down cards are not spoiled, e.g. during blockers damage order assignment.
- A little typo fix.
2014-12-11 17:08:22 +00:00
elcnesh
6de61cb9a6 Code cleanup: make a lot of methods static and remove some unnecessary interface implements and casts. 2014-12-10 18:40:19 +00:00
elcnesh
5055ed4d2b Add a "Hidden card ID" to face-down cards to uniquely identify them without spoiling the actual card id (hidden id increments each time a card is turned face-down). 2014-12-10 18:36:04 +00:00
elcnesh
963743781a Make Hokori's untap mandatory. 2014-12-10 18:11:19 +00:00
elcnesh
9e1cbc29d4 Remove Flying from Sultai Soothsayer. 2014-12-10 17:36:48 +00:00
elcnesh
02844aca95 Update libgdx to 1.4.1. 2014-12-09 18:45:54 +00:00
elcnesh
8085775888 Add iOS project. 2014-12-09 17:00:13 +00:00
Myrd
1da8cd7fb1 Default to KTK zombie token instead of M15 for Sidisi. 2014-12-09 00:16:09 +00:00
elcnesh
278b1229c1 Fix and cleanup Hideaway. Plus a typo in Praetor's Grasp. 2014-12-08 20:50:34 +00:00
swordshine
d6010d6d40 - Added Nature Shields Its Own 2014-12-08 14:02:10 +00:00
Sol
6f95d07f1c - Moving Sidisi from the 'z' folder to the 's' folder 2014-12-08 13:46:05 +00:00
swordshine
c005752c08 - Updated a script 2014-12-08 11:36:20 +00:00
Myrd
2db80f506b - When an effect mills cards, pop up a dialog to show which cards got milled. 2014-12-08 06:18:11 +00:00
Myrd
23c41834aa Fix flaky test ManaCostBeingPaidTest by making ManaCostBeingPaid.toString() not depend on map iteration ordering. 2014-12-08 05:49:11 +00:00
Myrd
6029b7bcde Implement Sidisi, Brood Tyrant along with corresponding engine changes to support her ability. 2014-12-08 04:27:05 +00:00
drdev
1888d201e3 Add some delays to the end day process and make it so commanders selected in order 2014-12-08 03:47:20 +00:00
drdev
3c2dffe1c4 Support undeploying by tapping commander row 2014-12-08 03:05:21 +00:00
drdev
eaaca84826 Add support for unlocking commander 2014-12-08 02:34:12 +00:00
drdev
503740dfe5 Support awarding booster 2014-12-08 01:12:00 +00:00
Krazy
f8e9679f52 QuestUtil class updates; some cleaning up, some old new code I forgot to commit a while back. 2014-12-08 00:43:27 +00:00
drdev
356934bf27 Start working on Booster logic for Planar Conquest 2014-12-07 18:17:03 +00:00
drdev
c5cde9d34d Improve ratios for recruit/study 2014-12-07 07:59:37 +00:00
drdev
b83a95d55d Fix message for choosing booster or card 2014-12-07 07:36:31 +00:00
drdev
5c773d8b1e Add support for prompting for reward 2014-12-07 03:25:53 +00:00
drdev
b8b433586d Support playing conquest games 2014-12-07 01:20:52 +00:00
drdev
f7fbdc05dd Refactor code to make it easier to show rewards for planar conquest games 2014-12-06 23:52:54 +00:00
drdev
ce3b8e6c76 Introduce concept of stars
Rename IVConquestBase
2014-12-06 21:18:34 +00:00
drdev
43ca7ffe71 Update current region when commander tapped 2014-12-06 21:12:33 +00:00
drdev
3b5a86cbc7 Prevent deploying commander to multiple regions 2014-12-06 21:04:52 +00:00
drdev
10450d51a8 Rename Planar Map to Command Center 2014-12-06 21:01:48 +00:00
drdev
e9d31c0f0c Improve use of fading to clarify what's happening 2014-12-06 18:56:09 +00:00
drdev
556c590233 Make undeploy work 2014-12-06 18:37:54 +00:00
drdev
8e26dc333f Move WaitCallback and WaitRunnable to forge-gui 2014-12-06 18:16:30 +00:00
drdev
b9275d5678 Flesh out recruiting and studying 2014-12-06 18:04:36 +00:00
drdev
0594785d1f Allow tapping deployed commander to cancel any action 2014-12-06 07:53:07 +00:00
drdev
105d02e004 Fix bug with targeting arrow support 2014-12-06 07:46:09 +00:00
drdev
48bf499e89 Add targeting arrow support 2014-12-06 07:37:33 +00:00
drdev
fe2547527e Support ending the current day 2014-12-06 07:08:56 +00:00
drdev
df75047bb4 Start fleshing out conquest actions 2014-12-06 06:22:23 +00:00
drdev
efb9921c64 Support showing zoom for commanders 2014-12-06 05:27:28 +00:00
drdev
97fb0b1b0a Prevent mana cost overlay extending outside bounds of card 2014-12-06 05:08:58 +00:00
drdev
0e269420d2 Prevent more crashes in deck generator 2014-12-06 04:57:44 +00:00
drdev
32a1ee130f Prevent crash in DeckGeneratorBase 2014-12-06 04:26:01 +00:00
drdev
70c2afa96a Prevent duplicate opponents 2014-12-06 04:22:53 +00:00
drdev
dccf428bb8 Support laying out panels in region display 2014-12-06 04:14:18 +00:00
drdev
ec6637bab7 Add concept of conquest actions 2014-12-06 00:45:51 +00:00
drdev
5a2ae84954 Version bump to 1.5.32.006 2014-12-05 23:49:33 +00:00
Agetian
e0e08989b6 - Fixed a NPE caused by clicking on the picture of a booster pack (or another non-card entity) in quest shop. 2014-12-05 05:06:17 +00:00
elcnesh
ace28a2f06 Add Shared Fate to new cards. 2014-12-03 14:54:51 +00:00
elcnesh
e7803b0572 - For face-down cards you can see, always display their face-up image for easier browsing through morphs.
- Don't display face-down cards in library/hand/exile as creatures.
2014-12-03 14:54:27 +00:00
Sloth
ad13c89422 - Added the medium quest deck Wonder Twins 2 (by tojammot) 2014-12-03 12:27:51 +00:00
elcnesh
ea23bb33b2 Codechanges and lots of fixes related to playing other player's cards from exile.
- Cards now keep track of who's allowed to cast them, fixing possible issues in multiplayer.
- Face-down cards can now be properly looked at when allowed to by a static ability.
- Improve support for casting a face-down exiled card in general.
- Add Shared Fate (including AI support).
2014-12-03 08:49:49 +00:00
Agetian
4ae2687478 - Fix the background music not working. 2014-12-03 04:49:02 +00:00
drdev
3c13e46193 Clear warnings 2014-12-02 23:20:09 +00:00
drdev
871681c0aa Add onFinished runnable to ForgeTransition 2014-12-02 23:11:17 +00:00
drdev
a7534d15e4 Start working on API to support transition animations 2014-12-02 23:07:57 +00:00
Chris
bce1831b95 Added new card names to changes.txt. 2014-12-02 20:52:02 +00:00
swordshine
2de56b09cc - C14: Added Loreseeker's Stone 2014-12-02 13:33:50 +00:00
swordshine
00753f486f - C14: Added Domineering Will and Infernal Offering 2014-12-02 13:11:05 +00:00
swordshine
a29260e846 - C14: Added Incite Rebellion 2014-12-02 10:54:06 +00:00
elcnesh
06681655c3 Non-functional change for Java 8 compatibility. 2014-12-02 08:28:05 +00:00
swordshine
f918978462 - Converted "Deplete" to a subability 2014-12-02 05:25:10 +00:00
drdev
e43884d298 Fix mana symbol order in test 2014-12-02 04:59:44 +00:00
swordshine
296eccdce3 - C14: Added Assault Suit 2014-12-02 04:55:45 +00:00
drdev
c541972527 Fix so correct text displays for flipped state in details view 2014-12-02 04:50:21 +00:00
drdev
6c7783d8d7 Fix P/T displayed when flipping morph cards 2014-12-02 04:36:03 +00:00
drdev
1bb451469b Code cleanup 2014-12-02 04:22:46 +00:00
drdev
dc93196b56 Fix crash when starting game 2014-12-02 04:18:45 +00:00
drdev
905eb0bb1f Fix P/T display for alternate state 2014-12-02 04:10:20 +00:00
drdev
e688d78781 Prevent showing flip icon for split cards in zoom view 2014-12-02 03:35:05 +00:00
drdev
7ce9a53cb0 Version bump to 1.5.32.005 2014-12-02 03:26:03 +00:00
Myrd
5b8014cb3b If the pic for a token doesn't exist, try loading one that doesn't have the set name suffix. 2014-12-02 03:16:04 +00:00
drdev
3590fc3891 Support flipping card on zoom view for mobile app 2014-12-02 03:05:59 +00:00
drdev
ec29cd8eca Cleanup warnings 2014-12-02 02:23:59 +00:00
drdev
5a6394cf34 Make zoom activate message more specific to the available abilities of a card 2014-12-02 01:52:01 +00:00
drdev
8bff9ff14b Prevent flashback cards losing their display area if graveyard open 2014-12-02 00:13:50 +00:00
Myrd
bc29bc0d50 No need to prompt user to select a color when convoking with a mono-color creature. Just use mana of the creature's color. (It can be converted to colorless if needed.) 2014-12-01 18:27:58 +00:00
swordshine
597334a66a - C14: Added Wave of Vitriol 2014-12-01 11:54:57 +00:00
Agetian
a9f05080f9 - Added a missing test dependency (junit.framework). 2014-12-01 09:15:18 +00:00
Myrd
53ca260a57 When looking for music to play, ignore non-file entities (e.g. .svn directories). 2014-12-01 06:12:55 +00:00
Myrd
a63f46414a Fix issue where a spell's target wouldn't be correctly shown in the game log message.
The problem was that by the time the log sees the spell, its target has been swapped with the stack ability.
2014-12-01 06:12:05 +00:00
Myrd
319cd97d83 Fix game log revealing opponent's morphed creatures in messages. 2014-12-01 06:09:54 +00:00
Myrd
b3a2ca8291 When attacked by morph creatures, show the word "Morph" when referring to the creature. 2014-12-01 06:08:46 +00:00
Myrd
73cad47c3c Fix bug with convoke where colored mana could end up being used as colorless.
Before this patch, the code would try to pay the mana symbols as they appear - for example if you convoke with a white creature and click "white" in the dialog, but the cost for the spell is "1WW", it would actually use that white mana to pay for the "1" portion of the cost, leaving "WW" to be paid (which is problematic if you have a swamp and a plains untapped which you were planning to use in addition to the white creature).

This change moves the logic for paying the cost from the UI code to the engine code (and re-uses existing code there) and also adds some unit tests for it.
2014-12-01 06:06:57 +00:00
Myrd
6c2347a261 Fix bug where card draw animations are shown even if you're in another tab (e.g. if you made two AIs play). 2014-12-01 06:03:27 +00:00
drdev
000241a875 Fix so canceling selecting an ability doesn't show zoom 2014-12-01 03:41:02 +00:00
drdev
c1238ed77b Prevent crash when activating card from zoom with multiple abilities 2014-12-01 02:51:44 +00:00
drdev
cd10a307bd Prevent calling activate if activateAction is null 2014-12-01 02:49:34 +00:00
Chris
a7dbf0ea6c Cleared out the changes.txt file, now ready for new material 2014-11-30 22:18:30 +00:00
drdev
15a102e895 Make zoom activation more flexible 2014-11-30 19:02:41 +00:00
drdev
7857f996e1 Version bump to 1.5.32.004 2014-11-30 18:05:52 +00:00
drdev
a1bdfefba6 Fix crash when zooming just single card 2014-11-30 18:01:48 +00:00
drdev
380c0b9afe Fix proportions of zoom view cards and bump version to 1.5.32.003 for quick fix 2014-11-30 15:32:30 +00:00
drdev
35f8f08041 Fix activation from zoom view for deck editor 2014-11-30 14:58:45 +00:00
drdev
05b0b7af54 Fix so selected item scrolls into view 2014-11-30 07:08:21 +00:00
drdev
5eeb302ce8 Add activate callbacks for zoom view 2014-11-30 07:05:40 +00:00
drdev
314e8242bc Tweak text color 2014-11-30 06:32:07 +00:00
drdev
3ee75a026e Add header and footer to zoom 2014-11-30 06:18:39 +00:00
drdev
931e44b213 Use swipe down to change between zoom and details 2014-11-30 05:59:02 +00:00
drdev
0b8c23990c Fix details view 2014-11-30 05:52:12 +00:00
drdev
4e2f753374 Refactor so CardZoom can support multiple cards 2014-11-30 04:14:14 +00:00
drdev
27980776d0 Disable Planar Conquest mode for now 2014-11-29 22:54:23 +00:00
drdev
83970030d5 Support flick action in place of Shift+click for mobile game 2014-11-29 22:49:49 +00:00
drdev
3c06c7ea81 Revert previous change 2014-11-29 22:38:36 +00:00
drdev
d3d8fc8c78 Support raising two finger tap event 2014-11-29 18:15:52 +00:00
drdev
6c2b7351ba Version bump to 1.5.32.001 2014-11-29 17:17:57 +00:00
drdev
9e2c0bfcf6 Add Shift+click support for Mana Pool icons 2014-11-29 17:06:45 +00:00
drdev
4fe33c6c9b Prevent crash in CardDetailPanel::setCard 2014-11-29 16:41:45 +00:00
drdev
bc0366813b Update Maven dependencies for mobile game 2014-11-29 16:33:36 +00:00
Sloth
f57df312c0 - Improved AI handling Mishra's Factory. 2014-11-29 12:03:55 +00:00
Sloth
e69385abb0 - Updated 2 quest decks. 2014-11-29 10:47:54 +00:00
Sloth
1802372fbe - Added the medium quest opponent Scarecrow 2 (by Nordos). 2014-11-29 10:43:54 +00:00
Chris
313c439d40 [maven-release-plugin] prepare for next development iteration 2014-11-28 15:37:56 +00:00
Chris
5361ac01c1 [maven-release-plugin] prepare release forge-1.5.31 2014-11-28 15:37:42 +00:00
Chris
1fcebd894a Preparing the changes.txt file for the next beta build and release. 2014-11-28 14:55:03 +00:00
Sloth
f1c092d41e - Updated the quest deck Owlman 3 (by Nordos). 2014-11-28 14:06:54 +00:00
drdev
4990887b98 Prevent using Shift+click to attack with cards that have summoning sickness 2014-11-27 03:55:33 +00:00
Sol
2b4cba7e14 - Fixing the Duel Decks whose Titles were inverted (Also changing "vs" to "as" for clarity) 2014-11-27 03:35:29 +00:00
drdev
09344f2302 Update CHANGES.txt 2014-11-27 03:33:08 +00:00
Sol
a66019b9d9 - Use local parent folder for loading in human deck in duel deck quest matches 2014-11-27 03:30:35 +00:00
drdev
361b0b69d9 Support using Shift+click to attack with an entire stack of creatures 2014-11-27 03:27:33 +00:00
drdev
513a8def41 Support using Shift+click to tap multiple lands while paying for a spell 2014-11-27 03:12:46 +00:00
drdev
960cded6d6 Code cleanup 2014-11-27 02:29:14 +00:00
drdev
4c6bd6a715 Prevent race condition when selecting multiple abilities using Shift+click 2014-11-27 02:05:26 +00:00
drdev
2cb2c266b3 Make Shift+tap and two finger tap select entire stack for mobile game 2014-11-27 00:44:33 +00:00
drdev
073db00909 Remove double-click as way to select entire stack 2014-11-27 00:27:29 +00:00
Sloth
900a3cf32e - Added Mirrodin quest world by serrasmurf. 2014-11-26 22:49:53 +00:00
drdev
043304e35b Support double-click and Shift+left click to tap all lands in the same stack 2014-11-26 20:47:47 +00:00
drdev
61af57d7ba Fix to ensure cards in stack not linked to stack aren't checked twice 2014-11-26 20:26:33 +00:00
drdev
7c7163b511 Add support for tapping the topmost card of a stack to activate the card behind if the card on top has no remaining actions (same as mobile game already supports) 2014-11-26 20:22:48 +00:00
drdev
74c579c286 Add support for passing other cards in stack to inputs upon double-click and shift+left 2014-11-26 19:17:30 +00:00
drdev
af3af33b50 Fix typo in CHANGES.txt 2014-11-26 17:44:51 +00:00
drdev
7de4e77eb8 Reduce flicker during zone window resize 2014-11-26 17:44:33 +00:00
drdev
d31212c9a9 Code cleanup 2014-11-26 17:22:06 +00:00
drdev
037b7e62ee Prevent horizontal scrollbar appearing in zone windows. 2014-11-26 17:19:40 +00:00
drdev
4ba11947ca Auto-hide floating zone window after last card removed from it
Reduce default size of zone windows slightly
2014-11-26 17:11:29 +00:00
drdev
352d7aeacd Support remembering zone window locations between sessions 2014-11-26 16:51:25 +00:00
drdev
c0e01d343a Change default phase stops 2014-11-26 15:54:50 +00:00
drdev
fa74874555 Code cleanup 2014-11-26 15:16:27 +00:00
drdev
3085a09b2b Make it so clicking zone icon a second time hides the window 2014-11-26 14:31:49 +00:00
drdev
0165c58320 Improve background around monitor 2014-11-26 05:09:49 +00:00
drdev
e8c7a23724 Add more style to Planar Map screen 2014-11-26 05:00:50 +00:00
drdev
23773e3e87 Improve map layout more 2014-11-26 04:02:22 +00:00
drdev
6840df7f35 Improve Planar Map layout 2014-11-26 03:40:22 +00:00
drdev
be7a3bfad2 Add background for Planar Map screen
Remove unused images
2014-11-26 03:26:18 +00:00
drdev
1dc2ff3aeb Tweak map layout 2014-11-25 22:10:06 +00:00
drdev
74ed949717 Add plane name and End Day button to bottom of map screen 2014-11-25 22:01:49 +00:00
drdev
288113ae88 Add validation logic to conquest prefs
Prevent crash when clearing numeric field
2014-11-25 21:43:44 +00:00
drdev
c3e6c1e6b5 Add more planar conquest prefs
Add TEST_MODE setup for Planar Conquest testing
2014-11-25 21:10:47 +00:00
elcnesh
871272971e Draw effects with orange border to make them easier to distinguish from normal cards. 2014-11-25 20:14:07 +00:00
Sloth
e3cb0481a2 - Added the hard quest opponents Regigigas 3 and Solaire 3 (by tojammot). 2014-11-25 13:37:32 +00:00
Sloth
548574484d - Added AI support for Flash Foliage. 2014-11-25 13:25:55 +00:00
Sloth
5629895c22 - Improved LifeGainAi. 2014-11-24 23:13:22 +00:00
elcnesh
86dac0ea8c Add Flash Foliage. 2014-11-24 17:33:17 +00:00
elcnesh
2d02fbcc1d Prevent possible issue with new deathtouch implementation concerning indestructible creatures. 2014-11-24 15:56:56 +00:00
Chris
b7c550a49f Added new card names to changes.txt. 2014-11-24 15:46:16 +00:00
Sloth
bd40daa905 - Added AI support for Grim Monolith. 2014-11-24 13:56:06 +00:00
Sloth
1dd2925f81 - Updated 2 SVars. 2014-11-24 13:12:23 +00:00
drdev
6d1e94cb53 Add support for configuring wins per commander unlock 2014-11-24 04:49:56 +00:00
drdev
4d8d2e3cbc Add lock icon 2014-11-24 04:35:57 +00:00
drdev
8ccda655d1 Render wins to unlock commanders 2014-11-24 04:11:42 +00:00
drdev
e17f55b39e Add commander row 2014-11-24 03:55:45 +00:00
drdev
471f866d06 Fix regions for Mirrodin 2014-11-24 02:33:18 +00:00
Sloth
bff7f28000 - Added Myriad Landscape.
- Fixed chooseSomeType AI function for land types.
2014-11-23 22:33:28 +00:00
drdev
e2659b5cd1 Improve display of region slider 2014-11-23 18:55:38 +00:00
drdev
5b001fd296 Add support for displaying region 2014-11-23 17:18:26 +00:00
elcnesh
d7943d767f Change deathtouch into a state-based action (as specified by the comp rules) rather than directly destroying the creature, fixing some bugs related to triggers. 2014-11-23 14:51:41 +00:00
drdev
2e5202e9f1 Add commander and his deck to collection when commander added to your arsenal 2014-11-23 05:39:35 +00:00
drdev
aeea51cb28 Remove unused imports 2014-11-23 05:34:33 +00:00
drdev
757af3b04d Refactor promptForName into static utility class 2014-11-23 05:33:58 +00:00
drdev
060fcba17d Fix load conquests screen
Prevent crash if you pause during startup
2014-11-23 05:29:28 +00:00
drdev
a17394f36d Fix display of map screen
Fix so deck gets saved
2014-11-23 05:19:04 +00:00
drdev
769b5c1b37 Support generating deck for planar conquest commander 2014-11-23 05:11:23 +00:00
Sol
86f738a81f - Fixing card type of Crater's Claws 2014-11-23 05:09:56 +00:00
Sol
449d1acd4e - Fixing Kyoki not targeting opponents 2014-11-22 15:52:25 +00:00
Sol
4537ddbd3e - Improve usability of Channel's effect (allow you to pay multiple life at a time) 2014-11-22 15:51:16 +00:00
swordshine
13013b1fd4 - C14: Added Siege Behemoth 2014-11-22 13:07:09 +00:00
drdev
d255b29cad Flesh out Jamuraa regions
Remove TSB from Dominaria
2014-11-22 06:06:02 +00:00
drdev
f62312ab07 Flesh out art for Dominaria and Shandalar regions 2014-11-22 05:46:15 +00:00
drdev
74f159c420 Flesh out Dominaria, Shandalar, and Jamuraa planes 2014-11-22 04:59:44 +00:00
drdev
d0b39a7c2c Flesh out Ravnica plane 2014-11-22 03:22:30 +00:00
drdev
050ec2b4bd Flesh out Rath plane 2014-11-22 02:55:06 +00:00
drdev
f24a7c8cd9 Flesh out Alara plane 2014-11-22 00:27:54 +00:00
drdev
446849c563 Flesh out Innistrad plane 2014-11-22 00:11:50 +00:00
drdev
28ded53c25 Flesh out regions some more 2014-11-21 23:46:52 +00:00
drdev
f3feb28009 Fix filename for Mercadian Bazaar 2014-11-21 23:07:11 +00:00
drdev
e29905d6b3 Remove planes with no associated sets 2014-11-21 22:49:55 +00:00
drdev
c17cd296dd Flesh out Lorwyn plane 2014-11-21 22:48:01 +00:00
drdev
50da0900d1 Flesh out planes some more 2014-11-21 20:17:03 +00:00
drdev
2bb3951f40 Support sorting commanders 2014-11-21 18:46:49 +00:00
drdev
3bccb98607 Initial commit for Planar Conquest mode 2014-11-21 18:13:38 +00:00
Sloth
ede4c1bc7c - Cleanup and little improvements in EffectAi. 2014-11-19 22:49:22 +00:00
Chris
2e0a109261 Cleared out the changes.txt file, now ready for new material. 2014-11-19 16:08:34 +00:00
Sloth
29e76febf5 - Added the hard quest opponent Zeus 3. 2014-11-19 15:37:57 +00:00
Sol
66ef7c5105 - Fix timing of Scheme triggers not working 2014-11-19 04:13:40 +00:00
Sol
13d744d2bd - Fix typo in Scrap Mastery 2014-11-19 03:44:55 +00:00
Sol
61a58bcafa - Fix Hurkyl's Recall 2014-11-19 03:37:42 +00:00
Sol
c707ef60b0 - Fix Distant Memories 2014-11-19 03:21:06 +00:00
Sol
643ce57a29 - Adding a setting for Pausing Forge While Minimized (especially useful during Forge Tournaments) 2014-11-19 02:33:14 +00:00
Sol
c0b5b6abdc - Log when players discard cards instead of forcing people to open up the graveyard each time to find out what was discarded 2014-11-18 03:21:12 +00:00
Sol
6a148946ae - FIx Combat from getting cleared out until EndCombat ends 2014-11-18 01:15:12 +00:00
drdev
88501c4311 Fix so pressing back from sealed deck editor takes you to sealed deck play screen 2014-11-17 04:05:56 +00:00
drdev
21ab65c61b Fix so LoadDraftScreen opened when finished editing draft deck 2014-11-17 04:03:45 +00:00
Sol
2fea283147 - Triggers on Effects get activated when it moves into the Command zone, no need to add it twice. 2014-11-17 03:42:00 +00:00
drdev
944f64a213 Remove name for new game mode from home screen 2014-11-17 03:31:57 +00:00
drdev
63a20b0996 Refactor Draft and Sealed Screens into a single Limited screen with two offshoot screens for loading existing drafts/decks 2014-11-17 03:29:20 +00:00
drdev
b10dbf687b Update pom files for mobile game 2014-11-17 02:06:33 +00:00
Sol
3f50a72555 - Small tweak to Scry's arrange top of library message 2014-11-17 00:47:01 +00:00
Sol
5fa122a8d9 - When flipping multiple coins due to Krark's Thumb, the player should call heads/tails only once 2014-11-15 02:30:11 +00:00
Sol
7c68513818 - Fixing Song of the Dryads script 2014-11-14 23:52:33 +00:00
Chris
9663a86c82 [maven-release-plugin] prepare for next development iteration 2014-11-14 14:54:13 +00:00
Chris
bc1b9b955b [maven-release-plugin] prepare release forge-1.5.30 2014-11-14 14:53:50 +00:00
Chris
4db46b87b0 Preparing the changes.txt file for the next beta build and release. 2014-11-14 14:13:52 +00:00
Sol
0a1f5d19e7 - Fix Essence of the Wild interaction with ETB creatures 2014-11-14 02:57:21 +00:00
Sol
8378776ccc - Inverting Static bonuses granted by Angelic Field Marshal 2014-11-14 02:21:10 +00:00
Sol
0ff29e937c - Adding Oracle text to C14 cards 2014-11-13 03:28:03 +00:00
Sol
b449e7b4dc - Small fixes to Triggers related to Clones and CopyPermanent triggering the wrong number of times 2014-11-13 03:16:04 +00:00
Sol
193bfec65f - Reset the shoplist after the first game, so ante cards are available with the appropriate quest item 2014-11-13 02:28:33 +00:00
drdev
acdb847b66 Support surrounding search strings in quotations 2014-11-13 01:34:15 +00:00
drdev
a9865cf7bb Remove unused import 2014-11-13 01:08:44 +00:00
drdev
c76b2b1554 Comment out unhelpful gui errors (at least at this time) 2014-11-13 00:55:15 +00:00
drdev
5af7f61c08 Fix achievement for Vraska the Unseen 2014-11-13 00:32:57 +00:00
drdev
755b21586b Fix achievements for Gideon Jura and Tezzeret Agent_of_Bolas 2014-11-13 00:25:42 +00:00
drdev
3819b07fa4 Show text cursor when over FTextEditor 2014-11-13 00:20:20 +00:00
drdev
e21f6da7c9 Fix name of Ob Nixilis of the Black Oath emblem 2014-11-13 00:17:53 +00:00
drdev
038854e6e8 Prevent Mother of Runes targeting creatures you don't control 2014-11-13 00:12:34 +00:00
Sol
8d7fa4257b - Updating mtgdata for C14 2014-11-12 01:21:28 +00:00
Chris
d2553e7844 Added new card names to changes.txt. 2014-11-12 00:23:44 +00:00
swordshine
70b8b26d44 - C14: Added Fell the Mighty 2014-11-11 08:42:18 +00:00
swordshine
e0d0a78071 - C14: Added Intellectual Offering and Sylvan Offering 2014-11-11 06:10:12 +00:00
swordshine
626660cfce - Fixed last commit 2014-11-11 05:54:02 +00:00
swordshine
7faa5b262d - C14: Added Benevolent Offering 2014-11-11 05:49:09 +00:00
drdev
6d2e2b960f Version bump to 1.5.30.003 2014-11-11 05:02:42 +00:00
drdev
a8ab3ecd67 Fix image downloading for Android 2014-11-11 04:49:15 +00:00
swordshine
b63586920c - C14: Added Wolfcaller's Howl 2014-11-11 03:14:33 +00:00
drdev
d4a5a69fb8 Version bump to 1.5.30.002 2014-11-11 03:03:01 +00:00
drdev
e116054e84 Prevent crash when ending Commander game 2014-11-11 03:01:23 +00:00
swordshine
588b99b576 - C14: Added Crown of Doom 2014-11-11 02:26:28 +00:00
Sloth
2f0d3b524a - Added SVar:PlayMain1:TRUE to Tamiyo, the Moon Sage to tap blockers. 2014-11-10 21:55:07 +00:00
Sloth
350c5ffc72 - Improved Curse Pump AI. 2014-11-09 16:07:15 +00:00
Sloth
08ae76d51d - Updated some quest decks. 2014-11-09 15:52:03 +00:00
Sloth
356c8bd2d4 - More AI improvements for Ajani Vengeant and Koth of the Hammer. 2014-11-09 13:58:29 +00:00
Sloth
a1d44f3068 - Added SVar:SacMe:4 to Tuktuk the Explorer. 2014-11-09 10:36:20 +00:00
Sloth
2a97feb159 - Prevent AI from casting spells with "May be played" from the Stack. 2014-11-09 09:21:08 +00:00
Sloth
9e87c08fe3 - Fixed removeAllExtrinsicKeyword. 2014-11-09 08:12:24 +00:00
Chris
9ab73c8565 Added new card names to changes.txt. 2014-11-09 01:28:55 +00:00
Sloth
05b3fa2644 - Added activateForCost part to PumpAI. 2014-11-08 22:30:03 +00:00
Sloth
9831eeba45 - Improved AI using The Chain Veil. 2014-11-08 21:49:19 +00:00
Sloth
7bbc917998 - Improved AI using Koth of the Hammer. 2014-11-08 21:46:30 +00:00
Sloth
14196fedc1 - AI will now play Moxen in Main1. 2014-11-08 21:43:06 +00:00
Sloth
d572f506de -Improved AI using Sarkhan, the Dragonspeaker. 2014-11-08 21:35:31 +00:00
Sloth
43a32b9f89 - Merged C14 branch into trunk. 2014-11-08 16:28:44 +00:00
Sloth
e19a17eed2 - Fixed Endless Ranks of the Dead (by Zirbert). 2014-11-08 07:28:49 +00:00
Sol
83866e654c - Small tweaks to Taigam's Scheming 2014-11-07 00:31:04 +00:00
swordshine
57b4af24e7 - C14: Added Nahiri, the Lithomancer 2014-11-06 10:27:01 +00:00
swordshine
403abd0a06 - C14: Added Grave Sifter 2014-11-06 08:07:40 +00:00
drdev
dc8ee819e5 Hide Online Lobby until there's something to do there 2014-11-06 03:00:23 +00:00
Sloth
b46c4292b6 - Little improvements in AttachAi. 2014-11-05 23:12:53 +00:00
Sloth
c0073f61cf - Added the hard quest deck Edward Scissorhands 3. 2014-11-05 12:17:24 +00:00
Sloth
021326a0f9 - Updated SVars and 2 quest decks. 2014-11-05 12:08:49 +00:00
Sloth
230ea2c61d - Cleanup. 2014-11-05 12:08:04 +00:00
swordshine
ea826ec107 - C14: Added edition file 2014-11-05 04:45:34 +00:00
Sol
7d5b8bc80a - Fix Elixir of Immortality not shuffling library if controller's graveyard is empty. 2014-11-05 01:28:46 +00:00
Sloth
425de15b48 - Improved AI using Remand. 2014-11-04 11:21:31 +00:00
Sol
de4e8e0831 - Fix "tap and hold" cards not remembering the target if it's already tapped 2014-11-04 04:14:03 +00:00
Sloth
feeec5d592 - Delve and Convoke will now happen after cost reduction. 2014-11-03 19:55:57 +00:00
Sloth
adcbce9f8f - Add even more new card names to changes.txt! 2014-11-03 12:11:06 +00:00
elcnesh
41a9403635 Add more new card names to changes.txt. 2014-11-03 10:44:33 +00:00
Chris
5d06efe79f Added new card names to changes.txt. 2014-11-02 15:07:03 +00:00
swordshine
c6424c18b7 - C14: Added Ob Nixilis of the Black Oath 2014-11-02 14:40:52 +00:00
elcnesh
a1edebd72a Add Oracle text to Magnetic Web. 2014-11-02 08:22:04 +00:00
elcnesh
c0d156856a Add Magnetic Web. 2014-11-02 08:18:17 +00:00
swordshine
9036cc33a9 - C14: Added Freyalise, Llanowar's Fury 2014-11-02 05:32:10 +00:00
Sloth
fe770a48ba - Added a new AI SVar: AmbushAI. Creatures with it will be played when the opponent is attacking. 2014-11-01 20:37:38 +00:00
Sol
b9864a2a23 - Xathrid Necromancer missing "Other" property for one half of its check 2014-11-01 15:18:58 +00:00
Sloth
36dd214785 - Reverted accidental commit of project file. 2014-11-01 14:40:31 +00:00
Sloth
3f58421a53 - Triggers with a cost will no longer ask you whether you want to use them before paying the cost. 2014-11-01 14:37:43 +00:00
Sloth
676c876f14 - Added card property "wasNotCast" for Containment Priest. 2014-10-31 22:04:20 +00:00
Sloth
8cc1842385 - Temporary fix for "View all Cards" dev button not working. 2014-10-31 14:05:38 +00:00
swordshine
c46b1bfea1 - Updated new planeswalker types 2014-10-31 08:40:56 +00:00
swordshine
d3699f3975 - Updated oracle texts 2014-10-31 08:38:26 +00:00
Sol
a0ff839c0e - Martyr's Bond primary trigger needs to have "Other" 2014-10-30 23:24:12 +00:00
elcnesh
57a09f275f Refactor attack declarations.
The game now correctly calculates whether an attack declaration is legal, based upon the restrictions and requirements present on the possible attacking creatures. AI support is not yet fully implemented, but the AI can always default to a legal attack declaration.
2014-10-30 15:44:13 +00:00
Sloth
04659d111b - Better fix for granted abilities (more in line with drdevs changes).
- Also Fixed Border color of detail panel.
2014-10-29 13:51:26 +00:00
Sloth
84500caf71 - Fixed abilities granted by static effects not appearing in the card detail panel. 2014-10-29 11:53:27 +00:00
Sol
d796f1b04f - More trigger tweaks (Harmonic Sliver) 2014-10-29 03:22:52 +00:00
Sloth
5f499f6af9 - AI will no longer play Ball Lightning and friends when his combat phase will be skipped. 2014-10-28 21:36:23 +00:00
Sloth
65c2fd5298 - Added a new AI SVar: NoZeroToughnessAI. Creatures with it will be played even when their toughness is zero. 2014-10-28 21:24:44 +00:00
Chris
6f11c238fc Added new card names to changes.txt. 2014-10-28 16:12:23 +00:00
Sloth
d52f8a6de7 - Expanded the canGainKeyword AI function to take targeted abilities into account. 2014-10-28 13:23:27 +00:00
Sloth
be7511c6b7 - Improved AI using Dauthi Mindripper and Mindstab Thrull. 2014-10-28 09:33:22 +00:00
Sloth
63cc278111 - Fixed triggers with costs being optional (and not every trigger). 2014-10-28 08:16:00 +00:00
Sol
d1858226ff - Fixing Snow Devil granting First strike to all blockers you control 2014-10-28 03:34:46 +00:00
Sloth
c639d71dcc - Added "AITgts$ BetterThanSource" to some more cards. 2014-10-27 21:01:41 +00:00
Sloth
57a9fc2710 - Added AI support for Blind Zealot and Necrite. 2014-10-27 20:15:44 +00:00
Sloth
7ff491bfd3 - Triggers with a cost are now always optional. 2014-10-27 20:09:38 +00:00
Sol
c7838056a4 - Fixing Flayer of the Hatebound not having an active trigger when it is in the graveyard. 2014-10-27 02:34:16 +00:00
Sloth
0cc2ece573 - The AI will now be aware of opponents Royal Assassin and similar cards. 2014-10-26 19:51:55 +00:00
drdev
bf6209734b Fully remove login dialog 2014-10-26 19:07:40 +00:00
drdev
164f31f1ad Remove use of login dialog 2014-10-26 19:05:22 +00:00
Sloth
baf0af3a24 - Added the new AI function "hasAFogEffect". 2014-10-26 15:24:42 +00:00
Sloth
3da6b32a7b - Cleanup. 2014-10-26 13:19:30 +00:00
Sloth
6d82637767 - Fixed Goblin Guide not revealing the card to the opponent. 2014-10-26 11:06:19 +00:00
Sloth
1c9c52839c - Small fix for Orcish Captain. 2014-10-26 10:58:31 +00:00
Sloth
242b510f26 - Improved CountersPutAi. 2014-10-26 08:39:17 +00:00
Sloth
c8e538da45 - Fixed human payment of the ability of Night Soil. 2014-10-26 07:25:26 +00:00
drdev
a19d4b8d62 Add Enter key handlers to username and password fields 2014-10-26 02:24:57 +00:00
drdev
1ec2fbf00d Add password field 2014-10-26 02:06:43 +00:00
drdev
9827880c47 Create login dialog
Flesh out some structure for having PHP files to govern server access
2014-10-26 02:06:21 +00:00
Sloth
02a5997810 - Improved stack description of FlipCoinEffect.
- Added AI support for Orcish Captain.
2014-10-25 21:35:46 +00:00
Sloth
264458521a - Added AI support for Armor Thrull. 2014-10-25 21:16:44 +00:00
drdev
b4ed726de1 Create shell for Online Multiplayer Lobby 2014-10-25 21:15:34 +00:00
drdev
0c3e46dbf5 Code cleanup 2014-10-25 20:25:19 +00:00
swordshine
da824e6fc0 - C14: Added Angelic Field Marshal 2014-10-25 04:14:36 +00:00
Sloth
4991ea22fa - Improved AI using Merseine. 2014-10-24 15:01:16 +00:00
Sloth
00a756833d - Cleanup. 2014-10-24 14:52:59 +00:00
Sloth
8f90f65371 - Added Merseine. 2014-10-24 14:22:10 +00:00
Sloth
1abd41b469 - Fixed crash when starting a Vanguard game. 2014-10-24 12:56:52 +00:00
Sloth
bde503b4fa - Fixed crash caused by the -2 of Chandra, the Firebrand. 2014-10-24 12:05:15 +00:00
Sloth
9deafa0be7 - Fixed a rare bug in runNonStaticTriggersForPlayer. 2014-10-24 11:56:48 +00:00
Sloth
efeca084c1 - Added Fat Pack prices (by Fizanko). 2014-10-24 08:15:21 +00:00
Agetian
14db79e126 - Fix targeting arrows not appearing for stack items in "On Mouse Over" targeting overlay mode. 2014-10-24 06:08:53 +00:00
Sol
f8444f6559 - Add a cost description for Back from the Brink 2014-10-24 02:20:26 +00:00
drdev
791466c63b Comment out failing test (for now) 2014-10-24 00:45:14 +00:00
drdev
8e1b0bc901 Remove unused import 2014-10-24 00:33:19 +00:00
drdev
37e6a0a269 Fix MalformedUrlException when loading from XML on Android 2014-10-24 00:23:24 +00:00
drdev
eee682e659 Prevent completely suppressing MalformedURLException 2014-10-23 23:52:17 +00:00
Sloth
842040c10d - Fixed a bug in CharmAI. 2014-10-23 21:43:15 +00:00
Sloth
7fbbd150e9 - Added DeckNeeds and DeckHints SVars to KTK cards. 2014-10-23 20:19:03 +00:00
Sloth
760f21c4b0 - Updated some cards with DeckNeeds SVars. 2014-10-23 19:42:17 +00:00
Chris
d07b3de761 Cleared out the changes.txt file, now ready for new material. 2014-10-23 16:42:15 +00:00
Sloth
0105f69a69 - Added AI support for Wash Out. 2014-10-23 12:19:00 +00:00
Sloth
4d35555769 - Extended pumpAgainstRemoval for non-targeted abilities. 2014-10-23 11:31:06 +00:00
Sol
0bad8a896b - Move Requirements Check from activeTrigger to canRunTrigger fixing some issues with intervening if (Valakut/Scapeshift)
- Reverted cards with spell cast numbers back to original numbers
2014-10-23 02:32:57 +00:00
drdev
b565868ef0 Fix crash that can occur after earning an achievement 2014-10-23 00:30:18 +00:00
drdev
4ea2f48e29 Version bump to 1.5.30.001 2014-10-23 00:09:33 +00:00
drdev
3f81f64f02 Prevent concurrent modification exception when building targeting overlays 2014-10-22 23:41:03 +00:00
drdev
f5aaf233d5 Prevent crash that can occur if stack item removed while hovering over it 2014-10-22 23:28:17 +00:00
Chris
5a0b2d83b4 [maven-release-plugin] prepare for next development iteration 2014-10-22 16:01:13 +00:00
Chris
3cf8df7cf1 [maven-release-plugin] prepare release forge-1.5.29 2014-10-22 16:01:00 +00:00
Chris
394aa59488 Preparing the changes.txt file for the next beta build and release. 2014-10-22 15:05:00 +00:00
drdev
74426afa86 Update CHANGES.txt 2014-10-22 01:50:42 +00:00
drdev
22ba6cd1e7 Support showing targeting arrows for players 2014-10-22 01:36:35 +00:00
drdev
1700b8895d Avoid showing unnecessary tooltip when hovering over items on stack 2014-10-22 01:23:54 +00:00
drdev
6ee010648f Add support for showing targeting arrows when hovering over items on the stack 2014-10-22 01:11:21 +00:00
drdev
9b522a1e45 Prevent combat entry being duplicated for every attacking creature
Prevent creatures displaying as blocked in combat panel if not actually blocked
2014-10-21 21:40:25 +00:00
Sloth
25dde09dfd - Fixed text of Angel of Serenity. 2014-10-21 20:46:11 +00:00
Sloth
85f0163ef7 - Fixed Reveille Squad. 2014-10-21 20:44:47 +00:00
Sloth
a6e593d42b - Improved last fixed for BoosterDraftAI. 2014-10-21 12:53:39 +00:00
Sloth
fa513fecd2 - Fixed a logic error in the draft logic. 2014-10-21 12:18:25 +00:00
Sloth
7569e8697a - remove option to fire events from checkStaticAbilities, because it isn't (and shouldn't really be used). 2014-10-21 07:25:00 +00:00
drdev
c3d9ff5fe2 Fix crash when getting commander info 2014-10-21 02:17:44 +00:00
drdev
c586c523e7 Version bump to 1.5.29.011 2014-10-21 01:23:30 +00:00
drdev
09608d671a Fix crash when trying to switch up targeting arcs 2014-10-21 01:02:32 +00:00
drdev
2002090c18 Fix player name in message for Vendilion Clique 2014-10-21 00:58:20 +00:00
drdev
75352fd7dd Fix so token has name displayed in detail pane 2014-10-21 00:44:39 +00:00
drdev
51ffbcaeb7 Fix concurrent modification exception 2014-10-21 00:00:52 +00:00
drdev
83e548d3a4 Fix display of fake cards 2014-10-20 23:39:59 +00:00
drdev
ab626363d8 Further reduce creation of unnecessary sets 2014-10-20 22:59:18 +00:00
drdev
9ec5497321 Optimize check for state-based effects to avoid creating a new HashSet unnecessary 2014-10-20 22:39:47 +00:00
Sloth
7d8a0829ba - Fixed AI moving counters from Spike Soldier onto itself. 2014-10-20 18:41:38 +00:00
Sloth
fc5bec6b9c - Updated AI of some more cards with ChooseColor effects. 2014-10-20 14:19:48 +00:00
Sloth
66f66f5a69 - Added AI support for Jihad. 2014-10-20 13:58:37 +00:00
Sloth
77ebe105f9 - Added AI support for Oona, Queen of the Fae. 2014-10-20 12:39:52 +00:00
Sloth
80730f1924 - Added AI support for Quirion Elves. 2014-10-20 11:04:22 +00:00
Sloth
b118859260 - Added AI support for Sol Grail. 2014-10-20 10:47:38 +00:00
Sloth
ffb90ac303 - Fixed Booster Prices (by Vecc). 2014-10-20 08:00:36 +00:00
Sol
efd56b859e - Balm of Restoration missing damage prevention amount 2014-10-20 01:18:23 +00:00
Sloth
e1976f9768 - Fixed checkStaticAbilities slowing down the game unnecessarily. 2014-10-19 21:16:27 +00:00
Sloth
29a8595752 - Removed the Effect type DebuffAll. The 5 cards that used it were converted to AnimateAll. 2014-10-19 20:37:04 +00:00
Sloth
61e8793a36 - Updated some quest decks. 2014-10-19 14:58:11 +00:00
Sol
8b2afd8f8c - Switch "choose not to untap" pump effects to match how Equipment works. (Duration still incorrect if untapped before continuous effect starts) 2014-10-19 03:35:50 +00:00
drdev
6f2888cf69 Version bump to 1.5.29.010 2014-10-19 01:38:14 +00:00
drdev
e9c48ac495 Remove class that Android doesn't have access to 2014-10-19 01:36:45 +00:00
drdev
a708d5d0a3 Version bump to 1.5.29.009 2014-10-19 00:53:30 +00:00
drdev
d84659a3f0 Fix token doubling effects 2014-10-19 00:33:40 +00:00
drdev
c6d2e89d13 Fix so AI respect Annihilator amount 2014-10-19 00:15:03 +00:00
drdev
00cf0ed0ed Fix refresh issue with card display 2014-10-18 23:56:15 +00:00
drdev
af19135c2e Fix so Prossh, Skyraider of Kher properly has tokens come into play 2014-10-18 23:44:25 +00:00
drdev
49ec80ac29 Fix so card image updated in Library as revealed top card changes 2014-10-18 23:10:28 +00:00
drdev
44dabcf382 Fix so cards like Courser of Kruphix allow viewing the top card or your library 2014-10-18 22:53:01 +00:00
drdev
2d136fb70e Fix so YouMayLook field is populated 2014-10-18 22:40:53 +00:00
drdev
b81426663f Fix concurrent modification exception with Chromatic Lantern 2014-10-18 22:31:20 +00:00
drdev
72d6b1ba97 Fix so both sides of split card have text displayed when card not on stack
Fix so only the cast half of a split card has its mana cost displayed when it's on the stack
2014-10-18 22:23:05 +00:00
drdev
b6a35d4993 Fix so planeswalkers appear with proper base loyalty even when not in play 2014-10-18 21:58:25 +00:00
drdev
e3bb577f73 Optimize hasImage check for paper cards by caching whether or not an edition has any images downloaded and avoiding the file exists checks if not 2014-10-18 21:52:37 +00:00
Sloth
0948cdb133 - Added AI support for Frenetic Efreet. 2014-10-18 20:17:12 +00:00
Sloth
ab9fc96f3e - The PlayMain1 AI SVar now has the distinctions "TRUE", "ALWAYS" and "OPPONENTCREATURES". 2014-10-18 19:53:49 +00:00
Sloth
8089d73ce9 - Targeting of triggered abilities is always mandatory. 2014-10-18 19:20:17 +00:00
Sloth
94e5b1fee7 - Fix for Valakut, the Molten Pinnacle (the script is still not really correct) 2014-10-18 18:49:42 +00:00
Sloth
f0f1507d02 - Fixed Soratami Seer. 2014-10-18 16:05:03 +00:00
Sloth
d0b4c9e734 - Fixed some AILogics not reseting targets in PumpAI. 2014-10-18 10:57:07 +00:00
Sloth
ac3afcb9aa - Fixed Heroes' Podium (by aescula). 2014-10-18 10:39:48 +00:00
drdev
ced735065b Version bump to 1.5.29.008 2014-10-18 02:48:14 +00:00
drdev
7a55bd6c48 Fix so cards like Clone enter the battlefield properly with immediately dying 2014-10-18 02:42:20 +00:00
drdev
8ded13b94f Remove comment 2014-10-18 01:32:09 +00:00
drdev
7a70b4ce39 Fix so scry card shows the correct art 2014-10-18 01:29:53 +00:00
drdev
cd9a333bd0 Optimize image loading logic a bit 2014-10-18 01:00:22 +00:00
drdev
652e7c2238 Avoid showing IDs for hidden cards 2014-10-18 00:36:37 +00:00
drdev
df378e7a13 Fix so cards revealed from hidden zones don't remain visible in those zones afterward 2014-10-18 00:18:46 +00:00
drdev
5b600bf592 Fix so cards with multiple subtypes have them appear in the correct order 2014-10-18 00:05:14 +00:00
Sloth
81e2815cbe - Fixed InputSelectCardsForConvoke. 2014-10-17 19:54:00 +00:00
Sloth
0c43d3a829 - Fixed and improved getWorstLand AI function. 2014-10-17 18:45:37 +00:00
Sloth
532b8b7e4b - Fixed two FindBugs results. 2014-10-17 16:56:52 +00:00
Sloth
b2707e9e13 - Make some more use of the isCardInPlay function. 2014-10-17 14:41:24 +00:00
Sloth
cf52edd1bc - Expanded getCardPreference AI function. 2014-10-17 14:08:44 +00:00
Sol
7f958ced12 - AI will now draft off-color good cards more aggressively (This number may need to be tweaked again) 2014-10-17 02:23:26 +00:00
Sol
32440f23f0 - Balduvian Rage missing second half of its spell description 2014-10-17 02:17:24 +00:00
drdev
f556d79f88 Fix bug with milling 2014-10-17 01:04:08 +00:00
drdev
daffc297cf Version bump to 1.5.29.007 2014-10-16 20:31:34 +00:00
drdev
46c0f4a178 Prevent achievement trophies not appearing right away 2014-10-16 20:22:29 +00:00
drdev
3e768739f6 Fix floating zone windows between games 2014-10-16 20:07:11 +00:00
drdev
1fa8e0553b Update CHANGES.txt 2014-10-16 19:01:40 +00:00
drdev
08d714f635 Fix so the most recent edition with art appears in ItemManagers 2014-10-16 18:48:33 +00:00
drdev
1859fd1c4f Prevent randomly selecting version of a card that doesn't have art available when there's another version where art is available 2014-10-16 18:22:48 +00:00
drdev
5ba5b70f1f Refactor some the image loading code into forge-core 2014-10-16 16:17:18 +00:00
drdev
0ac7ed44dc Prevent avatar, life, zone, and mana labels from being able to receive focus 2014-10-16 14:57:52 +00:00
drdev
64c1d25b82 Prevent cards that die from state-based effects sticking around on the battlefield 2014-10-16 14:50:42 +00:00
Sloth
aac38e4633 - Added the medium quest opponent Gix 2. 2014-10-16 13:05:28 +00:00
Sloth
ac43f7d229 - Tweaked two AI functions. 2014-10-16 12:55:43 +00:00
Sloth
aa1fc8765e - Fixed Changelings. 2014-10-15 20:54:16 +00:00
drdev
a3b3027ac2 Version bump to 1.5.29.006 2014-10-15 20:53:46 +00:00
drdev
7e20b07be8 Fix so cards in flashback zone don't display in the wrong place when viewed in their actual zone 2014-10-15 20:35:15 +00:00
drdev
adc0a48cec Prevent crash if calling hasStringType with "" 2014-10-15 20:03:10 +00:00
drdev
8aa9fd050e Fix flashback zone to work more like other zones and not crash for desktop game 2014-10-15 19:53:29 +00:00
drdev
e9c0e600ec Tweak fix for isEquipped 2014-10-15 18:55:57 +00:00
drdev
5ba9a8d0f5 Version bump to 1.5.29.005 2014-10-15 18:50:30 +00:00
drdev
7c262c98e2 Fix so card name reflects alternate state properly 2014-10-15 18:44:51 +00:00
Sloth
37f44764ed - Fixed isEquipped function. 2014-10-15 18:44:18 +00:00
drdev
546269761e Fix so the ability to flip on picture/detail pane is determined properly 2014-10-15 18:34:40 +00:00
drdev
c75980335c Fix name and mana cost display for split cards 2014-10-15 18:23:15 +00:00
drdev
65f3c5da2f Fix so oracle text appears properly for split cards in editor 2014-10-15 18:01:40 +00:00
drdev
058f66c22f Fix bug that prevented being able to play a card that had been returned to your hand or put on top of your library 2014-10-15 17:30:14 +00:00
drdev
cfeb022c91 Fix so conceding works immediately for human player 2 in head-to-head 2014-10-15 16:37:54 +00:00
drdev
a831201cd7 Remove unnecessary threadSafeIterator call 2014-10-15 16:12:37 +00:00
drdev
99e2b67e04 Prevent concurrent modification exception when moving token to a zone besides the graveyard 2014-10-15 16:07:54 +00:00
drdev
ab7fb0788e Fix Mindslaver so you can actually take actions for your opponent 2014-10-15 15:33:47 +00:00
drdev
4f3bf5d6fa Fix crash with MindSlaveMaster 2014-10-15 15:03:39 +00:00
drdev
c0e852b0a3 Fix crash when opening up Nursery or Pet tabs of Bazaar 2014-10-15 14:52:47 +00:00
drdev
e1d49610d6 Version bump to 1.5.29.004 2014-10-15 04:19:08 +00:00
drdev
487e239857 Support updating floating card panels as the zones update 2014-10-15 04:16:29 +00:00
drdev
1fd2aadbde Fix so flip side of morph cards can be seen 2014-10-15 04:02:44 +00:00
drdev
c5898a0364 Support double click to hide zone popup 2014-10-15 03:51:24 +00:00
drdev
829590b072 Allow zone popup to remember size and position if closed and later reopened 2014-10-15 03:44:08 +00:00
drdev
5be609c09e Prevent being able to view information in detail pane for hidden cards
Prevent foil overlay appearing for hidden cards
2014-10-15 03:23:19 +00:00
excessum
f2289584fc - Fixed token image for Hydra Broodmaster (g_x_x_hydra.jpg) 2014-10-15 03:14:25 +00:00
drdev
6b71a89026 Fix so cards hidden in zone popup when appropriate 2014-10-15 02:43:31 +00:00
drdev
c8de1c884c Include count in title
Fix hover effect for close button
2014-10-15 02:26:45 +00:00
drdev
649056d1dc Support showing other zones in a popup window 2014-10-15 01:42:08 +00:00
drdev
6748e12d23 Fix crash when opening deck editor 2014-10-15 00:12:55 +00:00
drdev
c08a944ad3 Restore flexibility of avatar pane 2014-10-14 22:12:15 +00:00
drdev
0744df07e6 Fix so cards in hidden zones are properly hidden 2014-10-14 22:10:56 +00:00
drdev
337b03025d Fix bug where creatures wouldn't visually leave the battlefield immediately when killed 2014-10-14 20:45:00 +00:00
drdev
5f2bcc198a Lock in size of player details pane 2014-10-14 20:36:40 +00:00
drdev
da726d0268 Fix so font shrunk more appropriately 2014-10-14 20:25:11 +00:00
drdev
1315275267 Fix so Fathom Seer's morph ability can be cancelled 2014-10-14 19:08:07 +00:00
drdev
846dce0c56 Code cleanup 2014-10-14 18:50:27 +00:00
drdev
eec3efacca Fix another corner case where updateSingleCard could crash 2014-10-14 18:49:56 +00:00
drdev
aeb710d764 Allow cancelling ability of Nullmage Shephard while in the process of selecting creatures to tap 2014-10-14 18:44:49 +00:00
drdev
b73594a530 Fix so spell/abilities display properly when card clicked 2014-10-14 04:42:22 +00:00
drdev
4810d15765 Version bump to 1.5.29.003 2014-10-14 04:34:26 +00:00
drdev
da2177385b Prevent crash if trying to update an empty battlefield 2014-10-14 04:33:00 +00:00
drdev
e7ca193ad1 Prevent poison icon/number appearing more opaque 2014-10-14 04:25:56 +00:00
drdev
8e06f8e2bc Improve layout of player details 2014-10-14 04:16:07 +00:00
drdev
0137bc5eaf Improve display of avatar and life total (prevent life total getting cut off) 2014-10-14 03:57:13 +00:00
drdev
f62b93f05e Prevent aura becoming unattached when undoing land tapping 2014-10-14 03:40:19 +00:00
drdev
3e33e7fc4c Increase stack spacing a bit more 2014-10-14 03:30:19 +00:00
drdev
0804a9b632 Increase stack spacing 2014-10-14 03:26:07 +00:00
drdev
844f765ec6 Fix so auras properly attach to permanents 2014-10-14 03:18:10 +00:00
drdev
96980a9d30 Prevent getDefender crash
Optimize combat logic a bit using FCollection
2014-10-14 02:42:28 +00:00
drdev
86e3d5c9f2 Prevent blocker that's been removed during Declare Blockers from dealing combat damage 2014-10-14 02:27:30 +00:00
drdev
27ffb6ccfc Ensure state-based effects and triggers updated when using Setup Game State
Remove unnecessary duplicate of setup game state code
2014-10-14 02:14:44 +00:00
drdev
f7f99366fc Fix bug that prevented dying triggers from firing 2014-10-14 01:54:43 +00:00
drdev
3741588939 Remove unused import 2014-10-14 00:59:29 +00:00
drdev
bcbcc1cb5c Fix updateSingleCard crashes 2014-10-14 00:56:20 +00:00
drdev
76ad6691a9 Fix crash from bad cast 2014-10-13 23:25:07 +00:00
drdev
8d71ae5cbf Prevent crash when canceling prompt for card or player 2014-10-13 23:13:13 +00:00
drdev
1b70875b40 Make it possible to see card name via toString() before currentState.getName() is established (for debugging purposes mostly) 2014-10-13 23:03:03 +00:00
drdev
71a9f33d4c Fix so each players opponents are cached in view 2014-10-13 05:24:33 +00:00
drdev
a8457ea75b Prevent P/T flickering for good 2014-10-13 05:06:25 +00:00
drdev
f8a54eed14 Rename Attack/Defense to Power/Toughness for consistency 2014-10-13 04:37:55 +00:00
drdev
75f60f07c8 Fix so P/T adjustments from state based effects are applied 2014-10-13 04:27:30 +00:00
drdev
5c6d9736b2 Fix non* targeting restrictions (e.g. nonland) 2014-10-13 04:10:05 +00:00
drdev
84da2570d8 Fix so blocking arrow shown when declaring blockers 2014-10-13 03:42:46 +00:00
drdev
c32ade2bc0 Fix so combat arrows go away when combat ends 2014-10-13 03:36:43 +00:00
drdev
b663642d49 Prevent losing all planeswalker abilities after one activation 2014-10-13 03:28:30 +00:00
drdev
498283f9b4 Optimize getCardTypesFromList 2014-10-13 03:12:58 +00:00
drdev
d3c3e6fe43 Prevent passing game object to client when adding card to field 2014-10-13 02:29:42 +00:00
drdev
f0e75ae9bc Fix so icons for selected cards in hand appear immediately 2014-10-13 02:19:42 +00:00
drdev
a7540481f6 Prevent passing GameObject instances to gui via SGuiChoose dialog
Fix so scry cards can appear in card picture pane
2014-10-13 02:03:03 +00:00
drdev
2b2e55a142 Prevent crash potential when updating attacker for view 2014-10-13 01:34:35 +00:00
drdev
7a1313d332 Fix crash when selecting a fake card in a list view 2014-10-13 01:29:44 +00:00
drdev
f905903db1 Fix bugs related to mana abilities being excluded 2014-10-13 01:17:02 +00:00
drdev
994903d080 Fix so log is updated immediately 2014-10-13 00:13:55 +00:00
drdev
57890310d8 Remove duplicate function for getting mana abilities 2014-10-12 22:52:11 +00:00
drdev
4cfb6a8659 Refactor card abilities into FCollections to protect access 2014-10-12 22:47:48 +00:00
drdev
6a299b89bf Fix crash when viewing Player pane 2014-10-12 21:32:37 +00:00
drdev
144f651fa0 Support caching ability text and certain keywords in view
Update names of certain classes and fields for better consistency
Fix so summoning sickness icon doesn't appear for creatures with Haste
2014-10-12 21:23:27 +00:00
Sloth
4cbd16d7b5 - Cleanup and performance fixes in AI functions. 2014-10-12 21:06:55 +00:00
Sloth
10bd22a944 - Fixed and improved predictThreatenedObjects. 2014-10-12 20:07:30 +00:00
drdev
7ec8d04eb7 Reduce how often updateState is called for CardView 2014-10-12 16:18:21 +00:00
drdev
d744f76024 Prevent commander effect appearing in UI 2014-10-12 15:59:20 +00:00
drdev
8bf08cf12a Prevent crash in updateSingleCard 2014-10-12 15:55:58 +00:00
drdev
91a714384a Fix so revealing a collection of cards doesn't display them all in one row 2014-10-12 15:49:19 +00:00
drdev
c7b8a070f8 Fix so Enters the Battlefield triggers work 2014-10-12 15:43:31 +00:00
drdev
f172e72604 Prevent stack overflow error with FCollection.addAll 2014-10-12 14:22:34 +00:00
Sloth
48df213082 - Updated Booster Prices by Vecc. 2014-10-12 10:44:42 +00:00
drdev
ecebe7e13d Remove unnecessary comments 2014-10-12 01:42:21 +00:00
drdev
92f187f6e3 Refactor card types to use class instead of a List<String>
Optimize Zone and other areas to use CardCollection
2014-10-12 01:37:27 +00:00
swordshine
351f0df19a - Attempt to fix NPE when handling the Legendary rule and Planeswalker rule 2014-10-11 04:32:00 +00:00
drdev
ce0266c3d5 Fix crash with chosen player 2014-10-10 16:38:38 +00:00
drdev
033cf1701a Prevent crashes from calling CardView.getCards and assumming non-null 2014-10-10 16:31:05 +00:00
drdev
f74f438765 Fix crash with Battalion 2014-10-10 16:23:24 +00:00
drdev
ea5e4857af Prevent details mismatching in deck editor 2014-10-10 16:02:35 +00:00
drdev
d7d79d11cd Fix crash with split cards 2014-10-10 15:52:48 +00:00
drdev
1d67bcbcc1 Fix so card text shows up properly in details pane 2014-10-10 15:43:21 +00:00
drdev
dfb260286a Fix so summoning sickness icon appears initially 2014-10-10 14:27:57 +00:00
Agetian
1a16381e82 - Better names for the card sale cap options in quest preferences. 2014-10-10 13:35:31 +00:00
drdev
3538823e11 Swap out old GameView structure for new one 2014-10-10 05:52:18 +00:00
Sloth
42e3778778 - Added AI support for Perilous Research (given the right deck). 2014-10-09 21:57:45 +00:00
Sloth
94b81a6ec9 - Fixed AI not playing Sarkhan, the Dragonspeaker in Main1. 2014-10-09 20:07:30 +00:00
Sloth
7bd91363be - Updated some quest decks. 2014-10-09 18:54:01 +00:00
drdev
8f023aaed3 Support updating game view 2014-10-09 15:01:45 +00:00
drdev
91e509ffd6 Fix so player view has zone updated 2014-10-09 01:50:29 +00:00
drdev
1ac14d3a29 Code cleanup 2014-10-09 01:36:52 +00:00
drdev
5e22f01358 Remove old implementation of game state serialization that was never used anyway 2014-10-09 01:30:16 +00:00
drdev
122e1ca75a Fix crash when tapping mana 2014-10-09 01:12:59 +00:00
drdev
14c5e5242f Support updating mana for player view 2014-10-09 01:09:54 +00:00
drdev
4ee4919d58 Remove unnecessary comments 2014-10-09 00:49:22 +00:00
drdev
6c95af229a Support storing commander and commander damage in player view 2014-10-09 00:33:38 +00:00
drdev
5563d8b1c6 Support parsing keywords for players
Support updating PlayerView properties
2014-10-08 23:33:36 +00:00
Sloth
498ee2d74b - Updated some quest decks. 2014-10-08 21:23:03 +00:00
drdev
9ba67076dc Add enum and instance classes for keywords 2014-10-08 19:34:14 +00:00
Sloth
fcada08599 - Improved AI's doAssault function. 2014-10-08 18:07:48 +00:00
Sloth
ad0921ecbe - Added AI support for Tyrant's Choice. 2014-10-08 14:59:23 +00:00
drdev
b35c3c4cd1 Remove unnecessary request rendering calls 2014-10-08 14:19:46 +00:00
Sloth
06f1b01489 - Updated some quest decks. 2014-10-08 12:03:07 +00:00
Sloth
9872b3c9d3 - Improved AI handling Glacial Fortress and friends. 2014-10-08 11:41:57 +00:00
Sloth
9c5e6beefa - Added a new AI SVar "FreeSpellAI" which makes the AI play these cards before other spells. 2014-10-08 11:03:31 +00:00
Sloth
c2b0801ada - Updated some SVars. 2014-10-08 10:38:06 +00:00
Krazy
1b5f9d257b Fixed NPE if no available sets to draft from in quest mode. 2014-10-07 21:45:08 +00:00
swordshine
0f9865c4d3 - Remove "Static$ True" params in two scripts 2014-10-07 13:38:04 +00:00
swordshine
14c3a1387a - Fixed War-Name Aspirant 2014-10-07 12:28:11 +00:00
swordshine
fb882f0fdb - Fixed last commit 2014-10-07 07:47:25 +00:00
swordshine
267a9a2801 - Fixed copyParamsToMap 2014-10-07 07:05:17 +00:00
drdev
0851301985 Add serialize and deserialize logic for trackable objects 2014-10-07 05:39:35 +00:00
drdev
f0fc60b9dc Support easily serializing and deserializing the TrackableProperty enum values themselves 2014-10-07 04:34:54 +00:00
drdev
b8285e3694 Add TrackableTypes to facilitate determination of default values as well as provide methods for loading and saving the property to file 2014-10-07 04:24:57 +00:00
drdev
75d1f5dea6 Add CardCollection class and special methods to CardView to make it easier to track changes to collections and make it possible to prevent changes outside Card class
Add delayed initialization of certain collection fields to Card to reduce memory usage and improve performance
2014-10-06 23:12:49 +00:00
drdev
44664bd30e Optimize the logic around for attaching cards to other cards/players 2014-10-06 15:12:02 +00:00
drdev
5bfd8462b9 Fix crash when a split card is initialized 2014-10-06 05:46:57 +00:00
drdev
755fcfc087 Fix crash in WrappedAbility 2014-10-06 05:41:24 +00:00
drdev
2cedade957 Fix crash in tempShowCard
Fix crash that can occur from calling canPlay too early
2014-10-06 05:20:48 +00:00
Agetian
6eef6ab9ad - Added quest preferences to make the max card selling price (default 1000) and the number of wins to remove the selling price limit (default 50) configurable. 2014-10-06 05:06:09 +00:00
drdev
255fc2ea5f Prevent crash when opening deck editor 2014-10-06 04:57:42 +00:00
drdev
6242c33c6a Avoid storing and passing IGuiBase instances everywhere since only one IGuiBase instance will ever exist on a single session 2014-10-06 04:49:03 +00:00
drdev
afcad4e672 Commit stage 1 of large game view refactoring 2014-10-06 04:06:42 +00:00
Sloth
e599aef134 - Added basic AI support for Necropolis Fiend. 2014-10-05 21:02:45 +00:00
Sol
bae8658c80 - Change the TapOrUntap Effect's default based on comparing the controller of the SA with the controller of the effected card 2014-10-05 17:33:12 +00:00
Sloth
6ac44f1618 - Fixed Paradox Haze. 2014-10-05 11:56:54 +00:00
Sloth
08c886cd96 - Fixed Nullstone Gargoyle. 2014-10-05 08:59:04 +00:00
Sloth
bc470536d5 - Fixed Erayo, Soratami Ascendant. 2014-10-05 08:55:10 +00:00
Sloth
5ee5b8a81d - Fixed Incursion Specialist. 2014-10-05 08:46:44 +00:00
swordshine
5975d78be5 - Fixed Meandering Towershell 2014-10-05 02:26:33 +00:00
swordshine
102a65f6d0 - Fixed Tithe so it triggers Ob Nixilis, Unshackled twice 2014-10-05 02:21:52 +00:00
swordshine
bdd2e915f7 - Fixed Path to Exile and friends 2014-10-05 02:07:49 +00:00
excessum
fabc78ae84 - Fixed Kheru Lich Lord 2014-10-05 00:15:48 +00:00
Sol
55c65c323b - Fix so Suppression Field doesn't RaiseCosts of ETB Replacement Effects. 2014-10-04 22:19:22 +00:00
Sloth
fc5cb66b2c - Fixed Maelstrom Nexus. 2014-10-04 20:24:08 +00:00
swordshine
2428a6b0b1 - A better fix for ComputerUtilCard.applyStaticContPT() 2014-10-04 12:31:09 +00:00
excessum
f7e8d51701 - Fixed typo in r27822 2014-10-04 12:23:34 +00:00
excessum
2f49deed12 - Fixed NullFormatException with ComputerUtilCard.applyStaticContPT() 2014-10-04 12:22:27 +00:00
excessum
135a11fb3d - Fixed bug with AI using double-strike damage when trying to kill an attacker in the first-strike phase with gang-blockers 2014-10-04 11:52:02 +00:00
drdev
ac23855453 Version bump to 1.5.29.002 2014-10-04 09:56:24 +00:00
drdev
e0d5115b57 Significantly improve performance of event handling and input processing 2014-10-04 09:50:18 +00:00
swordshine
b91530b799 - Removed duplicated codes "NumCounters" 2014-10-04 09:29:19 +00:00
swordshine
a8f640e00e - Update Elephant Resurgence 2014-10-04 09:14:57 +00:00
swordshine
6532ad8e8d - Updated more scripts 2014-10-04 09:09:28 +00:00
swordshine
17e8e116df - Updated scripts for multiplayer games 2014-10-04 08:45:15 +00:00
drdev
6e5829aaa3 Fix direction of tab swipe 2014-10-04 06:38:22 +00:00
Chris
964579c840 Cleared out the changes.txt file, now ready for new material. 2014-10-03 23:57:59 +00:00
Krazy
aa3480be4d The ! operator can now only precede a search term when using boolean expressions. This allows searches such as 'kaboom! | arms' to evaluate correctly. 2014-10-03 21:55:35 +00:00
drdev
20990440bb Version bump to 1.5.29.001 2014-10-03 19:41:37 +00:00
drdev
ec8b577aaf Fix crash when playing commander 2014-10-03 19:36:42 +00:00
drdev
102062fb13 Fix alignment of tab icons for non-compact mode 2014-10-03 19:28:48 +00:00
drdev
be5086e7f4 Make zooming in ItemManager image view easier 2014-10-03 19:26:05 +00:00
drdev
4b9aa2515d Support switching tabs by flinging your finger left or right 2014-10-03 19:22:59 +00:00
drdev
ce043302db Support compact tabs via setting 2014-10-03 19:06:32 +00:00
drdev
fe33235f08 Fix so cards in library update if you have to select multiple cards 2014-10-03 18:02:38 +00:00
Chris
e0aca90d0e [maven-release-plugin] prepare for next development iteration 2014-10-03 17:50:03 +00:00
Chris
3285529e9f [maven-release-plugin] prepare release forge-1.5.28 2014-10-03 17:49:48 +00:00
drdev
5752f3de59 Allow double tap to select card
Disable OK button when second tab selected
2014-10-03 17:13:58 +00:00
Chris
77ee3ad794 Preparing the changes.txt file for the next beta build and release. 2014-10-03 17:08:08 +00:00
drdev
5cad346879 Fix so item selected by default 2014-10-03 16:54:23 +00:00
drdev
76fc77acee Add search field and increase size of dialog 2014-10-03 16:49:22 +00:00
drdev
72dc0437d2 Implement better dialog for searching library in mobile game 2014-10-03 15:47:21 +00:00
Sol
1cac45f3da - Fix issue where CopyPermanent was not registering active triggers immediately, preventing ETB triggers from firing. 2014-10-03 15:45:42 +00:00
Sol
df1383c43e - Fix for intervening if trigger bug 2014-10-03 15:36:13 +00:00
drdev
82bf43a519 Split up choose entity between desktop and mobile to allow varying implementations for search and reveal combo dialog 2014-10-03 13:49:14 +00:00
drdev
9f25b55cfb Prevent flickering when multiple dialogs appear in quick succession 2014-10-03 13:25:52 +00:00
drdev
1d19df364f Indicate progress when searching for multiple cards 2014-10-03 11:13:05 +00:00
drdev
54250bec7d Improve title for search dialogs 2014-10-03 11:06:22 +00:00
drdev
c591031f48 Prevent having the same cards revealed multiple times 2014-10-03 10:34:35 +00:00
drdev
9391b0b486 Refactor logic that reveals cards before selecting a card so that it will be possible to combine the dialogs later 2014-10-03 10:32:16 +00:00
drdev
f04a47b15e Fix bug where details for some cards were not being shown when tutoring 2014-10-03 09:41:22 +00:00
drdev
be7a646ba4 Version bump to 1.5.28.015 2014-10-03 07:24:03 +00:00
drdev
beb294bd08 Fix reanimation spells 2014-10-03 07:21:27 +00:00
drdev
80ef6519df Version bump to 1.5.28.014 2014-10-03 06:59:01 +00:00
drdev
f456a4a095 Prevent game hanging if playing for ante 2014-10-03 06:57:02 +00:00
drdev
0536a9be5a Version bump to 1.5.28.013 2014-10-02 22:45:52 +00:00
drdev
5d919d9e03 Make previous fix actually work
Fix so cards cast by opponent aren't hidden while on stack
2014-10-02 22:43:23 +00:00
drdev
a6b4e74263 Fix so combat icons appear immediately 2014-10-02 22:28:38 +00:00
drdev
7c53f96328 Prevent stuff getting out of sync 2014-10-02 22:17:54 +00:00
drdev
d2b6a0831d Improve performance of rendering and event handling for Android app 2014-10-02 21:10:50 +00:00
drdev
d7bcbdd04b Avoid copying unneccessary information to card views that can't be shown anyway 2014-10-02 20:08:20 +00:00
Sloth
3ea9e25c66 - Added AI support for Fume Spitter. 2014-10-02 19:00:58 +00:00
excessum
82e7d6a1e4 - Re-implemented Convoke shard mapping for AI 2014-10-02 12:34:11 +00:00
drdev
c6d2a9a6ed Refactor event handling system to be much faster and more reliable 2014-10-02 10:31:37 +00:00
Sloth
75adde6794 - Updated some quest decks. 2014-10-01 21:44:23 +00:00
drdev
a870825b7a Version bump to 1.5.28.012 2014-10-01 20:39:45 +00:00
drdev
c5ac3c652e Use delayed event queue to improve performance of game startup and event processing in general 2014-10-01 20:29:01 +00:00
drdev
1f277a1e6b Slightly optimize use of gameView.updateViews 2014-10-01 19:22:44 +00:00
drdev
1dc64e18c6 Ensure tapped reset when card leaves the battlefield 2014-10-01 19:11:28 +00:00
drdev
98951a9e2b Prevent tapped card remaining tapped in graveyard 2014-10-01 19:08:45 +00:00
drdev
3bd35d225c Prevent incorrectly preventing certain information being correct when first opening match screen 2014-10-01 17:12:35 +00:00
drdev
ec1451fe85 Make spacing consistent 2014-10-01 16:44:50 +00:00
drdev
d8962746e6 Clear damage when card leaves battlefield 2014-10-01 16:39:52 +00:00
drdev
4978e34262 Commit large scale CardView refactoring to support head-to-head better, handle hidden and face down cards better, and reduce flickering of P/T and other attributes 2014-10-01 14:15:25 +00:00
swordshine
b12ca2f1dc - Update Formats for PerSetTracking 2014-10-01 11:57:19 +00:00
drdev
a7c2931ff9 Version bump to 1.5.28.011 2014-09-30 19:21:20 +00:00
drdev
f815c6d058 For now, prevent using player specific menu when that player doesn't have priority 2014-09-30 19:18:43 +00:00
Agetian
ba5feb5021 - Invert a condition in phasesCheck in an attempt to prevent a NPE 2014-09-30 19:00:30 +00:00
drdev
89fd88ad1d Allow all overlays to face top human player if needed
Allow top human player to concede
2014-09-30 18:23:42 +00:00
drdev
f8c2af1ad3 Make player menus appear in the correct place 2014-09-30 18:10:30 +00:00
Agetian
ca2db87d6c - A somewhat better temporary solution for the issue with foils: will now fully randomize the foil overlays inside the game (where there is no problem with them), but still set the default foil overlay of 1 for the deck editors (where the foil overlays "flicker" in case of randomization). 2014-09-30 18:08:04 +00:00
drdev
5eaa5733df Fix so player specific menu can be tapped to close 2014-09-30 08:37:38 +00:00
drdev
f62c5d0343 Fix so player specific menus appear in correct location 2014-09-30 08:34:18 +00:00
drdev
3c3c488c48 Simplify code 2014-09-30 08:21:22 +00:00
drdev
989c6f0ffb Add Hot Seat Mode setting for mobile game
Prevent crash when rendering card without display area set yet
2014-09-30 08:19:55 +00:00
drdev
8fb607c92d Allow stack items to appear rotated 90 degrees 2014-09-30 08:11:10 +00:00
drdev
7f73d6f719 Avoid making theming optional since things don't look right otherwise 2014-09-30 08:10:55 +00:00
Sol
239f49c53d - Add a Quest Preference for Item Level Restriction, defaulting to enabled (1). 2014-09-29 23:55:44 +00:00
Chris
72cf37406f Added new card names to changes.txt. 2014-09-29 22:34:01 +00:00
drdev
3001429536 Fix so clipping works properly against objects rotated 90 degrees 2014-09-29 21:40:22 +00:00
drdev
a82123bb95 Fix so rotated 90 components can capture input 2014-09-29 21:33:07 +00:00
drdev
167c2befb0 Support 90 degree rotation so match menu can appear on right side of screen 2014-09-29 20:45:11 +00:00
Agetian
b35aa63654 - Attempt to fix Battalion according to friarsol's suggestion. 2014-09-29 18:56:41 +00:00
drdev
85bcd08eab Tweak how 2nd human opponent displayed so its more of a mirroring effect than pure rotation 2014-09-29 18:49:07 +00:00
excessum
214c929ca3 - Re-factored payManaCostFromPool() out from payManaCost() 2014-09-29 12:36:33 +00:00
elcnesh
9ce50662fe Fix counter placement sound playing repeatedly. 2014-09-29 09:08:45 +00:00
Sloth
97a46fae15 - Fixed several bugs in isPreferredTarget. 2014-09-28 21:35:46 +00:00
drdev
8583b45b81 Version bump to 1.5.28.010 2014-09-28 19:42:58 +00:00
drdev
1d02422553 Add Chromatic and Epic challenges 2014-09-28 18:38:24 +00:00
drdev
04f725a142 Add Domain achievement 2014-09-28 17:50:19 +00:00
drdev
962ea5c452 Fix so targets for subabilities of stack items are accounted for with target arrows 2014-09-28 17:36:14 +00:00
drdev
05f289222a Add 3 deck challenge achievements 2014-09-28 16:42:23 +00:00
drdev
fece3f9f0b Add Challenges achievement category 2014-09-28 16:07:38 +00:00
drdev
56e2e63379 Prevent P/T being hidden for tapped cards in a stack 2014-09-28 16:02:20 +00:00
drdev
8209e80b03 Support showing special symbols used by charms 2014-09-28 15:49:41 +00:00
drdev
ff50f4fe5f Use \u syntax for special characters 2014-09-28 15:45:32 +00:00
elcnesh
e44b4b3cbc Multiple fixes.
- Make determination of card viewing permissions much faster;
- A general fix related to choosing a fixed amount of options from a list;
- Improve display of card's names;
- Reduce card flickering when changing phases.
2014-09-28 15:43:34 +00:00
drdev
6969aaad91 Cleanup charm formatting 2014-09-28 15:39:27 +00:00
drdev
e19c0ba694 Version bump to 1.5.28.009 2014-09-28 15:06:00 +00:00
Agetian
0c09cdbbe0 - Better version of the previous fix. 2014-09-28 13:47:49 +00:00
Agetian
cb93455530 - Fix a NPE with automated targeting for cards that require dividing damage (e.g. Polukranos, World Eater; Armament Corps). 2014-09-28 13:45:27 +00:00
drdev
024d832bce Add support for displaying formatted timestamp for earned achievements 2014-09-28 10:06:10 +00:00
drdev
43d4bab1b7 Add timestamp support to achievements
Throw out any previously earned ManaScrewed achievements due to now fixed bug
2014-09-28 09:40:21 +00:00
drdev
0a313c4071 Fix ManaScrewed achievement 2014-09-28 09:25:03 +00:00
drdev
89348087af Reduce size of achievements file 2014-09-28 09:07:13 +00:00
drdev
2306524df1 Refactor achievement definitions to make them easier to implement 2014-09-28 09:01:16 +00:00
Agetian
cc920261d8 - Fix effects like Fact or Fiction not revealing the cards properly to the player. 2014-09-28 07:32:51 +00:00
Agetian
09b8e0f9e1 - Make it impossible to undeclare attackers with "CARDNAME attacks each combat if able" at will. 2014-09-28 06:15:52 +00:00
excessum
f9a4cd63d7 - AI will now take note of static P/T abilities when using Animate and Pump effects 2014-09-28 02:53:03 +00:00
excessum
4b51b0f9e7 - Simplified removal of likely blockers in chooseCardsForConvoke() 2014-09-28 01:10:06 +00:00
drdev
43382d5f9d Update CHANGES.txt 2014-09-27 22:53:08 +00:00
drdev
e90b347692 Version bump to 1.5.28.008 2014-09-27 22:38:17 +00:00
drdev
528642a11e Fix so combat arrows appear red again 2014-09-27 22:35:34 +00:00
drdev
2921bc6a9f Fix so blocking arrow appears immediately upon declaring blockers 2014-09-27 22:27:14 +00:00
drdev
04229ba711 Fix so Always Yes and Always No options appear for optional triggered abilities 2014-09-27 22:12:49 +00:00
drdev
40802d126b Small rendering optimization 2014-09-27 22:02:01 +00:00
Sloth
a7bcc7d9d3 - Fixed text of Dance of the Dead. 2014-09-27 21:37:52 +00:00
drdev
afe1552659 Add Storm Chaser achievement 2014-09-27 21:25:49 +00:00
drdev
535e72e3fc Add Arcane Master achievement 2014-09-27 21:16:43 +00:00
drdev
c3871c1d82 Fix issue where earned achievements weren't being saved for mobile game 2014-09-27 20:57:56 +00:00
drdev
15f61402ba Go back to re-using game thread to avoid creating too many threads 2014-09-27 20:51:33 +00:00
drdev
cc3480b266 Add ManaFlooded achievement 2014-09-27 20:44:31 +00:00
drdev
a1c7d97807 Remove extra period 2014-09-27 20:28:04 +00:00
drdev
a4f53729df Add ManaScrewed achievement 2014-09-27 20:27:04 +00:00
Sloth
14f31bfabe - Improved ordering in playReusable. 2014-09-27 20:23:04 +00:00
Sloth
422271ab4d - Fixed NPE when AI's Goblin Arsonist dies. 2014-09-27 20:17:32 +00:00
drdev
a5be45a160 Add RagsToRiches achievement 2014-09-27 20:16:21 +00:00
drdev
35a31fc2d3 Revert change not meant to be committed 2014-09-27 19:56:34 +00:00
drdev
84f564b65e Create achievement tracker class to make it easier to track information for certain achievements 2014-09-27 19:55:48 +00:00
Sloth
520adae0fd - Fixed Abomination of Gudul. 2014-09-27 19:50:59 +00:00
drdev
1c6bf04143 Fix mana cost payments for cards that cost 0 mana 2014-09-27 19:43:59 +00:00
excessum
1cd69ebcb3 - Implemented AI for Convoke 2014-09-27 15:12:38 +00:00
excessum
3c9d6645e4 - Re-factored AiBlockController.assignBlockers() overloads and associated utility functions. 2014-09-27 15:03:11 +00:00
Agetian
1c58d91ef5 - Fix tapping events not firing off for Convoke. 2014-09-27 14:48:24 +00:00
excessum
204be837be - Fixed power for Watcher of the Roost 2014-09-27 02:16:15 +00:00
drdev
32ef0a898a Allow quick tapping to perform consecutive double tap actions
Prevent long press action being handled a bit after finger is released due to lag
2014-09-26 20:00:17 +00:00
drdev
9cdeceaabd Prevent long press causing achievement to not be selected 2014-09-26 19:22:45 +00:00
drdev
fc00dfa8af Turn on continuous rendering to improve responsiveness 2014-09-26 19:20:52 +00:00
drdev
b4bcee6bc6 Make gameViews final 2014-09-26 19:15:49 +00:00
Agetian
f833a49c7f - Fix targeting arrows in the desktop version of the game. 2014-09-26 15:30:28 +00:00
elcnesh
af731da251 Minor textual fix. 2014-09-26 12:59:53 +00:00
drdev
de5b026c4e Version bump to 1.5.28.007 2014-09-26 10:49:40 +00:00
drdev
f4829869c9 Remove attack traces 2014-09-26 10:47:54 +00:00
drdev
88cd6b0ba1 Fix so attack and defend icons appear 2014-09-26 10:44:08 +00:00
drdev
1cc9056b7b Optimize card rendering behind other cards
Fix issue with achievement tooltip not appearing at times
2014-09-26 10:32:09 +00:00
elcnesh
3f1f199537 Use caching for CombatView (plus some random NPE and concurrency fixes). 2014-09-26 07:38:47 +00:00
Sol
3c411f3a3c - "Effect" effects that contain triggers will now be registered immediately instead of waiting for the next registration time. 2014-09-26 00:22:05 +00:00
Sol
2cab5a7a11 - Tweaking Vengevine script to adhere to how triggers register 2014-09-26 00:07:09 +00:00
Sloth
b5b33c9afc - Updated some quest decks. 2014-09-25 20:11:43 +00:00
drdev
57a552dc04 Move FTrace to forge.core 2014-09-25 19:17:56 +00:00
drdev
56908b9516 Add requestRendering calls to aid in performance 2014-09-25 18:15:38 +00:00
drdev
a2030f7db6 Use separate background threads for certain actions instead of re-using game thread 2014-09-25 17:55:07 +00:00
drdev
ab984bad9b Prevent starting trace multiple times before ending it 2014-09-25 17:40:25 +00:00
drdev
bde531ad50 Remove render traces 2014-09-25 17:31:59 +00:00
drdev
74f088bf58 Add support for printing trace information 2014-09-25 17:22:23 +00:00
drdev
51ed1f758b Version bump to 1.5.28.006 2014-09-25 16:06:02 +00:00
drdev
096b4f7e12 Ensure caches cleared between games 2014-09-25 16:03:49 +00:00
drdev
7fd3b39765 Temporarily disable human v. human 2014-09-25 15:58:21 +00:00
drdev
d29ae9d948 Remove press delay to make app feel more responsive 2014-09-25 15:55:12 +00:00
Sloth
6bd10d6a9a - Fixed more ChangeZone triggers. 2014-09-25 15:53:54 +00:00
drdev
a89c9df904 Prevent crash when starting game without name configured
Avoid unnecessary duplication of event handling when two human players
Avoid duplicate copies of views when two human players
2014-09-25 15:49:23 +00:00
Sloth
70f780ab11 - Fixed more ChangeZone triggers (A-G). 2014-09-25 15:01:22 +00:00
elcnesh
5b84bdfb75 - Fix a possible IllegalArgumentException.
- Hotfix for foil cards: always use foil index '1' rather than a random foil (prevents flickering in deck editor).
2014-09-25 14:59:52 +00:00
Sloth
54e29afe26 - Fixed cards with "When CARDNAME is put into a graveyard from anywhere, shuffle it into its owner's library". 2014-09-25 14:43:48 +00:00
drdev
28dfb26329 Prevent mana tapping for second human player causing issues 2014-09-25 14:04:26 +00:00
drdev
d701242e65 Support showing card zoom upside down if second human player is active 2014-09-25 13:54:50 +00:00
drdev
655e1f7e0f Support rotating top player panel when playing Human v. Human on same device 2014-09-25 13:29:51 +00:00
drdev
43d2169ba5 Prevent earning achievements when playing Human v. Human on the same device 2014-09-25 13:27:58 +00:00
excessum
938ffba9b5 - Fixed token image names for Magic 2015 2014-09-25 13:27:32 +00:00
drdev
62ab06b188 Support drawing prompt rotated 180 degrees 2014-09-25 12:52:11 +00:00
drdev
4e2729b4f0 Prevent showing menu bar when there are two prompts 2014-09-25 11:41:49 +00:00
drdev
1b0346219d Code cleanup 2014-09-25 11:37:24 +00:00
drdev
42af632ccf Fix so opponent's hand shown for duration of mindslave turn 2014-09-25 11:33:00 +00:00
drdev
b563109dbc Prevent crash that can occur at end of Mindslaver turn 2014-09-25 11:14:55 +00:00
drdev
b78c7d76af Fix so conceding after a Mindslaver turn works 2014-09-25 10:59:34 +00:00
drdev
7857b4d5c9 Fix issue with Mindslaving opponent 2014-09-25 10:46:37 +00:00
drdev
19ae842ba5 Prevent showing two instances of WinLose screen 2014-09-25 10:30:52 +00:00
drdev
e47ad1eeed Make it so human player has prompt disabled while other human player has an input active 2014-09-25 10:14:33 +00:00
drdev
c7ec4d9c64 Fix crash when starting AI v. AI match 2014-09-25 10:02:59 +00:00
drdev
a76c9f25fd Fix so loading overlay actually appears 2014-09-25 06:42:19 +00:00
drdev
3d8341096c Change API version back to 20 since that wasn't the problem 2014-09-25 06:08:40 +00:00
swordshine
801d7ecbfb - Added Dragon Grip 2014-09-25 05:13:35 +00:00
swordshine
b38bff844b - Added Ride Down 2014-09-25 04:38:04 +00:00
Chris
ece36b70ef Added new card names to changes.txt. 2014-09-24 23:13:47 +00:00
drdev
b92f67aa7e Change API version back to 19 to see if that helps
Version bump to 1.5.28.005
2014-09-24 21:19:38 +00:00
drdev
1af5223b82 Fix so ability selection dialog formats text correctly 2014-09-24 21:12:52 +00:00
drdev
c9e131a1f0 Refactor code to prevent duplication of match code 2014-09-24 21:03:49 +00:00
Sloth
236ac164b0 - Added a medium version of the Abraham Lincoln opponent and updated 2 quest decks. 2014-09-24 21:01:33 +00:00
Sloth
68107c0386 - Added an easy version of the Amphibian opponent. 2014-09-24 19:47:25 +00:00
elcnesh
6db5685906 Make LocalGameView a bit faster, plus some minor refactoring. 2014-09-24 14:16:42 +00:00
excessum
2f70494c14 - AI will now consider multi-blocks before attacking (avoid 1/4 lifelink attacking two 2/2s) 2014-09-24 13:27:35 +00:00
excessum
7226e24cf5 - Moved canBeBlockedProfitably() from AiBlockController to ComputerUtilCard 2014-09-24 13:12:52 +00:00
excessum
14c4b95658 - Re-factored AiBlockController.shouldThisBlock() into ComputerUtilCard.doesSpecifiedCreatureBlock()
- Changed Outlast AI to use doesSpecifiedCreatureBlock()
2014-09-24 13:04:46 +00:00
Agetian
2813896e6b - Added a fix by Swordshine that fixes playing spells without paying their mana cost and playing spells for their alternative cost. 2014-09-24 13:02:44 +00:00
Sol
5b59db8b59 - Updating Changes with information about the new trigger fixes. 2014-09-24 03:00:42 +00:00
drdev
c10c90e075 Fix crash when starting next game of match 2014-09-23 19:24:14 +00:00
Sloth
d4b46dbf8b - Fixed implementation of game rule 704.5f (creatures with 0 toughness aren't "destroyed"). 2014-09-23 18:58:07 +00:00
Sloth
ff2c700d5e - Fixed Rough // Tumble in Commander 2013. 2014-09-23 18:42:32 +00:00
Sloth
19d6d035a4 - Fixed Abzan Charm. 2014-09-23 18:39:54 +00:00
Sloth
d8cff22024 - Fixed Mirror of Fate not allowing less than 7 cards. 2014-09-23 18:37:30 +00:00
Agetian
fbf2b77c3a - Fix token image for Goblin Kaboomist (Land Mine). 2014-09-23 16:07:45 +00:00
drdev
efefedd445 Support showing prompt for second human player 2014-09-23 13:38:39 +00:00
Sloth
b7ceefc8c4 - Updated some SVars. 2014-09-23 12:33:13 +00:00
drdev
1d965da35e Fix so second player's prompt appears and button images don't extend outside their bounds 2014-09-23 11:52:50 +00:00
drdev
6a5cd5f39f Start refactoring to make Human v. Human support better 2014-09-23 11:22:36 +00:00
swordshine
edf8c58754 - Added Ashcloud Phoenix 2014-09-23 11:21:15 +00:00
swordshine
6e35fee7ba - Fixed Narset, Enlightened Master 2014-09-23 11:18:13 +00:00
drdev
cbb80c482e Add achievements for winning with Phage and Door to Nothingness 2014-09-23 09:48:23 +00:00
drdev
fb7ec4bad5 Add Test of Endurance alt win condition 2014-09-23 09:20:14 +00:00
drdev
1559825d86 Uncommit allowing cheating for achievements 2014-09-23 09:14:10 +00:00
drdev
8264fd8075 Support earning Planeswalker ultimate achievements 2014-09-23 08:53:28 +00:00
drdev
0c9b6ec08a Shorten some achievement names so they fit 2014-09-23 07:33:23 +00:00
Sol
e05ff43f74 - A whole bunch more adjusted "dies" triggers. 2014-09-23 03:23:51 +00:00
Sol
d6935e9e9a - Fixing even more triggers for "dies" not functioning with the new trigger code 2014-09-23 02:53:23 +00:00
Sol
46d3c7c044 - Fixing more triggers for "dies" not functioning with the new trigger code 2014-09-23 02:06:06 +00:00
elcnesh
bf7944d108 Speed boost to GUI refactoring, mostly by using the Caches smarter. 2014-09-22 22:32:09 +00:00
Chris
d545802b18 Added new card names to changes.txt. 2014-09-22 22:01:48 +00:00
drdev
323b9a4048 Fix issues with CardZoomer 2014-09-22 18:21:45 +00:00
Agetian
ecd39b85a2 - Remove an unused method. 2014-09-22 17:54:11 +00:00
Agetian
b357f88a8c - Attempt to fix blocker targeting arrows without breaking the combat log. 2014-09-22 17:50:09 +00:00
drdev
86ecc75dbe Support showing card associated with achievement using double click or middle/long press 2014-09-22 15:31:09 +00:00
drdev
a4f8ee4f9c Add Planeswalker Ulimtates achievements 2014-09-22 15:05:11 +00:00
drdev
9ea8d84ee8 Refactor achievements so they're not packaged with the game 2014-09-22 14:11:43 +00:00
elcnesh
99626fc9b7 Add new dev mode option to menus, and remove a superfluous synchronized() call. 2014-09-22 13:12:55 +00:00
excessum
d2415c7aa5 - Fixed bug with AI failing to activate Deathtouch in combat 2014-09-22 12:27:38 +00:00
elcnesh
2442362e5b Fix a lot of concurrency issues and some other GUI problems. 2014-09-22 12:10:50 +00:00
Sloth
44aed6b85d - Added AI support for Duneblast. 2014-09-22 07:25:46 +00:00
Sol
49d4d3cd77 - Updating a few more scripts to run better with the new trigger changes 2014-09-22 03:21:09 +00:00
Sol
a6c8d2b8fe - Updating a few scripts to run better with the new trigger changes 2014-09-22 02:35:07 +00:00
Krazy
97e330a2bf Fixed Death Frenzy's mana cost. 2014-09-22 02:02:43 +00:00
Sloth
e85d22995d - Updated some more SVars. 2014-09-21 21:02:51 +00:00
Sloth
59949eea96 - Added AI support for Barrage of Boulders. 2014-09-21 20:44:08 +00:00
Sloth
b1c07c8f7a - Added AI support for Crackling Doom. 2014-09-21 20:08:01 +00:00
drdev
2270b047bc Improve display of Achievement Earned dialog for special achievements 2014-09-21 19:04:35 +00:00
drdev
c9709a21f2 Uncomment hasCheated check that was mistakenly committed 2014-09-21 18:50:35 +00:00
drdev
ce00d3159a Use "Great" instead of "Huge" 2014-09-21 18:42:44 +00:00
drdev
f33bc09468 Shorten achievement name and prevent it's image being used for something else 2014-09-21 16:00:03 +00:00
drdev
b5aa3b429e Commit first set of alternate win achievements 2014-09-21 15:22:59 +00:00
Sloth
d6fa02582b - Fixed Stigma Lasher. 2014-09-21 15:18:51 +00:00
drdev
8f32e44223 Add keystore to SVN 2014-09-21 13:55:41 +00:00
drdev
4696b5ccbc Make stack wider (particularly on tablets) to prevent it wrapping as much 2014-09-21 13:46:25 +00:00
swordshine
4430dee771 - Added Deflecting Palm 2014-09-21 05:26:11 +00:00
drdev
ef25938d8e Clarify comment 2014-09-21 05:23:33 +00:00
drdev
d98a617592 Use height ratio for scaling instead of the min of width and height ratios 2014-09-21 05:21:57 +00:00
excessum
c9e74d3dc1 - Fixed token image names for Khans of Tarkir 2014-09-21 04:54:50 +00:00
drdev
d92c7233d5 Bump to API 20 properly 2014-09-21 04:22:21 +00:00
drdev
35dd00e365 Revert previous change 2014-09-21 04:03:57 +00:00
drdev
cc99b4533d Update platform to 20 2014-09-21 04:02:56 +00:00
drdev
9663105622 Tweak scaling logic so Android app looks better on tablets and so there's only 1 scaling function instead of 4
Version bump to 1.5.28.004
2014-09-21 03:49:57 +00:00
excessum
244293c119 - Added check for Ferocious when using Savage Punch 2014-09-21 03:43:17 +00:00
excessum
46033d55a9 - Implemented AI for Crater's Claws 2014-09-21 03:38:15 +00:00
Sol
3db4d519b7 - Updating triggers to a Register/Clear mechanism. Goal is to fix issue with Deathgreeter (etc) not triggering when multiple creatures LTB. 2014-09-21 03:12:43 +00:00
drdev
829d0f82e9 Fix GUI refactoring issue that was preventing Android app from working on mobile devices 2014-09-21 02:14:49 +00:00
Sloth
1ce3ed4407 - Fixed Crackling Doom. 2014-09-20 19:37:41 +00:00
Sloth
65feaca0c2 - Added draft rankings for KTK. 2014-09-20 19:35:20 +00:00
swordshine
9554275d0f - Added Villainous Wealth 2014-09-20 14:04:59 +00:00
excessum
20cf653fb1 - Fixed ordering of mana symbols in card costs 2014-09-20 13:33:14 +00:00
excessum
eeeeee8a1d - Fixed missing keyword for Efreet Weaponmaster 2014-09-20 12:51:26 +00:00
drdev
591b59df05 Make it easier to show a scaled version of the mobile dev app 2014-09-20 12:37:12 +00:00
swordshine
c9e4aa1c51 - Added Kheru Lich Lord 2014-09-20 12:33:14 +00:00
Sloth
c5a44c9b04 - Fixed a rare bug in knownOriginCanPlayAI (Norin the Wary bug). 2014-09-20 12:27:34 +00:00
swordshine
3eefce7176 - Added Howl of the Horde 2014-09-20 12:14:50 +00:00
excessum
c8b57e90ed - Extended OblivionRing logic for Suspension Field
- Implemented rudimentary logic for Outlast
- Fixed mana cost for Dazzling Ramparts
2014-09-20 10:24:43 +00:00
Agetian
072a0941e1 - Make a default value in AiProps correspond to the value set in the Default AI profile. 2014-09-20 08:03:11 +00:00
Agetian
5549604d0d - Tweak spell prediction when deciding whether to move equipment or not.
- Enable spell prediction (works for AttachAi only at the moment).
- The Default AI profile will only move equipment from one creature to another if the one it's currently attached to is useless, but will consider it a priority task to move equipment away from useless creatures.
- The Reckless AI profile will always move equipment from worse creatures to better ones but will prioritize getting as many threats and other permanents out before moving creatures around (currently - even if the creature the equipment is attached to was rendered useless).
2014-09-20 08:01:58 +00:00
Agetian
2abcc7c951 - Disable spell prediction for PumpAi. 2014-09-20 07:30:21 +00:00
Agetian
68f35d3a6f - Reverted some of the modifications related to the way spell prediction works (canPlaySa can't currently be a part of the process).
- Limited predictSpellToCastInMain2 to idenitifying permanents to put on the battlefield only.
- For now, keep spell prediction disabled until the conditions and effects are tested well enough and do not cause the AI to prevent itself from performing other priority tasks.
2014-09-20 07:24:12 +00:00
excessum
32a3f5964e - Implemented AI for Launch the Fleet 2014-09-20 07:10:18 +00:00
Agetian
f55ae8ab95 - Disable all prediction for Main 2 spells until I can figure out the stack overflow issue. 2014-09-20 04:48:53 +00:00
excessum
dd6d7e7ae8 - Fixed missing keyword for Icefeather Aven 2014-09-20 02:58:43 +00:00
excessum
3abb197fca - Fix for zero division error in PumpAiBase 2014-09-20 02:22:09 +00:00
Sloth
a19c05ca56 - Improved blocking AI for blockers that don't survive until the next turn anyway (due to Vanishing or Fading). 2014-09-19 22:22:17 +00:00
drdev
96ca7d1df8 Version bump to 1.5.28.003 2014-09-19 22:09:05 +00:00
drdev
d7d20925f3 Tweak previous fix 2014-09-19 21:52:21 +00:00
drdev
1d5c552bd9 Prevent updating achievements for a game where the user cheated using Dev mode functions 2014-09-19 21:50:13 +00:00
drdev
4cb64a18aa Refactor dev mode cheat functions into separate class that through it's restricted access allows determining if a player as cheated during a game 2014-09-19 21:45:24 +00:00
Sol
799e86bf0f - Improve tgt prompt for Jilt 2014-09-19 21:31:00 +00:00
drdev
1d092bf821 PLuralize certain dev mode actions 2014-09-19 20:54:35 +00:00
drdev
3b2a992999 Make name and order of Dev menu items be consistent 2014-09-19 20:47:27 +00:00
drdev
854030e6d4 Prevent remembering Dev Mode unlimited lands between games to prevent accidentally leaving it that way and then playing more than one land per turn
Clean up Dev Mode pane so case is consistent and toggle color is consistent with other labels
2014-09-19 20:33:49 +00:00
drdev
25b862ef5d Improve Achievement Earned dialog for mobile game 2014-09-19 19:50:22 +00:00
Chris
3d2d4555e7 Added new card names to changes.txt. 2014-09-19 17:39:25 +00:00
Agetian
9a9ebb59bd - NPE prevention in TargetingOverlay (not sure why getController would return null during an ongoing game in the first place though, might be worth investigating) 2014-09-19 14:19:51 +00:00
elcnesh
4a37042149 Restore support for ordering cards in hand. 2014-09-19 14:08:40 +00:00
elcnesh
fbee794685 Fix creatures displaying as "being blocked" incorrectly. 2014-09-19 07:44:25 +00:00
elcnesh
66768b6ddf Fix pile effects (Fact or Fiction) for new GUI code. 2014-09-19 07:39:45 +00:00
Agetian
cdcb9c84be - Added a way to disable predictive analysis for spells in Main 2 via an AI property PREDICT_SPELLS_FOR_MAIN2 (currently prediction is enabled by default for all profiles). 2014-09-19 04:39:44 +00:00
swordshine
b686341cbf - Fixed Meandering Towershell 2014-09-19 04:37:08 +00:00
Agetian
9564fba6f2 - Prevent an infinite loop when trying to process PumpAllAi in predictSpellToCastInMain2. 2014-09-19 03:54:36 +00:00
Sol
824cee4632 - Fixing small script issues 2014-09-19 03:15:59 +00:00
Sol
a56e6b761e - Updating edition file to correct Archers' Parapet name 2014-09-19 01:36:52 +00:00
Sol
81fdb73ff4 - Fix typo for name of Archers' Parapet 2014-09-18 23:18:56 +00:00
Sol
6b7f42147d - Updating mtg-data.txt
- Adding Oracle text to KTK
2014-09-18 23:10:30 +00:00
Sol
bd27893fd3 - Adding a handful of cards by Kapoue 2014-09-18 23:04:30 +00:00
Krazy
15ba70475b Fixed High Sentinels of Arashin missing its activated ability. 2014-09-18 22:27:37 +00:00
Sloth
99624e6527 - More little text and script fixes. 2014-09-18 21:19:30 +00:00
Sloth
efd9c0ed74 - Updated some AI SVars and fixed a typo. 2014-09-18 20:46:58 +00:00
Sloth
6103f9f87d - Updated blockdata and TypeLists. 2014-09-18 20:38:04 +00:00
Sloth
348591b966 - Merged KTK branch into trunk. 2014-09-18 20:03:04 +00:00
drdev
b1065c4328 Fix tooltip width 2014-09-18 19:39:34 +00:00
drdev
27f695963d Remove unnecessary period 2014-09-18 18:28:19 +00:00
drdev
b6222582fa Add support for displaying achievement earned dialog nicer 2014-09-18 18:25:59 +00:00
elcnesh
0d006b6ab6 Add a lot of comments to the view classes and remove a deprecated method. 2014-09-18 16:55:40 +00:00
drdev
ede7931deb Fix order more properly 2014-09-18 14:59:24 +00:00
drdev
076b87ab32 Fix achievement order 2014-09-18 14:58:07 +00:00
elcnesh
617f5d0889 Fix to prevent some concurrency issues. 2014-09-18 14:53:47 +00:00
Agetian
5a45730a0f - Return default property values from AiController.getIntProperty and AiController.getBooleanProperty in case of an erroneous call. 2014-09-18 14:50:44 +00:00
Agetian
b39ac29746 - Prevent NumberFormatException when AI properties are queried from runAsAi. 2014-09-18 14:42:34 +00:00
drdev
25842fe5ca Fix so Magic card back doesn't show through for transparent trophy 2014-09-18 14:37:59 +00:00
excessum
55dbe5bc09 - Changed isEffectiveAttacker() to ignore ability pumps.
- Reworked attack pumps for attackers
2014-09-18 13:23:08 +00:00
Sloth
3d85c7c791 - The AI will now take "CARDNAME can't be blocked except by three or more creatures." into account when attacking. 2014-09-18 12:34:49 +00:00
excessum
f37835b7d0 - Fixed PumpAiBase.pumpedCreature() not copying the attack/defense bonuses of the target creature. This should fix the AI's inability to apply repeatable attack/defense pumps. 2014-09-18 12:02:40 +00:00
Agetian
cf70a969b1 - At least for now, added an AI profile property RESERVE_MANA_FOR_MAIN2_CHANCE that indicates a chance that the AI would want to reserve mana for a main 2 phase spell. Currently set to 0 for all profiles (the AI will not reserve mana).
- The AI will obey mana reservations either if the spell ability is explicitly marked as low priority with SVar LowPriorityAI or, if it's not marked as low priority, depending on the random chance as specified in RESERVE_MANA_FOR_MAIN2_CHANCE.
2014-09-18 11:47:45 +00:00
Agetian
50553802e7 - Fixed the previously inverted logic. 2014-09-18 08:50:14 +00:00
Agetian
a902f5f1e7 - For now, ignore mana source reservations unless the AI has explicitly specified that the spellability is of low priority. 2014-09-18 08:46:16 +00:00
elcnesh
ac4a6049a5 - Hopefully reduce the P/T flickering.
- Assign a random negative int to each hidden CardView to prevent awt from crashing.
2014-09-18 08:26:42 +00:00
Agetian
1ea2b9d034 - Allow the AI to correctly predict the ability to cast a certain spell in Main 2 phase with the canPlaySa logic. 2014-09-18 08:05:37 +00:00
Agetian
57403ff053 - canPlay does not work as intended in context, removing for now. 2014-09-18 07:52:54 +00:00
Agetian
435adf41d9 - Removed a debug comment. 2014-09-18 07:46:20 +00:00
Agetian
67649130c7 - Modified the logic of Main 2 spell prediction to account for canPlay() 2014-09-18 07:42:35 +00:00
Agetian
973a7b6bc6 - For now, do not reserve mana for spells when deciding whether to pump/not to pump a creature (hopefully will get the AI screwed over in fewer cases than otherwise :) 2014-09-18 07:36:07 +00:00
Agetian
20b9b6fa17 - Fix the blocker targeting arrows not appearing in time because the declared blockers were not passed to the combat view until the blockers were finalized (please review). 2014-09-18 06:59:31 +00:00
drdev
547b570406 Refactor achievements to use new trophy style and offer 4 tiers 2014-09-18 05:39:47 +00:00
Agetian
69bc6d5ac4 - Fix the extra tap events firing from the Pump AI. 2014-09-18 05:15:38 +00:00
Sol
554f9cfc6f - Fixing toughness bonus for Spur Grappler 2014-09-18 00:49:15 +00:00
Krazy
23ff256892 Fixed Typo 2014-09-17 23:33:54 +00:00
Krazy
2ce558c3f4 Removed debugging line. 2014-09-17 23:22:13 +00:00
Krazy
bb1f61a2a9 Added support for Kin-Tree Invocation (KTK). 2014-09-17 23:11:15 +00:00
Agetian
f9bbaef92b - Attempt to fix the concurrent modification exception related to card extrinsic hidden keywords by using a thread-safe array list. 2014-09-17 19:37:01 +00:00
Agetian
5cec620a9f - Make sure that the AI does not randomly move the same equipment around from creature to creature within the same turn (the related logic is currently used in the Reckless AI profile). 2014-09-17 18:48:07 +00:00
Agetian
570b90b859 - Mistype fix, clarification. 2014-09-17 15:46:51 +00:00
Agetian
d06edd2ed3 - Attempt to fix NPEs related to SpellAbilityRestrictions queried with no activator set for the spell ability. 2014-09-17 15:38:19 +00:00
elcnesh
e710743a3b Fix cards showing up black and NPE's related to CardPanel. 2014-09-17 14:53:55 +00:00
Sloth
51b3d723b9 - The Prowess keyword will now set a BuffedBy SVar for the AI. 2014-09-17 13:39:38 +00:00
elcnesh
f75a2a8888 Fix displaying CARDNAME instead of the card name in SpellAbilities. 2014-09-17 08:42:40 +00:00
Sloth
7f0140332a - Updated the quest opponent Fred Flintstone 3. 2014-09-17 08:07:10 +00:00
elcnesh
8702eefb01 Fix "Play with top of library revealed" cards a prevent a possible NPE. 2014-09-17 07:36:40 +00:00
Sloth
c1f630dca6 - Updated some AI SVars. 2014-09-17 07:15:52 +00:00
drdev
12c6d98ec7 Add hover tooltip for achievement info 2014-09-17 05:28:40 +00:00
drdev
539a74b874 Support outlining the hovered achievement 2014-09-17 05:00:35 +00:00
drdev
2ab70d64c4 Fix selection issue 2014-09-17 04:44:24 +00:00
drdev
57e1cfe6b3 Simplify the way custom achievement images are loaded 2014-09-17 04:30:24 +00:00
drdev
69255650a8 Refactor shared parts of certain descriptions into separate field so it can be displayed on its own line 2014-09-17 04:13:17 +00:00
drdev
2a871c2525 Add Blackjack achievement 2014-09-17 03:46:35 +00:00
drdev
bf7832c14d Prevent multiple thread queues for loading custom achievement images on startup 2014-09-17 03:15:04 +00:00
Sol
ba3b6cbce0 - Adding purchase restrictions for Quest Pet based on the user's level 2014-09-17 03:04:52 +00:00
drdev
6d0f1364be Support custom achievement images for mobile app 2014-09-17 03:04:18 +00:00
drdev
d8cc47c8a3 Add temporary offset for custom images 2014-09-17 02:52:03 +00:00
drdev
bde2c72cf7 Support custom achievement images 2014-09-17 02:24:35 +00:00
drdev
bbc2a754f6 Add Poisoned and DeckedOut to quest achievements 2014-09-17 02:10:42 +00:00
drdev
a632216a4d Fix Decked Out key 2014-09-17 02:08:57 +00:00
drdev
9c5d6179aa Fix how shelf count is calculated 2014-09-17 01:27:18 +00:00
drdev
4decffe293 Add DeckedOut achievement 2014-09-17 01:18:41 +00:00
drdev
276f354e4b Add Poisoned achievement 2014-09-17 00:41:01 +00:00
drdev
3d3df48a43 Add NeedForSpeed achievement 2014-09-17 00:13:16 +00:00
drdev
9174b5b62a Refactor achievements to give more control over subtitle display to derived class 2014-09-16 23:52:51 +00:00
Chris
fbb87eff6a Added new card names to changes.txt. 2014-09-16 23:20:39 +00:00
Krazy
48778379f9 Fixed NPE for cards that Forge doesn't have yet. 2014-09-16 22:09:47 +00:00
drdev
a2e765220a Remove extra space 2014-09-16 21:06:35 +00:00
elcnesh
d3b6893d33 Fix (hopefully) attack icons on cards and a possible NPE. 2014-09-16 21:05:39 +00:00
drdev
8bade53caa Use the word "Active" instead of "Current" 2014-09-16 20:42:45 +00:00
drdev
084621f946 Improve achievement formatting options 2014-09-16 20:40:43 +00:00
drdev
fec98e99f9 Add support for negative thresholds 2014-09-16 20:19:45 +00:00
drdev
cbdc6bd78a Make wood intersections look a little softer 2014-09-16 19:07:10 +00:00
drdev
8b6f3b4c75 Make shelf top a little less tall
Allow shelves to flow from one to the next
2014-09-16 18:54:05 +00:00
drdev
aa197aaeef Switch to using hi-res shelf for achievements 2014-09-16 18:30:07 +00:00
drdev
9e56699220 Add achievements for each variant type 2014-09-16 17:52:19 +00:00
drdev
55b55e6abd Refactor achievements to support a core set of achievements that each game mode offers 2014-09-16 17:38:08 +00:00
drdev
7a347a50bc Fix Life to Spare thresholds 2014-09-16 16:19:39 +00:00
Agetian
63be2b5ee3 - A simpler way of counting shards. 2014-09-16 15:46:19 +00:00
Agetian
434baa66c6 - Added mana cost color shard count to deck statistics. Currently counts all individual mana symbols in mana costs (hybrid symbols count as one mana symbol of each color, Phyrexian symbols count as their respective color). Uses very basic text-based messages in the statistics UI, improvements are welcome. 2014-09-16 15:39:32 +00:00
elcnesh
12e331e2bd Fix some display problems:
- Update GUI after clone effects.
- Fix foil display on face-down cards.
- Update icons on card panels more aggressively.
2014-09-16 14:17:03 +00:00
elcnesh
2e48a21f0e Fix Alpha Strike. 2014-09-16 12:53:35 +00:00
swordshine
9c44a5ae55 - KTK: Added Meandering Towershell 2014-09-16 12:43:49 +00:00
elcnesh
6a9ef3d94e Fix showing all hands for hotseat and AI vs AI. 2014-09-16 11:59:03 +00:00
swordshine
1907b47a54 - Fixed Excise 2014-09-16 11:01:10 +00:00
elcnesh
9446a4e069 Fix text-changing Possessed Aven. 2014-09-16 10:18:37 +00:00
swordshine
62b1c791b4 - KTK: Added 2 cards 2014-09-16 08:24:41 +00:00
Sloth
e4c8567638 - Updated some AI SVars. 2014-09-16 07:57:27 +00:00
swordshine
f443f5943f - KTK: Added Empty the Pits 2014-09-16 07:39:39 +00:00
Agetian
5e09534c2e - More formatting fixes. 2014-09-16 07:13:41 +00:00
Agetian
33f3639d75 - Fixed text formatting. 2014-09-16 07:12:41 +00:00
Agetian
0c55123770 - Fixed Venomous Breath. 2014-09-16 07:00:25 +00:00
Agetian
90d4d3aa6f - Fix an index of bounds exception related to visualizing card information for cards with AF Charm. 2014-09-16 06:08:33 +00:00
swordshine
e508aaba7e - KTK: Added 3 cards 2014-09-16 05:54:41 +00:00
swordshine
5b0de3fc71 - KTK: Added 3 cards 2014-09-16 04:35:31 +00:00
Krazy
37c1cc9c54 Updated boolean expressions to really, actually, seriously work this time. 2014-09-16 00:49:44 +00:00
Chris
1c9975bf2a Added new card names to changes.txt. 2014-09-16 00:43:39 +00:00
drdev
3421b63c07 Fix so cards appear face down in hidden zones (like library) instead of not appearing in the zone at all 2014-09-15 23:18:51 +00:00
drdev
4f1aca385d Fix so command zone actually shows up 2014-09-15 23:14:11 +00:00
drdev
7628278300 Fix Tutor for Card dev mode option 2014-09-15 22:59:56 +00:00
drdev
b2af1be3ea Fix so card type appears properly on card list items 2014-09-15 22:39:32 +00:00
elcnesh
58c727ed66 Fix DeckHintsTest. 2014-09-15 22:28:35 +00:00
drdev
42b99b0b5e Refactor creation of Gui and AI lobby players into GamePlayerUtil
Fix so gui player name updated
Fix so multiple human players receive separate LobbyPlayerHuman instances
2014-09-15 22:26:55 +00:00
drdev
e658588771 Prevent duplicating class 2014-09-15 21:41:31 +00:00
drdev
a612161db2 Prevent stack order being reversed 2014-09-15 21:28:21 +00:00
drdev
d83fcbd26f Fix compile error 2014-09-15 20:59:08 +00:00
drdev
89e8899aba Resolve some merge conflicts and actually commit mobile game Auto-Yields menu item to SVN 2014-09-15 20:58:41 +00:00
elcnesh
0c896f4110 Some minor GUI fixes, amongst which fixes for Morph display and Ponder effects. 2014-09-15 19:29:48 +00:00
Agetian
89f5100ba8 - Added a missing dependency to forge-gui-desktop to fix compilation error. 2014-09-15 18:34:03 +00:00
Sloth
987cac7eab - Added "withoutAbilities" parameter to damageIfUnblocked function (fixes AI not pumping Killer Bees). 2014-09-15 13:02:24 +00:00
elcnesh
04f0fdbf4e Fix crash with Lens of Clarity. 2014-09-15 12:28:49 +00:00
elcnesh
1922a83c44 Merge GuiRefactoring back into trunk.
Note that this changes ALL the display code to not pass game objects directly into the GUI, so bear that in mind when merging local changes (and in future commits).
2014-09-15 12:12:02 +00:00
excessum
3fb3095311 - AI should not grant haste for tapped creatures with summoning sickness 2014-09-15 11:55:02 +00:00
elcnesh
a59f456fd1 Remove mergeinfo. 2014-09-15 11:30:30 +00:00
elcnesh
8bc99d7a5b Merged changes from trunk to GuiRefactoring: 27390-27405. 2014-09-15 11:17:15 +00:00
Agetian
e36983bd2e - Added a corner case for cost reduction of cards with color-locked X to the Known Issues list for now. 2014-09-15 04:14:12 +00:00
drdev
ee1855f432 Prevent rendering part of a shelf you can't scroll to 2014-09-15 04:11:06 +00:00
drdev
23e4024f8e Version bump to 1.5.28.002 2014-09-15 03:44:27 +00:00
drdev
fa831c0bcf Support tooltips for selected achievement 2014-09-15 03:35:15 +00:00
drdev
b05e6676d5 Reset selection when zooming 2014-09-15 02:44:03 +00:00
drdev
992d1b724d Support selecting an achievement 2014-09-15 02:34:54 +00:00
drdev
1e36dffb14 Support zooming trophy case 2014-09-15 02:16:38 +00:00
drdev
b989f59ac7 Fix layout logic for trophy case 2014-09-15 01:34:29 +00:00
drdev
159f6d51cf Start working on Achievements screen for mobile game 2014-09-14 23:36:57 +00:00
drdev
47fd531afc Support tracking colors of mana spent on X part of mana cost for cards like Soul Burn 2014-09-14 20:37:05 +00:00
drdev
e63276135f Code cleanup 2014-09-14 18:25:58 +00:00
drdev
7464f31f9b Fix so Soul Burn doesn't allow paying X with non-black, non-red mana 2014-09-14 17:47:10 +00:00
drdev
1d40924d0a Prevent Gorilla Shaman refunding mana after there are no more remaining targets 2014-09-14 16:55:10 +00:00
drdev
4e5b5e4d6c Simplify implementation of pre-announcing X 2014-09-14 16:44:42 +00:00
drdev
43ccd4d09e Code cleanup 2014-09-14 16:03:16 +00:00
Krazy
25f0b0b777 Prevent display of Lens of Clarity keyword in players panel. 2014-09-14 15:52:09 +00:00
drdev
5558273fbb Prompt for X if sVar is empty 2014-09-14 15:22:02 +00:00
drdev
a704220556 Cleanup whitespace 2014-09-14 14:49:59 +00:00
drdev
7cd2081cec Prevent prompting for X if user can't control what X is 2014-09-14 14:49:34 +00:00
drdev
d7f31fdda6 Prevent possible crash in checkZoneRestrictions 2014-09-14 14:27:58 +00:00
excessum
fd308ceee9 - NPE guard for previous commit 2014-09-14 13:03:06 +00:00
Agetian
8472b0f82a - Removed a debug comment. 2014-09-14 13:02:50 +00:00
excessum
4f20eb8a1a - AI should not regenerate creatures affected by burn spells with "can't be regenerated" 2014-09-14 13:00:22 +00:00
Agetian
0ae716f8a3 - Refactoring for card memory logic (moved the card memory reset routine that is to happen at every end of turn from the non-intuitive location in SA choice logic higher in the stack to a separate reset method in the player controller code). 2014-09-14 12:59:38 +00:00
elcnesh
6708e7ab32 Remove potentially problematic svn:mergeinfo properties. 2014-09-14 11:14:06 +00:00
elcnesh
6188509eee Merged changes from trunk to GuiRefactoring: 27379 2014-09-14 10:04:44 +00:00
Agetian
4518cd3c6c - A logic fix related to Main 2 spell prediction.
- Some card memory code refactoring.
2014-09-14 07:41:15 +00:00
elcnesh
00bf228e0f Merged changes from trunk to GuiRefactoring: 27326-27376. 2014-09-14 07:17:49 +00:00
elcnesh
7d8ec24fbe Prevent possible NPE. 2014-09-14 06:19:59 +00:00
Agetian
66973f5954 - Remember the actual moved equipment, not its target (fixes random "reconsideration" jump). 2014-09-14 06:15:32 +00:00
elcnesh
a31e273147 Some more minor fixes for GUI refactoring (restores full playback control). 2014-09-14 06:15:11 +00:00
Agetian
037f30ebe9 - Prevent the Reckless AI (with MOVE_EQUIPMENT_TO_BETTER_CREATURES=true) from randomly moving equipment back and forth between two creatures with similar evaluation.
- Some code reorganization related to AI card memory.
2014-09-14 06:06:35 +00:00
excessum
3503caf77d - Fixed PumpAiBase.pumpedCreature() not copying the tap-state and extra keywords of the target creature 2014-09-14 06:02:40 +00:00
drdev
e74882a934 Improve trophy appearance 2014-09-14 06:00:30 +00:00
Agetian
0c6b92cf78 - Fixed a NPE when entering deck editor. 2014-09-14 04:23:21 +00:00
drdev
9d9c5b83d7 Fix so trophies appear in order 2014-09-14 04:19:57 +00:00
drdev
4bb0fd2911 Add support for showing trophy name plates 2014-09-14 04:13:25 +00:00
Agetian
f206a73f89 - Take two at fixing the Pump Ai: hopefully will no longer dumb-spam non-stacking pumps while still pumping creatures with "aggressive" (attack-increasing) pumps when necessary. 2014-09-14 03:50:00 +00:00
Krazy
b67a39cd52 Fixed long-standing quest draft bug in which hundreds of booster packs would be awarded for old sets. The names of booster packs are now correctly formatted and a reasonable number of packs are now awarded. Also, the amount of leeway for determining the number of packs to award is now a percentage instead of a flat value. If there's 10% or less of the price of a booster pack needed to award another, it will be awarded anyway. 2014-09-14 02:49:18 +00:00
Krazy
2b4fef3e07 Quest drafts now award a player-selectable rare from the block of the draft. Spending draft tokens allows the player to pick which block the draft is instead of it being random. 2014-09-14 02:34:04 +00:00
drdev
5b6925891c Make trophy case bigger 2014-09-14 01:00:46 +00:00
drdev
4f20fafffa Create layout for Achievements screen
Improve trophy appearance
2014-09-13 23:36:59 +00:00
Krazy
2544d5c8f5 Fixed morphed card text not showing up in details panel with Lens of Clarity on the battlefield. Added reminder to the details panel that morphed cards can be looked at when you control a Lens of Clarity. 2014-09-13 23:18:23 +00:00
Krazy
20ef2a9d27 Added support for Lens of Clarity. 2014-09-13 22:56:30 +00:00
drdev
23fc246ea5 Add Achievements submenu 2014-09-13 21:11:31 +00:00
drdev
44f0b5b25a Ensure game type mapped to game type with associated achievements 2014-09-13 20:08:28 +00:00
drdev
8016bedd58 Refactor Achievements to support separate achievements for each main game format 2014-09-13 20:03:35 +00:00
Krazy
835ecb735c Updated display of charm-like spells in the card details panel to look like the new cards in KTK. 2014-09-13 20:00:32 +00:00
Sloth
8e5b5c8b4f - Little improvement for the sortManaAbilities function. 2014-09-13 19:12:21 +00:00
drdev
d028c1e235 Make logic smarter for sorting cards to use for auto-payment of mana abilities 2014-09-13 17:24:46 +00:00
drdev
3ffa15019f More code cleanup 2014-09-13 16:43:44 +00:00
drdev
9fc3798e30 Code cleanup 2014-09-13 16:38:51 +00:00
drdev
d0c08eb8ff Fix unintentional error 2014-09-13 16:35:11 +00:00
Chris
f8570802b3 Added a fluff piece to the changes.txt file.
Added new card names to changes.txt.
2014-09-13 16:33:39 +00:00
drdev
93447295d7 Fix warnings 2014-09-13 16:32:07 +00:00
drdev
02fc761d93 Prevent crash when opening Scheme Deck Editor 2014-09-13 16:24:12 +00:00
drdev
8aaa1da773 Restore version back to 1.5.28 and update mobile game to match 2014-09-13 16:13:28 +00:00
Agetian
2ddcc854a3 - Fixed delayed parameter propagation for Extort. 2014-09-13 16:09:12 +00:00
drdev
0746814595 Add checkbox to start with all cards in selected sets 2014-09-13 16:07:30 +00:00
drdev
91ccdc1f75 Change version back to 1.5.27 2014-09-13 15:49:11 +00:00
Chris
2f4ffcb72e update 2014-09-13 15:27:24 +00:00
Chris
216832b9f0 Added new card names to changes.txt. 2014-09-13 14:53:23 +00:00
swordshine
3d7aa2a864 - We'd better not remove "TriggeredCardController$Valid Spirit.YouCtrl" in Kodama of the Center Tree, otherwise there would be bugs when it was not controlled by the owner 2014-09-13 13:58:09 +00:00
swordshine
2ff284831c - KTK: Added 2 cards 2014-09-13 13:49:41 +00:00
Agetian
8706470491 - Fixed Kodama of the Center Tree. 2014-09-13 13:48:28 +00:00
swordshine
6c0f34c3b9 - Elixir of Immortality should not shuffle the library twice
- New CounterType Gem
2014-09-13 13:35:27 +00:00
Agetian
d65d6ee16a - A better and more correct fix for X propagation. 2014-09-13 13:24:51 +00:00
Agetian
e1004a6f52 - Attempt to fix the value of X not being announced to subabilities. Fixes Sphinx's Revelation. Please review. 2014-09-13 13:18:08 +00:00
elcnesh
295423050b Merged changes from trunk to GuiRefactoring: 27297-27319. 2014-09-13 07:53:24 +00:00
elcnesh
36c11018c6 Fix playback controls plus some other stuff in GUI refactoring. 2014-09-13 07:22:53 +00:00
Chris
7020fa97ac [maven-release-plugin] prepare for next development iteration 2014-09-13 02:43:34 +00:00
Chris
268ab4c547 [maven-release-plugin] prepare release forge-1.5.27 2014-09-13 02:43:19 +00:00
drdev
4eb2fd50a2 Version bump to 1.5.27.002 2014-09-13 00:21:43 +00:00
drdev
41e610c985 Cleanup whitespace 2014-09-13 00:16:04 +00:00
drdev
b084b7c85d Always allow unselecting cards for InputSelectManyBase 2014-09-13 00:06:14 +00:00
drdev
bbbdb643ad Ensure used to pay flag reset if user cancels InputSelectManyBase 2014-09-12 23:58:28 +00:00
drdev
da9071d160 Code cleanup 2014-09-12 23:54:01 +00:00
drdev
b7c8a57730 Improve message for Devour 2014-09-12 23:45:55 +00:00
Krazy
014c02b4d0 Somehow an old module that I deleted survived and got committed to the main project pom.xml. This reverses that and lets the project build again. Sorry! 2014-09-12 23:06:25 +00:00
drdev
9afdcc743e Prevent tokens stacking if they have different counters on them 2014-09-12 23:01:48 +00:00
Krazy
7abc680aa7 Added option to start quests with 4 copies of each card in selected sets. 2014-09-12 22:55:50 +00:00
Krazy
7ec3211931 Fixes for drafts not rotating, small tweak to boolean expressions, estates bonus % and amount now both displayed. 2014-09-12 22:50:34 +00:00
drdev
3a4fa42956 Fix so isAi properly set for the sake of random deck generation 2014-09-12 22:21:54 +00:00
drdev
18ff21c964 Update Android app to 1.5.27.001 2014-09-12 22:14:34 +00:00
Krazy
46b9dd67ab Fix for cards such as Nykthos, Shrine to Nyx causing NPEs when being sorted for AI mana payment. 2014-09-12 21:49:50 +00:00
Chris
9b40940292 Cleared out the changes.txt file, now ready for new material. 2014-09-12 17:18:51 +00:00
Chris
008b6eca4f [maven-release-plugin] prepare for next development iteration 2014-09-12 16:26:32 +00:00
Chris
b59c5f752d [maven-release-plugin] prepare release forge-1.5.26 2014-09-12 16:26:20 +00:00
Chris
61d503aaa8 Preparing the changes.txt file for the next beta build and release. 2014-09-12 15:51:08 +00:00
Chris
388f77ae3f Added new card names to changes.txt. 2014-09-12 15:45:56 +00:00
elcnesh
22374664f7 Allow Human vs Human games in GUI refactoring, plus some minor fixes. 2014-09-12 13:06:54 +00:00
elcnesh
c3e9ff7e5b Merged changes from trunk to GuiRefactoring: 27266-27293; plus some minor fixes. 2014-09-12 11:07:11 +00:00
Agetian
05729db2d0 - Removed an outdated comment. 2014-09-12 04:20:58 +00:00
Sloth
f0633ad5b7 - Fixed AI playing Molting Harpy and friends without being able to pay the upkeep next turn. 2014-09-11 20:10:02 +00:00
elcnesh
1ba2cb498b HUGE update to the GUI refactoring, fixing most known bugs and making everything run a lot faster and smoother.
Fixed: exceptions during combat, display of face-down cards, searching libraries, mindslaver effects, and more.
2014-09-11 15:46:33 +00:00
Agetian
8c6d9615a8 - Raise the max mulligan limit to 3 cards for Reckless AI. 2014-09-11 12:26:18 +00:00
Agetian
1d19e6cf44 - Attempt at NPE prevention related to achievements code. 2014-09-11 11:57:03 +00:00
elcnesh
fbcc8dbf1c Fix planes and schemes in GUI refactoring. 2014-09-10 13:00:49 +00:00
elcnesh
574e12d2e3 Lots of small fixes and cleanup for the GUI refactoring. 2014-09-10 12:08:48 +00:00
Agetian
3f66ff2975 - More AI-related clarifications. 2014-09-10 04:23:17 +00:00
Agetian
d4cded46bb - Some AI-related clarifications to CHANGES.txt. 2014-09-10 04:16:33 +00:00
Agetian
7455437fc8 - The AI will move equipment off of creatures that are no longer controlled by the AI. 2014-09-10 03:49:31 +00:00
drdev
add4f12e8b Add trophy images 2014-09-10 02:12:56 +00:00
drdev
f97cdc62f1 Allow showing larger icons in message box 2014-09-10 01:12:15 +00:00
drdev
7ea9109236 Fixed thresholds for Life to Spare 2014-09-10 00:41:43 +00:00
drdev
d87a863623 Add Overkill and Life to Spare achievements 2014-09-10 00:36:46 +00:00
Chris
a4143a47f5 Added new card names to changes.txt. 2014-09-10 00:07:51 +00:00
drdev
c3cdc4e99d Fix bronze threshold 2014-09-10 00:06:41 +00:00
drdev
44fc0778e8 Start support for achievements 2014-09-10 00:03:31 +00:00
Agetian
fb50fab9d6 - Attempt to stay on two AI profiles for now (Default and Reckless). Set the Default AI to move equipment only from useless creatures to useful ones, seems reasonable (will keep testing). 2014-09-09 18:55:11 +00:00
Agetian
8681266e16 - Added some information about the AI improvements to CHANGES.txt. 2014-09-09 18:44:02 +00:00
Agetian
072fc12d1d - Some extra NPE protection. 2014-09-09 18:37:31 +00:00
Agetian
7e7a069455 - Added a new AI profile property: MOVE_EQUIPMENT_TO_BETTER_CREATURES. Defines whether the AI will always move equipment to better creatures if it has mana ('always'), only move if the currently equipped creature becomes useless ('from_useless_only'), or never moves equipment around ('never').
- Added a new AI profile: Tricky (doesn't mulligan too heavily, moves equipment around from useless creatures).
- Default AI profile will not move equipment around (similar to how Forge operated before this change).
- Reckless AI profile will always move equipment to new more powerful creatures if it has enough mana and doesn't have other Main 2 plans.
- Some related refactoring.
2014-09-09 18:34:11 +00:00
Agetian
3173e330fa - Improved AttachAi such that the AI can choose to equip a different creature with an equipment that was already placed on a creature before. Currently set to make sure to hold mana for a predicted spell to cast in Main 2. Will help along with better use of equipment once equipped creatures get Arrest'ed or when a more powerful creature is played and the equipment is better used elsewhere. 2014-09-09 17:38:52 +00:00
elcnesh
b608d7e7a3 First attempt at converting the Android code for the GUI refactoring (untested). 2014-09-09 14:03:54 +00:00
elcnesh
e160267520 Refactor ForgeConstants to work with android also. 2014-09-09 14:02:33 +00:00
elcnesh
ecdd2b2995 Merged changes from trunk to GuiRefactoring: 27239-27260 2014-09-09 09:30:57 +00:00
elcnesh
0222c64b62 Fix many more problems with the GUI refactoring (plus some preparations for mobile GUI support). 2014-09-09 08:37:17 +00:00
Agetian
38bd41cec6 - Added a special AI logic to guild lands such that the AI does not bounce played guild lands back to hand with their own triggered ability. 2014-09-09 05:46:49 +00:00
Sol
9725fd30ee - Adding a Minimum amount of Packs Field for Quest mode.
- Slight increase to Quest Packs available in the Spell Shop
2014-09-08 23:55:28 +00:00
drdev
f921a2e44e Remove outdated comment 2014-09-07 23:14:50 +00:00
drdev
9b0776f353 Version bump to 1.5.26.005 2014-09-07 23:13:03 +00:00
drdev
e64de69a39 Make it so X mana costs are paid using a pre-mana payment announcement 2014-09-07 21:54:12 +00:00
drdev
407bc67af9 Support Replicate using pre-mana cost announcement 2014-09-07 21:15:31 +00:00
drdev
622896c398 Fix typo for Replicate 2014-09-07 20:45:22 +00:00
drdev
cdf4a891d7 Optimize card loading 2014-09-07 20:44:07 +00:00
drdev
b0cba37cb5 Fix typo for Transmute 2014-09-07 20:16:34 +00:00
drdev
683ccbcf41 Fix so MultiKicker is announced before mana paid 2014-09-07 20:15:16 +00:00
drdev
3427709c7b More code cleanup 2014-09-07 18:52:08 +00:00
drdev
cda130b233 More code cleanup 2014-09-07 18:38:53 +00:00
drdev
b8b26657f9 More code cleanup 2014-09-07 18:31:39 +00:00
drdev
1fca98c134 Code cleanup 2014-09-07 17:39:08 +00:00
drdev
be826672f2 Refactor variant descriptions into GameType enum 2014-09-07 17:35:54 +00:00
drdev
cd69a0f4e2 Refactor so variant checkboxes display same description in tooltip as used by mobile game 2014-09-07 17:23:36 +00:00
drdev
7f57ea6509 Fix so deck chooser doesn't reappear inappropriately when switching to another screen and back 2014-09-07 17:03:30 +00:00
drdev
16d325551d Cleanup tabs 2014-09-07 16:35:53 +00:00
drdev
f3060b177a Add Momir Basic variant to Constructed screen 2014-09-07 16:35:17 +00:00
drdev
228f7db0e3 Fix so paying X mana cost for Auto is run as AI 2014-09-07 16:03:49 +00:00
drdev
221b084679 Add Auto support for paying X mana costs 2014-09-07 15:24:14 +00:00
elcnesh
7bc8bf6c9c Merged changes from trunk to GuiRefactoring: 27198-27235 (mobile and android projects) 2014-09-07 09:50:18 +00:00
elcnesh
5925c35486 Merged changes from trunk to GuiRefactoring: 27198-27235 2014-09-07 09:27:46 +00:00
elcnesh
c931379ce8 Fix many problems and errors encountered while testing the GUI refactoring. 2014-09-07 08:51:40 +00:00
Agetian
160d23f3d4 - Removed a superfluous comment. 2014-09-07 05:59:56 +00:00
Agetian
e65adb6dff - Improved the AttachAi to account for cases when attaching a card is useless even though basic evaluation of the target may show otherwise (e,g, it's useless to equip a creature if this creature can't attack or block or if it's tapped and won't untap normally during the untap step, even if the said creature is evaluated as the best creature for its high CMC in ComputerUtilCard.evaluateCreature). 2014-09-07 05:56:20 +00:00
swordshine
b29852df19 - KTK: Added Dragon's Eye Savants, Horde Ambusher, Ruthless Ripper, Watcher of the Roost 2014-09-07 04:40:57 +00:00
swordshine
b017d2156f - Added Duel Decks: Speed vs. Cunning edition file 2014-09-06 11:41:28 +00:00
swordshine
c7f0d5316c - KTK: Added Clever Impersonator, End Hostilities, and Ugin's Nexus 2014-09-06 05:34:25 +00:00
swordshine
0d2b5ea076 - Fixed Mystical Teachings 2014-09-06 04:29:58 +00:00
Agetian
c080f5cb19 - Fix a rare NPE related to trying to show a card to a particular player outside of game context.
- Allow all cards to be shown the player when in developer mode (in order to be consistent with the fact that the player is able to see everything in dev mode including both players' hands and the content of both libraries).
2014-09-06 04:24:39 +00:00
drdev
fe63fd8925 Code cleanup 2014-09-05 22:20:34 +00:00
drdev
71afc97573 Prevent error when failing to assign a required blocker 2014-09-05 21:40:45 +00:00
drdev
162435ca52 Fix so Oracle Text appears on fallback image for copies 2014-09-05 14:18:16 +00:00
drdev
09221a180e Prevent showing "Waiting for opponent..." when not actually waiting for opponent 2014-09-05 13:56:10 +00:00
Agetian
b834a03172 - Added a way for the AI to ignore the fact that the mana sources have been reserved in case some high priority spell needs to be cast (e.g. for the cases where a regen ability has to be activated for a creature but all the mana has previously been reserved for a future spell). Currently not very smart, basically considers everything "high priority" except for the +X/+X pumps that the mana is initially reserved for. Feel free to improve. 2014-09-05 13:52:22 +00:00
drdev
67c5dedd5e Prevent game getting stuck if you try to End Turn at a time when you can't pass priority, such as while paying mana cost 2014-09-05 13:46:43 +00:00
Agetian
cfcb0b7549 - Refactored the code that deals with holding mana sources for spells. Still need to figure out where to best place the decision to hold mana so that the AI is not too conservative in its plays related to useful pump spells. 2014-09-05 06:20:28 +00:00
Agetian
aa6c0e9208 - Renamed a method to be more self-explanatory. 2014-09-05 04:27:03 +00:00
Agetian
e2b8c5156d - Renamed a method to be more self-explanatory. 2014-09-05 04:26:23 +00:00
Agetian
2b9a8bf05b - Fixed a bug that caused an illegal cast when the AI wrongly tried to determine if it has reserved mana sources for creatures on the human's side of the battlefield.
- General code cleanup related to the reserved mana sources code.
2014-09-05 04:21:25 +00:00
Agetian
a481c0b536 - Highly experimental: added a way for the AI to reserve mana for casting a Main 2 phase spell when deciding whether to pump a creature or not. This may not be optimal and probably needs refactoring as well. It's a somewhat drastic changes so bugs may arise (though the main use cases were tested). Please assist if possible. 2014-09-04 20:18:48 +00:00
elcnesh
1f62869b24 Fix the refactored GUI code so that games can now be played. 2014-09-04 18:08:22 +00:00
Agetian
8041d7a440 - Temporarily commented out the parts of AI card memory code that will not be used in the nearest future. 2014-09-04 13:56:27 +00:00
Agetian
90367cbc93 - Simplified the AI card memory interface. No more need to store the reference to a player and complicate matters with individual memory sets for each player. 2014-09-04 13:53:26 +00:00
Agetian
10bc6f92b7 - Added a basic card memory mechanism that allows the AI to temporarily mark certain cards in game zones for future decisions.
- Added a way for the AI to mark temporarily stolen creatures that return to the original controller at end of turn as "mandatory attackers" so that the AI doesn't miss the opportunity to attack with a creature that will otherwise be worthless for the AI.
2014-09-04 12:12:07 +00:00
elcnesh
2d1f2dc1ae Fix the last problems related to inputs. All errors are fixed, it's time to test! 2014-09-04 10:53:00 +00:00
elcnesh
89b3395cec Completely refactor the GUI code.
All direct references to a gui have been replaced by a field, allowing dynamic GUI assignment throughout the code (necessary for eg. network play). Fixes almost all errors. Untested.
2014-09-04 09:44:31 +00:00
Sol
fb4ac61919 - Combat.getBandOfAttacker() should only return from lkiCache if the card found in the cache actually was attacking 2014-09-04 03:10:01 +00:00
elcnesh
1a9b54cdd4 Update combat display code in GUI refactoring branch 2014-09-03 12:21:24 +00:00
elcnesh
608cae2572 Refactor GameLog in new GUI code. 2014-09-03 10:47:51 +00:00
elcnesh
b40c999cce Remove a lot of (now deprecated) GUI code. Removes almost all warnings from the desktop code. 2014-09-03 09:49:50 +00:00
elcnesh
af494b13b0 More GUI code refactoring. Fixes all errors in forge-gui-desktop! 2014-09-03 08:38:38 +00:00
Chris
f82a844730 Added new card names to changes.txt and moved some older material from changes.txt to readme.txt. 2014-09-02 14:48:27 +00:00
drdev
147255108a Fix typo that resulted in 24 Swamps and 0 Forests for Momir Basic
Version bump to 1.5.26.004
2014-09-02 12:21:46 +00:00
elcnesh
01c2648555 Add views to GUI refactoring, and update some more code. 2014-09-02 10:37:11 +00:00
elcnesh
e4f6c7cb5d Branch GUI refactoring.
Most of the code has been converted, but some problems remain (mostly with Inputs). Nothing has been tested yet.
2014-09-02 08:29:19 +00:00
Krazy
6418962357 Small update to further improve mana ability ordering. Multi-mana producing cards are given even lower priority. 2014-09-01 20:41:52 +00:00
Krazy
c1eada4c21 Made the AI smarter in picking which mana abilities to use. Pain lands will only be used when necessary, creatures will be tapped last, and abilities that produce multiple mana will be left available, among other possible interactions. 2014-09-01 20:31:23 +00:00
drdev
512ca12a70 Version bump to 1.5.26.003 2014-09-01 18:19:26 +00:00
drdev
ba4af4af35 Update CHANGES.txt 2014-09-01 18:16:25 +00:00
drdev
95fd905c5a Avoid needing to show Commander effect black rectangle in command zone
Make it so when Commander effect needs to be displayed (such as for confirmation dialog for replacement effect), the commander's name and image are used
2014-09-01 18:02:47 +00:00
drdev
157d8ff187 Format reminder text in message dialogs 2014-09-01 15:44:11 +00:00
drdev
d82334c7be Fix so commander deck initialized correctly 2014-09-01 15:22:37 +00:00
drdev
8cb4405297 Prevent lands getting cut off by command zone 2014-09-01 14:52:06 +00:00
drdev
71503072a3 Prevent showing command zone wider than 2 cards wide 2014-09-01 14:24:29 +00:00
excessum
fa857b7d38 - AI will bounce the attacker to save its blocker(s) instead of bouncing the blocker(s) 2014-09-01 12:45:14 +00:00
Agetian
6a4b140ffe - For now, changed Battlefield Forge to Arid Mesa in Vanellope von Schweetz 2 deck because the AI uses Battlefield Forge suboptimally. 2014-09-01 07:43:00 +00:00
Agetian
44e429eae3 - Added a Hard version of Vanellope von Schweetz deck. 2014-09-01 07:28:04 +00:00
swordshine
ba0d208d6f - KTK: Added Ainok Bond-Kin and Mardu Skullhunter 2014-09-01 04:36:45 +00:00
drdev
45942de46f Support showing command zone inline with lands instead of in a tab 2014-09-01 04:12:42 +00:00
drdev
4160e78d39 Support actually starting a Momir Basic game and lay the groundwork for other game types with auto-generated decks 2014-09-01 02:58:58 +00:00
drdev
46111bda6c Support Momir Basic variant type for mobile game 2014-09-01 02:02:27 +00:00
drdev
1e901cb59a Code cleanup 2014-09-01 01:51:38 +00:00
drdev
034f56d331 Add Momir Basic format and game type 2014-09-01 01:17:45 +00:00
Agetian
d55286e373 - Added a new deck Vanellope von Schweetz 2, a medium "race" W/R deck that tries to build a large number of buffed Haste creatures and tokens to deal critical damage. This deck will also "glitch" the damage through to the opponent's face and "glitch away" the opposing threats with cheap removal. 2014-08-31 17:34:14 +00:00
swordshine
8ef85b3628 - KTK: Added Herald of Anafenza 2014-08-31 05:21:28 +00:00
swordshine
6ef84ea656 - KTK: Added Dragon-Style Twins 2014-08-31 04:38:34 +00:00
elcnesh
bb9fac0f2d Fix possible error with merging keyword changes. 2014-08-30 22:53:45 +00:00
drdev
689890941c Version bump to 1.5.26.002 2014-08-30 22:20:44 +00:00
drdev
9b24119eab Make it so mana pool is shown if you prompted to pay mana after floating mana 2014-08-30 22:14:49 +00:00
drdev
c2155a5a57 Prevent stack text being shrunk improperly 2014-08-30 21:23:26 +00:00
drdev
16c140c7ad Prevent abilities being put on the Undo stack if not activated by Gui player 2014-08-30 21:11:16 +00:00
drdev
3227bd6963 Update CHANGES.txt 2014-08-30 20:58:41 +00:00
drdev
0e6b4c2046 Support auto-targeting single target for triggered abilities 2014-08-30 20:57:53 +00:00
drdev
c85e46e905 Version bump to 1.5.26.001 2014-08-30 20:47:26 +00:00
Chris
bc65e884f8 [maven-release-plugin] prepare for next development iteration 2014-08-29 14:43:59 +00:00
Chris
4f509f28b7 [maven-release-plugin] prepare release forge-1.5.25 2014-08-29 14:43:45 +00:00
Chris
137570d134 Preparing the changes.txt file for the next beta build and release. 2014-08-29 14:10:15 +00:00
Chris
9f2827ed0e Added new card names to changes.txt. 2014-08-29 14:07:38 +00:00
Agetian
abacd41e47 - For now, only keep pumping the creature if it actually increases its effective power. 2014-08-29 06:55:37 +00:00
Agetian
ccf04c97e6 - An experimental update to PumpAiBase that allows the AI to pump attackers when they will be left unblocked or when the pumped attacker is not predicted to be destroyed in combat. 2014-08-29 05:37:15 +00:00
Krazy
4c815e8c5a Fixed the previous fix to not decrement the active draft (if any). 2014-08-28 21:56:05 +00:00
Krazy
6db8531c1e Fixed quest draft age not getting decremented at all, resulting in infinite tournament availability. 2014-08-28 21:52:10 +00:00
Sol
2e165afb13 - Kookus trigger description cares about a Keeper for himself, not himself. 2014-08-27 12:19:00 +00:00
Sol
1eb6acd5c3 - Add MaxTgt to Wheel and Deal for multiplayer games. 2014-08-27 03:08:54 +00:00
Sloth
eb089053c9 - Updated 2 quest decks. 2014-08-26 22:12:55 +00:00
Sloth
ec62700bb6 - Added an easy version of the Madama Hydra opponent.
- The AI can now use Wretched Banquet.
2014-08-26 21:55:50 +00:00
Sloth
ee500cb6bd - Fixed AI using Glowing Anemone. 2014-08-26 07:14:32 +00:00
drdev
9234013d02 Version bump to 1.5.25.006 2014-08-26 05:00:58 +00:00
drdev
d0ee47f066 Support buffered images rendered dynamically 2014-08-26 03:29:27 +00:00
drdev
e1f1d96413 Update CHANGES.txt 2014-08-25 23:12:59 +00:00
drdev
fc46f91bac Version bump to 1.5.25.005 2014-08-25 22:55:47 +00:00
drdev
d0a0b45a6e Add timeout to reading URL from website 2014-08-25 22:54:53 +00:00
drdev
cb7ff871dd Add timeout to prevent spending forever trying to determine an Internet connection 2014-08-25 22:43:56 +00:00
drdev
acf3aa6693 Make it so "target opponent" cards auto-target your opponent when playing 1v1. 2014-08-25 22:23:38 +00:00
drdev
adf11e77da Fix so version file published with apk 2014-08-24 19:05:44 +00:00
drdev
fb50b49d07 Ensure running .apk is done as a separate task 2014-08-24 18:41:16 +00:00
drdev
efa6b60b47 Fix so Android app is fully closed when exiting 2014-08-24 18:06:26 +00:00
rikimbo
32cac7b12c Changed the "First Mulligan is Free" quest item logic so that the sequence of mulligans is 7-7-6-5-4-3-2-1 instead of 7-7-5-4-3-2-1. 2014-08-23 21:28:47 +00:00
Sloth
9263d1faa2 - Fixed ability text of Wishmonger. 2014-08-23 20:33:29 +00:00
drdev
cc8e3f41f6 Change download directory for apk file 2014-08-23 19:19:39 +00:00
Sloth
f9ce33310b - Added Wishmonger (The AI is ready for it now). 2014-08-23 19:01:47 +00:00
drdev
597821b866 Fix technique for running installer 2014-08-23 17:50:55 +00:00
drdev
f38a33456c Version bump to 1.5.25.004 2014-08-23 16:56:54 +00:00
drdev
d99547f21c Restore flag for sharing desktop assets 2014-08-23 16:52:46 +00:00
drdev
0325fac63e Cache process ID before calling finish 2014-08-23 16:52:07 +00:00
drdev
121f7f2b91 Add call to finish activity on exit 2014-08-23 16:51:32 +00:00
drdev
c5cad6e4b0 Support running installer after exiting 2014-08-23 16:46:41 +00:00
drdev
961cedc549 Refactor file downloading code 2014-08-23 15:58:05 +00:00
drdev
34e2daaeb0 Make it easier to test downloading separate asset files 2014-08-23 15:49:10 +00:00
drdev
697a90dfa3 Add support for testing assets downloading on desktop 2014-08-23 15:43:48 +00:00
drdev
3ba6cf2ec7 Add extra little message if not connected to wifi 2014-08-23 15:10:45 +00:00
drdev
37abd1ffcf Add support for checking for updates
Support not parsing reminder text for FTextArea
2014-08-23 15:03:03 +00:00
drdev
320aa2590e Support uploading version.txt file to main installer folder 2014-08-23 14:45:24 +00:00
excessum
de1d214a16 - Basic fix for PumpAiBase.shouldPumpCard() to enable the AI to use abilities that grant "Lifelink" 2014-08-23 12:18:26 +00:00
Sloth
fc71b705f8 - Fixed Pale Wayfarer. 2014-08-23 11:16:36 +00:00
excessum
450359a677 - Flagged Roaring Primadox as AI-unplayable as the AI is terrible with persistent upkeeps 2014-08-23 08:16:47 +00:00
excessum
19b50b4ff8 - Improved logic for AiAttackController.toProtectAttacker() and added documentation 2014-08-23 08:10:35 +00:00
drdev
ba9de8197b Improve prompt when no internet connection 2014-08-23 04:00:39 +00:00
drdev
cc566a1d68 Version bump to 1.5.25.003 2014-08-23 03:46:21 +00:00
drdev
0c5fa57737 Show "Checking for updates..." on splash progress bar 2014-08-23 03:33:45 +00:00
drdev
9aa23e0436 Avoid checking for assets when running from desktop 2014-08-23 03:29:27 +00:00
drdev
705615c8d5 Fix so dialogs can display before skins loaded fully 2014-08-23 03:23:50 +00:00
drdev
f88fa044d0 Add support for prompting user before downloading assets 2014-08-23 02:23:26 +00:00
drdev
bef9d66ffe Add support for testing network connection 2014-08-23 01:45:24 +00:00
Sloth
afff639130 - Added the medium quest opponent Madame Hydra 2. 2014-08-22 22:22:34 +00:00
Chris
be23391955 Added new card names to changes.txt. 2014-08-22 19:47:52 +00:00
drdev
c5a3db8f92 Version bump to 1.5.25.002 2014-08-22 05:20:37 +00:00
drdev
da54f86aca Prevent spell shop crash when items bought or sold 2014-08-22 05:18:09 +00:00
drdev
e1e2eb0c92 Give user a chance to respond if opponent blocks a creature they were forced to attack with after pressing End Turn 2014-08-22 04:36:23 +00:00
drdev
1b26d6677b Ensure creatures that must attack do so even if you End Turn before combat 2014-08-22 04:23:22 +00:00
drdev
7a98346356 Cancel auto-pass for all opponents of activating player when a new non-triggered ability is put on the stack 2014-08-22 04:00:59 +00:00
drdev
d0dae3d7f8 Fix typo 2014-08-22 00:38:08 +00:00
swordshine
4139f46f91 - KTK: Added Jeskai Elder 2014-08-21 12:01:40 +00:00
elcnesh
cc7098e31b Display text changes in keywords. 2014-08-21 09:47:23 +00:00
elcnesh
1922fdde66 Fix bug in Swirl the Mists (accidentally introduced in r27099). 2014-08-20 14:45:56 +00:00
Sol
40cf4b2228 - Adarkar Valkyrie delayed trigger should only trigger once 2014-08-20 02:47:35 +00:00
Krazy
3f35cb25c3 Temporary fix for multiple search terms being treated as one. 2014-08-19 21:24:36 +00:00
elcnesh
abed6a4024 Fix text changing costs, and fix displaying intrinsic SpellAbilities with changed text. 2014-08-19 20:03:52 +00:00
elcnesh
ce97950c8e Display changed text in abilities with strikethrough, and move the display code. 2014-08-18 15:03:59 +00:00
elcnesh
f51e767e6b Fix possible NPE in having a player select from a list. 2014-08-18 13:05:08 +00:00
elcnesh
fca084c44e Cleanup code for plural type names (like Clerics), and fix them for type changing effects. 2014-08-18 12:52:45 +00:00
elcnesh
12b0aa8e40 Fix NPE in KeywordsChange. 2014-08-17 07:32:24 +00:00
swordshine
bd80c4c706 - Update several scripts to display mana symbols in the card detail panel 2014-08-17 04:44:13 +00:00
drdev
4aa8207f49 Update CHANGES.txt 2014-08-17 01:07:56 +00:00
drdev
66ef9b874a Fix so removing auto-yields works 2014-08-17 00:56:49 +00:00
drdev
1272b501b4 Update enabled state of remove button when abilities removed 2014-08-17 00:40:08 +00:00
elcnesh
d7bea5d518 Fix some problems with text changing related to Effects and replacements. Also fixed Words of Wilding. 2014-08-16 19:30:10 +00:00
drdev
7a9d8adb2e Add AutoYields dialog 2014-08-16 19:25:00 +00:00
drdev
0c56a561e0 Support setting auto-yields in desktop game like in mobile game
Support showing stack ability menu on left click
2014-08-16 17:53:20 +00:00
drdev
84d8f003fd Fix so toggling off always yes/no works 2014-08-16 17:42:14 +00:00
drdev
6de1ca70d9 Fix font logic for search field rendering 2014-08-16 16:59:41 +00:00
Chris
05a28accc2 Cleared out the changes.txt file, now ready for new material. 2014-08-16 15:34:51 +00:00
Krazy
08ab364c4e Fix to respect inverting filters. 2014-08-16 15:18:00 +00:00
drdev
674d4486d2 Code cleanup 2014-08-16 14:27:46 +00:00
drdev
38f8511967 Fix so searching type, text, and mana cost work properly 2014-08-16 14:27:06 +00:00
rikimbo
ef16001fe8 Theme deck files now support indicating which set a card is to be drawn from using the usual "CardName|SetCode" syntax. The suffix can also be added to the BasicLandPercentage line to indicate the set that basic lands are to be drawn from. Eg. "basicLandPercentage=16|M10" 2014-08-16 14:21:56 +00:00
drdev
9c4579b2b1 Code cleanup 2014-08-16 14:16:12 +00:00
drdev
04b414b744 Code cleanup 2014-08-16 14:15:21 +00:00
drdev
c01b86bee7 Version bump to 1.5.25.001 2014-08-16 14:06:29 +00:00
elcnesh
13a4621dfa Fix reversed naming of abilities is Spectral Shift. 2014-08-16 07:56:26 +00:00
elcnesh
55efef6406 Fix changing color words in "Protection from all colors". 2014-08-16 07:53:22 +00:00
elcnesh
8be5331329 Use calculateAmount as these values may not be integers. 2014-08-16 07:51:51 +00:00
Sloth
4661a6f18e - Fixed "AILogic$ Never" in PumpAI. 2014-08-16 06:40:38 +00:00
Sloth
e28f1a1a37 - Fixed a NPE in applyAbilityTextChangeEffects. 2014-08-16 06:29:43 +00:00
Chris
2012621be7 [maven-release-plugin] prepare for next development iteration 2014-08-15 18:40:00 +00:00
Chris
48f4e4d801 [maven-release-plugin] prepare release forge-1.5.24 2014-08-15 18:39:45 +00:00
Chris
0803248e0b Preparing the changes.txt file for the next beta build and release. 2014-08-15 18:04:43 +00:00
Chris
5655b838ec Added new card names to changes.txt. 2014-08-15 18:02:02 +00:00
swordshine
b4549ebfe6 - Move "Offering" from modifiableKeywords to modifiableKeywordEndings 2014-08-15 14:31:13 +00:00
swordshine
cf80f5f48b - Prevent an NPE 2014-08-15 14:14:40 +00:00
drdev
0faf2bea5e Version bump to 1.5.24.012 2014-08-15 13:35:51 +00:00
elcnesh
7512536311 Update all devotion cards to use color name (to work with changing text). 2014-08-15 12:44:30 +00:00
elcnesh
bbcbd2e3e5 Update Chroma cards to work with color-changing effects (+some minor textual fixes). 2014-08-15 11:43:31 +00:00
elcnesh
0834873756 Many changes to make text changing effects work better. Highlights:
- Correctly identify which SpellAbilities are intrinsic;
- Prepare for fixing Chroma/Devotion;
- Fix which keywords are text-changed.
2014-08-15 11:17:20 +00:00
Sloth
d190fd6773 - Added a medium version of the Iron Man quest opponent. 2014-08-15 07:25:29 +00:00
Sloth
8a2c8020e5 - Fixed some cards that change lands to a basic land type not removing old abilities. 2014-08-15 07:13:05 +00:00
drdev
746b2453c2 Support removing auto-yields 2014-08-15 03:19:32 +00:00
drdev
017e16ba95 Allow yields to wrap and increase their height 2014-08-15 02:59:27 +00:00
drdev
846fdc0fb3 Add Auto-Yields dialog and support for temporarily disable all auto-yields 2014-08-15 02:43:58 +00:00
drdev
5f431bcfd5 Refactor duplicate logic in ListChooser and DualListBox into a single reusable control 2014-08-15 02:09:17 +00:00
swordshine
7836c18940 - Added edition file From the Vault: Annihilation 2014-08-14 14:35:34 +00:00
swordshine
1e885cecdc - Prevent an NPE when AI tried to activate Back from the Brink 2014-08-14 09:39:57 +00:00
Krazy
b7fba9d64c Fixed a compiler error. 2014-08-14 02:45:30 +00:00
Sloth
545666f7c9 - Added basic AI support for Helm of Obedience. 2014-08-13 20:55:54 +00:00
Krazy
e4c78160fb Removed more debugging code. 2014-08-13 03:49:56 +00:00
Krazy
db68cb4b3b Removed debugging code and fixed method signature. 2014-08-13 03:42:04 +00:00
Krazy
d54b421c87 Rewrote boolean expression parsing and added a NOT operator. Also updated CHANGES.txt to reflect this. 2014-08-13 03:40:51 +00:00
Krazy
5600929506 Added preferences for customizing draft availability in quests. 2014-08-13 01:22:00 +00:00
Sol
37fda65a24 - Added Unexpected Potential 2014-08-12 23:58:47 +00:00
Sol
052319577f - Small fix for Iterative Analysis
- Added Double Stroke
2014-08-12 23:19:50 +00:00
elcnesh
e27ab626fe Fix changing text of keywords added to players. To do so, refactor the player keywords code to use the same construction as cards. 2014-08-12 20:48:00 +00:00
elcnesh
8876a27af1 Fix GenericChoice to not fizzle when the choosing player can't be targeted, and isn't. 2014-08-12 20:20:40 +00:00
elcnesh
0f5697d1fa Restore accidentally removed null check in text changes. 2014-08-12 19:52:20 +00:00
elcnesh
331016cef7 Fix replacing "Green" in Omnath by another color. 2014-08-12 19:49:48 +00:00
Sol
566b1955f9 - Forgot to add AI handling for Iterative Analysis 2014-08-12 11:58:07 +00:00
Sol
224c19bf3c - Added Iterative Analysis 2014-08-12 04:10:55 +00:00
drdev
b00db0977c Support tapping art to show auto-yield menu 2014-08-12 01:55:15 +00:00
drdev
eb3f668410 Support auto-yielding to abilities on the stack 2014-08-12 01:37:03 +00:00
elcnesh
584eefbfe7 Add Swirl the Mists (plus some general text change cleanup). 2014-08-11 21:31:11 +00:00
Chris
4c20cab69c Added new card names to changes.txt. 2014-08-11 20:58:41 +00:00
elcnesh
281ea92a83 Add Balduvian Shaman. 2014-08-11 10:44:27 +00:00
elcnesh
8f2732e3e7 Fix newlines in a couple of cards, plus some minor textual changes. 2014-08-11 10:15:51 +00:00
elcnesh
df8cb00589 Add most of the cards with text-changing effects. 2014-08-11 10:09:37 +00:00
elcnesh
0d534be21e Add code allowing text-changing effects (+some cleanup). 2014-08-11 09:22:18 +00:00
Sol
2168779735 - Fixing infinite loop when the active player dies during his turn in a multiplayer game 2014-08-10 19:31:29 +00:00
drdev
1ee967a8e4 Version bump to 1.5.24.011 2014-08-10 19:10:41 +00:00
drdev
cf63114da1 Fix so pressing Back doesn't get you stuck on sideboard dialog 2014-08-10 19:05:25 +00:00
drdev
131943f4c0 Prevent yielding until end of turn message remaining after pressing Cancel 2014-08-10 06:13:26 +00:00
drdev
22cbf2f64b Update CHANGES.txt 2014-08-10 05:39:57 +00:00
drdev
342d9a07ab Update CHANGES.txt 2014-08-10 05:32:24 +00:00
drdev
ef8186ecd6 Version bump to 1.5.24.010 2014-08-10 05:32:11 +00:00
drdev
7a91e31f8a Fix so game doesn't skip over phases with stops too quickly after using End Turn 2014-08-10 05:25:42 +00:00
drdev
4250459eca Support canceling End Turn 2014-08-10 05:19:45 +00:00
drdev
e2fca5c020 After ending turn, pause briefly while things on the stack resolve 2014-08-10 04:27:05 +00:00
drdev
7d77e2007c Make end turn button meet player's expectations by skipping the attack phase and not requiring you to respond to triggers 2014-08-10 04:19:54 +00:00
drdev
3f6c4a2b75 Fix suffix for reveal dialog titles 2014-08-10 04:01:11 +00:00
drdev
23293a5983 Prevent "Waiting for opponent..." appearing while input dialog open 2014-08-10 03:53:12 +00:00
drdev
c155c7f0f5 Disable buttons and clear prompt at the beginning and end of each game
Disable buttons and show "Waiting for opponent..." in prompt if more than a quarter second passes between inputs
2014-08-10 03:45:08 +00:00
drdev
3c285382e2 Code cleanup 2014-08-09 18:51:25 +00:00
drdev
b375c244db Improve prompt for cleanup phase 2014-08-09 18:48:06 +00:00
drdev
5ab85508b0 Fix loading overlay for desktop game 2014-08-09 18:14:54 +00:00
drdev
d83220c653 Remove unneeded com.ibm.icu dependency from all projects which was preventing Android being able to build 2014-08-09 05:51:05 +00:00
drdev
34e42dd629 Add com.ibm.icu dependency for android project 2014-08-09 05:46:16 +00:00
drdev
5bf2219a93 Version bump to 1.5.24.009 2014-08-09 05:34:08 +00:00
drdev
003de06a68 Fix so layout updated when gauntlets and quests deleted 2014-08-09 05:31:09 +00:00
drdev
7d6f30eef0 Fix max prompt size for FOptionPane 2014-08-09 05:23:53 +00:00
drdev
ce95b9e8ac Support creating gauntlets from contests 2014-08-09 05:22:20 +00:00
drdev
0eb50905f8 Fix a couple other potential double tap bugs 2014-08-09 04:58:57 +00:00
drdev
a3e13484d4 Improve usability of deck chooser for multiple prompts 2014-08-09 04:57:39 +00:00
drdev
291263b63e Fix case of localized string 2014-08-09 04:22:11 +00:00
drdev
f56927fc00 Support creating custom gauntlet for mobile game 2014-08-09 04:16:27 +00:00
drdev
1aa95fbddc Use ghost text for gauntlet name field
Fix ghost text to appear at baseline
2014-08-09 03:57:51 +00:00
drdev
a169f50861 Fix issue with creating multiple new gauntlets in the same session 2014-08-09 02:49:38 +00:00
swordshine
55dc9949a7 - Fixed two cards by Zirbert 2014-08-09 02:30:46 +00:00
drdev
0275d222ec Support creating quick gauntlets for mobile game
Support AI opponents using preconstructed decks in gauntlets
2014-08-08 23:09:04 +00:00
Sloth
8ef560c93d - Fixed some more cards with the same problem as Intervene. 2014-08-08 18:09:28 +00:00
Sol
b1fcda54e1 - Intervene can only target spells that target creatures, not creature cards. 2014-08-08 16:38:44 +00:00
Sol
6bc5582480 - Fixing Dragon Mage not using the Discard Effect 2014-08-08 16:32:54 +00:00
Sol
d119d5ab1e - Removing extra parameter in Soul Manipulation that allows you to choose both modes 2014-08-08 16:22:33 +00:00
Chris
b79e2bcd29 Added new card names to changes.txt. 2014-08-08 14:51:30 +00:00
Sloth
90c318ef91 - Added a safety check for invalid blocks at the end of assignBlockers AI. 2014-08-08 07:00:47 +00:00
Sloth
c7adf7de14 - Added the hard quest opponent Iron Man 3. 2014-08-08 06:16:30 +00:00
Sloth
492a651593 - Copies of Shadowborn Apostle will no longer be sold in quest shop when selling extras. 2014-08-08 06:15:51 +00:00
drdev
815608a722 Disable buttons if no gauntlets exist 2014-08-08 04:55:39 +00:00
drdev
b52583a2e1 Refactor GauntletWinLose 2014-08-08 04:51:25 +00:00
drdev
952e3d93f0 Create Gauntlets screen 2014-08-08 04:05:18 +00:00
Krazy
b16b80c4d5 Fixed a typo.................. 2014-08-08 01:09:52 +00:00
Krazy
52c4a32511 Added better error message for missing keys in localization files. 2014-08-08 01:09:28 +00:00
Krazy
c26de845e1 Added localization classes and the start of the localization process. 2014-08-08 01:05:03 +00:00
drdev
1ca0428ae9 Remove space before "?" 2014-08-07 23:56:03 +00:00
drdev
50749c101a Fix timestamp formatting for gauntlets 2014-08-07 23:51:58 +00:00
drdev
27fecdcedf Update CHANGES.txt 2014-08-07 23:42:17 +00:00
drdev
d571daeed0 Make it so Last Activity column isn't cut off
Make it so double-clicking a gauntlet on the Load Gauntlet screen will launch it
Support renaming gauntlets
Support sorting gauntlets (and quests) case insensitive
2014-08-07 23:33:46 +00:00
drdev
04c2e30dbd Support selecting deck for gauntlet without one specified 2014-08-07 22:44:48 +00:00
drdev
8d2c402f47 Add gauntlet column to display your deck 2014-08-07 22:09:31 +00:00
drdev
61ff23623a Fix so deck saved with quick gauntlet 2014-08-07 22:01:26 +00:00
elcnesh
5c6091c290 Fix human being able to pick invalid types. 2014-08-07 18:39:38 +00:00
swordshine
a6101203c7 - Added Pygmy Hippo 2014-08-07 13:33:36 +00:00
swordshine
d1c0340bfc - Added Drain Power 2014-08-07 12:21:16 +00:00
Sol
a0c8ba0d2c - Sentinel Dispatch shouldn't trigger from the Sideboard 2014-08-07 04:04:23 +00:00
drdev
818424cdd3 Start working on support for ability effects 2014-08-07 02:53:35 +00:00
Sol
fd799d679d - Add Conspiracy section to the constructed deck editor for convenience (really needs to be added to the draft deck editor) 2014-08-07 02:45:21 +00:00
Agetian
9b35413ded - Fixed the token image name for Kathari Bomber. 2014-08-06 16:51:27 +00:00
drdev
0b396c4b3a Version bump to 1.5.24.008 2014-08-06 15:08:39 +00:00
drdev
be2bd295bd Swap commander and sideboard tabs 2014-08-06 15:05:44 +00:00
drdev
a23e6ae000 Account for commander as part of main deck size 2014-08-06 15:03:22 +00:00
drdev
f330f8d513 Fix so commander saved with deck 2014-08-06 14:55:37 +00:00
drdev
abc26805e1 Prevent crash if group refreshed while collapsed then later expanded 2014-08-06 14:27:46 +00:00
Sloth
2d12c8faac - Fixed AI not using the first ability of Vraska the Unseen. 2014-08-06 09:18:47 +00:00
swordshine
1a25c88287 - Fixed Grisly Spectacle 2014-08-06 06:24:17 +00:00
swordshine
cc90fc61c6 - Added North Star 2014-08-06 05:59:40 +00:00
drdev
b0d2244633 Fix so 1 round Gauntlet assigns random opponent 2014-08-06 05:47:17 +00:00
drdev
b9d9721551 Avoid message box on LimitedWinLose for mobile game 2014-08-06 05:30:48 +00:00
drdev
d66629a842 Refactor LimitedWinLose 2014-08-06 05:27:29 +00:00
drdev
314c46bae5 Whitespace cleanup 2014-08-06 04:47:44 +00:00
Sol
10ed5c3db1 - Adding +2 Mana for Flash Keyword to be displayed in the card detail panel (for cards like Rout) 2014-08-06 03:47:03 +00:00
swordshine
6d005f6b7d - Fixed Scholar of Athreos 2014-08-06 02:03:00 +00:00
drdev
5953e88e58 Select main deck page by default if sideboard empty 2014-08-05 23:57:01 +00:00
drdev
074dedc25c Code cleanup 2014-08-05 23:52:33 +00:00
drdev
b63e916076 Add support for facing 1-7 opponents for draft 2014-08-05 23:41:37 +00:00
drdev
55b105c404 Version bump to 1.5.24.007 2014-08-05 22:45:46 +00:00
drdev
0d4bdcec2b Fix so quest deck editor can work properly after first opening other editor or switching quests 2014-08-05 22:43:08 +00:00
drdev
73a9c7e889 Fix so adding and removing cards from deck works properly in quest deck editor 2014-08-05 22:20:23 +00:00
drdev
305c1ee444 Add cases for Conspiracy 2014-08-05 21:43:21 +00:00
drdev
9726610210 Prevent showing bug reporter for concurrent modification exceptions during render 2014-08-05 21:24:27 +00:00
drdev
63fe167c42 Trim text in field aftering editing 2014-08-05 21:08:01 +00:00
Sloth
772cade20b - The AI will now take the trigger of Godsend into account. 2014-08-05 19:46:50 +00:00
elcnesh
a5c255e72a Fix AnimateAi: the source card of the AnimateEffect need not be the animated card.
Fixes Genju of the Fields.
2014-08-05 08:48:21 +00:00
swordshine
81718d866e - Update LifeExchangeEffect 2014-08-05 06:05:25 +00:00
drdev
5f9bc99734 Version bump to 1.5.25.006 2014-08-05 03:15:12 +00:00
drdev
ffea98c57f Fix so quest avatars work properly after traveling 2014-08-05 03:08:50 +00:00
drdev
037a38e99b Fix size of challenge items 2014-08-05 02:52:42 +00:00
drdev
4d3796d8a7 Optimize image loading a bit 2014-08-05 02:32:03 +00:00
Sol
869620f37c - FIx issue where Aggregates.random(list, count) doesn't actually return "count" values in the resulting list 2014-08-05 02:19:11 +00:00
drdev
970e1fe115 Fix so more than one quest avatar can be loaded 2014-08-05 01:56:05 +00:00
swordshine
e8d92ce5b1 - Fixed CopyPermanentEffect 2014-08-05 01:53:55 +00:00
drdev
974caed9b5 Fix so pets show up on mobile game 2014-08-05 01:50:37 +00:00
drdev
15c3f3a409 Sort quest booster reward by name then color then rarity 2014-08-05 01:40:52 +00:00
drdev
ef6091a463 Refactor QuestWinLose overlay so most of its code is shared between desktop and mobile 2014-08-05 01:28:31 +00:00
drdev
030795ff93 Version bump to 1.5.24.005 2014-08-04 22:48:27 +00:00
drdev
e1db9f30b8 Prevent locking up draft screen by tapping at top part of cards 2014-08-04 22:47:14 +00:00
drdev
cc547c4e01 Fix crash when removing cards from deck without first switching to Catalog tab 2014-08-04 21:49:39 +00:00
drdev
1618079d7b Fix so life label has proper starting life total 2014-08-04 21:36:50 +00:00
drdev
39e6ffc95f Code cleanup 2014-08-04 21:30:27 +00:00
Sloth
9ede4f6b3c - Cleanup. 2014-08-04 21:04:45 +00:00
Sloth
1ec07dcae7 - Prevent a possible NPE. 2014-08-04 20:41:08 +00:00
Sloth
4571aecf48 - Fixed a bug of Precursor Golem and friends. 2014-08-04 20:32:09 +00:00
Chris
96408ce956 Added new card names to changes.txt. 2014-08-04 16:10:38 +00:00
Chris
bebbfd1735 Cleared out the changes.txt file, now ready for new material. 2014-08-04 16:04:32 +00:00
Sloth
927fe41087 - Updated 2 more quest decks with M15 cards. 2014-08-04 08:24:01 +00:00
drdev
d62daa5b47 Flesh out saving and loading game state some more 2014-08-04 03:00:32 +00:00
drdev
4f6d22e182 Start working on serialization support for game state 2014-08-03 23:47:34 +00:00
drdev
28880dc230 More code cleanup 2014-08-03 18:12:13 +00:00
drdev
dc148d833a Code cleanup 2014-08-03 18:09:52 +00:00
drdev
a7f9837601 Refactor random and color deck generators 2014-08-03 16:07:24 +00:00
drdev
846fd1aa34 Fix so random decks works properly for constructed game 2014-08-03 15:21:36 +00:00
swordshine
4419a85ea2 - Added Cultural Exchange 2014-08-03 13:24:59 +00:00
swordshine
dcc61c6d1c - Added Panglacial Wurm 2014-08-03 08:29:22 +00:00
swordshine
c7c75e576b - Added Sentinel Dispatch 2014-08-03 07:28:01 +00:00
Sloth
e0507cfd63 - Updated some more quest opponents with M15 cards. 2014-08-02 19:53:22 +00:00
Sloth
1dc6fbe2f4 - Fixed Genesis Hydra. 2014-08-02 18:30:21 +00:00
Sloth
a9d7c890b2 - Updated some of the Sliver quest decks with new SLiver cards. 2014-08-02 15:52:24 +00:00
drdev
18a0eea74e Version bump to 1.5.24.004 2014-08-02 15:29:50 +00:00
drdev
0b414a22c9 Support delay loading images 2014-08-02 15:18:25 +00:00
drdev
146a73185d Version bump to 1.5.24.003 2014-08-02 00:59:46 +00:00
drdev
9e121ca6c4 Prevent concurrent modification issue from applying multiple filters quickly 2014-08-02 00:49:51 +00:00
drdev
731bab9c93 Optimize handling of unique cards only 2014-08-02 00:20:36 +00:00
drdev
01ca3ae055 Version bump to 1.5.24.002
Fix so zooming for compact mode works properly
2014-08-01 18:58:26 +00:00
drdev
d055da796d Let preferred art be respected again for unique cards only list 2014-08-01 17:38:11 +00:00
drdev
6534fcb575 Support toggling want unique on the fly for Catalog 2014-08-01 16:40:49 +00:00
drdev
91ac72b55e Support remembering change to compact mode on list views 2014-08-01 16:17:19 +00:00
drdev
c1cf87e339 Version bump to 1.5.24.001 2014-08-01 16:00:50 +00:00
drdev
e7dee60016 Hide menu on zoom 2014-08-01 15:53:58 +00:00
drdev
988800940b Add support for zooming to adjust compact mode on the fly 2014-08-01 15:51:28 +00:00
Chris
061baa5664 [maven-release-plugin] prepare for next development iteration 2014-08-01 14:47:37 +00:00
Chris
b2138b9a03 [maven-release-plugin] prepare release forge-1.5.23 2014-08-01 14:47:22 +00:00
drdev
2985ab9f6b Reduce size of compact items 2014-08-01 14:25:44 +00:00
Chris
d3247c0b06 Preparing the changes.txt file for the next beta build and release. 2014-08-01 14:10:38 +00:00
Sol
08ba8a436a - Fix AB text of Veiling Oddity 2014-08-01 02:35:11 +00:00
drdev
7c03c6382f Add compact list items setting 2014-08-01 02:19:32 +00:00
drdev
a58ca9e9b0 Remove Zoom/Details item that's not really needed 2014-08-01 01:52:43 +00:00
drdev
1153e46219 Hide menu when list scrolled 2014-08-01 01:44:42 +00:00
drdev
84b6c55e5d Version bump to 1.5.23.010 2014-07-31 21:30:07 +00:00
drdev
ce7a5d9fcd Prevent showing add to favorites and change preferred art except on Constructed editor 2014-07-31 21:28:03 +00:00
drdev
849a56bfd5 Version bump to 1.5.23.009 2014-07-31 19:46:08 +00:00
drdev
15ea03bf7c Prevent altering default for desktop game 2014-07-31 19:41:27 +00:00
drdev
6c8c9423b0 Improve filtering responsiveness 2014-07-31 19:37:27 +00:00
drdev
e39130c5ee Delay loading catalog until shown for decks 2014-07-31 19:31:11 +00:00
drdev
caeafad343 Support respecting saved card preferred art on future sessions 2014-07-31 19:16:35 +00:00
drdev
2d55e64c23 Code cleanup 2014-07-31 18:05:08 +00:00
drdev
d7664e6cfc Support changing preferred art for cards in catalog
Support adding and removing catalog cards from favorites
Only show unique cards in Catalog by default
2014-07-31 17:55:11 +00:00
drdev
3502714bfd Show unique cards only by default for mobile game 2014-07-31 16:43:04 +00:00
elcnesh
12391340f9 Fix Angelic Arbiter for multiplayer. (+remove some unused methods) 2014-07-30 12:38:37 +00:00
elcnesh
e682111d35 Fix to allow creatures to attack at all (oops). 2014-07-30 11:58:52 +00:00
elcnesh
49df281a2f In multiplayer games, let the coin toss winner decide who starts the game, rather than have him choose between himself and the first opponent. (Nothing changes in 1-vs-1 games.) 2014-07-30 11:20:58 +00:00
elcnesh
2b3ede060b Remove some more references to getOpponent, refactor some cards to support the changes. 2014-07-30 10:50:47 +00:00
elcnesh
fb03ed6654 Fix effects that have a player attack a certain GameEntity (like Gideon Jura, Taunt). 2014-07-30 09:51:24 +00:00
elcnesh
db07b734a1 Fix cost reducers (like Heartstone and Training Grounds). 2014-07-30 09:27:20 +00:00
elcnesh
8690f70b2f Fix Grudge Keeper. 2014-07-30 06:58:51 +00:00
elcnesh
ceb3de4bca Fix a Card property and remove some unused card-related code. 2014-07-30 06:49:44 +00:00
drdev
600ea97726 Version bump to 1.5.23.008 2014-07-30 02:58:38 +00:00
drdev
89c8f9369b Support copy/paste on Android 2014-07-30 02:56:49 +00:00
drdev
df9f02e66a Add try/catch to FContainer::draw() so screen doesn't bug out when something throws an exception during rendering 2014-07-30 02:39:24 +00:00
drdev
a002898db5 Improve BugReportDialog by making it a screen 2014-07-30 02:15:26 +00:00
Sol
15395a6421 - Adding a small blurb into the Changelog about Conspiracy types 2014-07-30 00:47:52 +00:00
elcnesh
ecc4620dda - Fix Crawlspace in multiplayer
- Move a method using getOpponent() to AI (only place it's used, to group the methods using this deprecated function in the AI code)
2014-07-29 22:22:14 +00:00
drdev
ed496dbc10 Version bump to 1.5.23.007 2014-07-29 13:18:17 +00:00
drdev
15d8b6930b Fix a couple pet typos 2014-07-29 13:16:04 +00:00
drdev
7a3d775c27 Fix crash when certain types of tokens are rendered using card image generator 2014-07-29 13:08:11 +00:00
drdev
51b1e5ee07 Fix so phyrexian mana symbols display properly in generated card images 2014-07-29 12:56:44 +00:00
drdev
5f5447d3e1 Add oracle text for all quest pets so they work with the card generator 2014-07-29 12:31:40 +00:00
swordshine
3526e80b0e - Prevent a potential NPE 2014-07-29 00:49:11 +00:00
elcnesh
ae98af475c Fix some more getOpponent calls. 2014-07-28 20:17:33 +00:00
elcnesh
b59f77e2ac Fix some more references to getOpponent(). 2014-07-28 15:28:50 +00:00
elcnesh
858c26745f Fix Grizzled Wolverine with reworded oracle text. 2014-07-28 15:25:09 +00:00
elcnesh
6bdb6cbd4d Fix some card file line endings. 2014-07-28 14:54:55 +00:00
elcnesh
05cb449cb9 Remove some references to Player.getOpponent (fixing cards for multiplayer games). 2014-07-28 14:35:57 +00:00
elcnesh
643e58e954 A permanent leaving the battlefield causes "lose control" triggers to trigger. 2014-07-28 13:52:52 +00:00
elcnesh
c52fc8c612 Add Ogre Enforcer. 2014-07-28 13:26:02 +00:00
elcnesh
301cfb0540 Add Giant Albatross. 2014-07-28 11:13:16 +00:00
elcnesh
2b49613d39 Fix card image of Burning-Eye Zubera. 2014-07-28 10:48:47 +00:00
elcnesh
b89326f058 Add Burning-Eye Zubera and Rushing-Tide Zubera. 2014-07-28 10:29:18 +00:00
swordshine
13ada02ae1 - Improve the commander pool to support other non-legendary creature commanders 2014-07-28 10:00:40 +00:00
swordshine
5bae2421be - Fixed Cataclysm 2014-07-28 08:22:54 +00:00
drdev
4286abb1c9 Version bump to 1.5.23.006 2014-07-28 06:38:25 +00:00
drdev
685a14020c Show foil overlay in card zoom 2014-07-28 06:30:21 +00:00
drdev
3af3eaad09 Make zoom from scratch and details be same size 2014-07-28 06:26:39 +00:00
drdev
91e44c5cc5 Remove extra code from home screen 2014-07-28 06:20:55 +00:00
drdev
8a63374ab7 Make fallback card image rendering more dynamic 2014-07-28 06:19:12 +00:00
drdev
a63e8419f2 Improve rendering of basic lands 2014-07-28 02:09:45 +00:00
drdev
425ebeadeb Remove extra vertical padding 2014-07-28 01:49:08 +00:00
drdev
59bb321593 Remove change from FOptionPane 2014-07-28 01:29:05 +00:00
drdev
e2b09f7f20 Increase border thickness of card 2014-07-28 01:21:19 +00:00
drdev
5fcee5c3b0 Remove changes to home screen code 2014-07-28 00:53:39 +00:00
drdev
e74ad85a8c Improve p/t box layout 2014-07-28 00:49:08 +00:00
drdev
13e94a2109 Increase P/T box padding 2014-07-28 00:36:19 +00:00
drdev
419a4095d9 Improve card rendering 2014-07-28 00:32:47 +00:00
Chris
b6b62ad282 Added new card names to changes.txt. 2014-07-28 00:24:45 +00:00
drdev
c03bbca0fc Improve handling of rendering card image from scratch 2014-07-27 22:15:14 +00:00
drdev
390b5eb315 Support rendering card image from scratch if image not found 2014-07-27 20:03:47 +00:00
swordshine
6cac3199de - Commander 2014: Added Teferi, Temporal Archmage 2014-07-27 11:56:42 +00:00
swordshine
a3acbce645 - Commander 2014: Added Ghoulcaller Gisa 2014-07-27 11:11:31 +00:00
elcnesh
1e93f310aa Remove now unused references to Licid state. 2014-07-27 09:33:22 +00:00
elcnesh
e6a8f5d60d Fix the Licids to use normal AnimateEffect rather than states. Works much better with copy effects and other parts of the game. 2014-07-27 08:55:15 +00:00
swordshine
a864e0e856 - KTK: Added Zurgo Helmsmasher 2014-07-27 08:28:20 +00:00
swordshine
49deb45bea - Fixed “CARDNAME attacks each turn if able.” 2014-07-27 08:10:50 +00:00
drdev
e24d8da134 Version bump to 1.5.23.005 2014-07-27 00:50:34 +00:00
drdev
ae2a3f524a Add quest preferences screen 2014-07-27 00:47:35 +00:00
drdev
1d9e73b0f2 Implement quest preferences screen 2014-07-27 00:06:30 +00:00
drdev
a9c8922395 Version bump to 1.5.23.004 2014-07-26 17:10:30 +00:00
drdev
a4279022af Fix so win game actually fires correctly for desktop game 2014-07-26 17:03:44 +00:00
drdev
408299ce3c Add Dev mode option to automatically win the current game 2014-07-26 17:02:17 +00:00
drdev
bbac882f76 Prevent crash if you win on turn zero somehow 2014-07-26 16:45:25 +00:00
drdev
e954c95899 Fix so moving to main deck works properly 2014-07-26 16:41:12 +00:00
drdev
5f4419bb88 Implement sideboard dialog for mobile game 2014-07-26 16:36:27 +00:00
drdev
135cadac67 Add PaperCard renderer for DualListBox 2014-07-26 14:54:13 +00:00
drdev
31535e552b Improve display of ante cards at the beginning of the game 2014-07-26 14:42:53 +00:00
drdev
fb547d7234 Improve question wording 2014-07-26 03:06:02 +00:00
drdev
2c72a94010 Support show card option pane 2014-07-26 03:00:06 +00:00
swordshine
04fb8a7033 - Fixed Wall of Kelp 2014-07-26 00:52:08 +00:00
drdev
843dae2072 Prevent crash when zooming cards in deck editor 2014-07-26 00:02:56 +00:00
drdev
93f847ceac Fix so cards that have players play with their hand reveal work properly 2014-07-25 23:52:41 +00:00
drdev
cce5ac665a Fix so stats on face down cards appear properly 2014-07-25 23:24:26 +00:00
drdev
76adfe39b4 Fix so sort combo box hidden appropriately when view options hidden 2014-07-25 23:16:40 +00:00
drdev
afd1c20782 Shorten Decks sort option 2014-07-25 23:14:00 +00:00
drdev
cc30562986 Prevent sort options being duplicated 2014-07-25 23:11:20 +00:00
drdev
fb7a14177f Version bump to 1.5.23.003 2014-07-25 06:38:11 +00:00
drdev
1012ffde79 Sort power and toughness descending by default 2014-07-25 06:30:22 +00:00
drdev
05114eebe1 Support double tap to confirm set selection 2014-07-25 06:27:42 +00:00
drdev
0ec13f0294 Make rarity sort descending by default 2014-07-25 06:12:56 +00:00
drdev
2d9c4f36bf Support specifying sort for mobile game 2014-07-25 06:11:12 +00:00
drdev
0d46e58dbc Prevent being able to scroll options panel 2014-07-25 05:23:37 +00:00
drdev
e0806e5d14 Fix so value range filter works properly 2014-07-25 05:16:52 +00:00
drdev
eadc1134d6 Improve FSpinner editing 2014-07-25 05:06:05 +00:00
drdev
154b50cebd Make single set selection show only that set
Show multiple set selection in chron order in combo box
2014-07-25 04:32:59 +00:00
drdev
13d766f706 Allow restoring previous formats/sets after opening choose sets screen 2014-07-25 04:21:35 +00:00
drdev
d1713b2e94 Fix scrolling issue with list view 2014-07-25 04:12:40 +00:00
drdev
c4b4037577 Fully implement card and deck set/format filter 2014-07-25 04:11:06 +00:00
drdev
88f82d23ae Fix so third filter shows up 2014-07-24 23:35:00 +00:00
drdev
1855a72c40 Fix padding between filters 2014-07-24 23:28:46 +00:00
Krazy
977532b032 Fixed typo. 2014-07-24 23:28:09 +00:00
drdev
879b9a59d5 Clean up filters logic 2014-07-24 23:17:34 +00:00
drdev
85f22db6df Support applying format filter 2014-07-24 23:10:38 +00:00
drdev
f154dbf267 Fix crash when loading deck chooser if RANDOM_DECK configured in forge.preferences 2014-07-24 22:48:08 +00:00
drdev
5181b1b267 Support iterating formats in order 2014-07-24 02:46:25 +00:00
drdev
3919b39201 Start working on new format filters 2014-07-24 02:24:45 +00:00
Krazy
b2d806c692 Tokens are now stacked side by side when they have differing intrinsic keywords (Wurmcoil Engine tokens, etc will now end up in two piles—one for deathtouch and one for lifelink). 2014-07-23 21:41:21 +00:00
swordshine
0cd207530d - Fixed Vitu-Ghazi, the City-Tree by Marek14 2014-07-23 04:01:30 +00:00
swordshine
41c39bda0d - Fixed Rogue's Gloves by Zirbert 2014-07-23 03:57:50 +00:00
drdev
d85122d6fa Tweak filter layout logic 2014-07-23 02:07:24 +00:00
Chris
01b9a25169 Added new card names to changes.txt. 2014-07-22 18:53:24 +00:00
Chris
0ba35f08a9 Cleared out the changes.txt file, now ready for new material. 2014-07-22 18:52:31 +00:00
drdev
5a542391a5 Reduce width of filter buttons 2014-07-22 05:01:08 +00:00
drdev
d65c83bee4 Simplify filters for ItemManager 2014-07-22 04:40:21 +00:00
drdev
2997e38fd7 Version bump to 1.5.23.002 2014-07-22 03:14:23 +00:00
drdev
08f2e48262 Fix crash after completing quest game for ante 2014-07-22 03:11:53 +00:00
swordshine
5dba3a8fdc - Fixed Ajani Steadfast 2014-07-22 00:29:50 +00:00
swordshine
4bd83f4ec9 - Fixed remaining auras with "This effect doesn't remove CARDNAME". 2014-07-21 10:12:35 +00:00
swordshine
e6f4de26dc - Fixed Pledge of Loyalty 2014-07-21 09:59:39 +00:00
swordshine
47ba659072 - Fixed Tattoo Ward 2014-07-21 09:49:20 +00:00
swordshine
782f7197ea - Fixed other four wards 2014-07-21 09:42:22 +00:00
swordshine
49a5ae3e77 - Fixed White Ward 2014-07-21 09:25:50 +00:00
Agetian
28364f97ec - A better fix for Scry 1. 2014-07-21 07:19:16 +00:00
Agetian
83e914b00c - Scry 1 will now correctly show the card it's inquiring about to the player (in the card detail/picture boxes). 2014-07-21 07:14:48 +00:00
swordshine
7131a97324 - "This effect doesn't remove Auras" (Spectra Ward) is now checked in state-based actions. 2014-07-21 06:00:32 +00:00
drdev
b6523d227e Version bump to 1.5.23.001 2014-07-21 05:14:19 +00:00
drdev
7e4057b492 Prevent graveyard opening after resolving a removal spell with another spell targeting that creature below it that will now be countered 2014-07-21 04:49:56 +00:00
drdev
21d223908a Fix so zone containing stack item targets is temporarily revealed 2014-07-21 04:18:00 +00:00
drdev
9930732c8f Ensure stack height increases if needed when activating items below top 2014-07-21 04:00:19 +00:00
drdev
a7f7366771 Only show targeting arrows for active stack instance 2014-07-21 03:54:05 +00:00
drdev
8fc35fc858 Support bringing non-active items to front 2014-07-21 03:49:33 +00:00
drdev
a471d88ade Fix so zones restored after selecting targets 2014-07-21 03:06:49 +00:00
Sol
c42f6fea9d - !PrintSheets can now be referenced inside Booster contents of an edition file
- M15 Boosters no longer contain cards only found in Intro decks
- Adding a few Conspiracy type cards, along with the capability of their use (NOTE: Deck editors still need a way to add Conspiracy types)
- Added Brago's Favor, Immediate Action, Muzzio's Preparations, Secret Summoning, Secrets of Paradise
2014-07-21 02:56:13 +00:00
drdev
007ebc3e9c Fix so proper zones revealed when activating targeted ability 2014-07-21 02:11:19 +00:00
drdev
2d0c0a05f7 Improve handling of targeting arrows for cards that leave the battlefield or are in a non-visible zone 2014-07-20 22:47:12 +00:00
drdev
558d24c431 Improve stack display so it feels more like a stack 2014-07-20 22:23:30 +00:00
Sloth
78927eb7c4 - Added the 5 M15 precons (Thanks to Fizanko). 2014-07-19 20:32:27 +00:00
Sloth
af879a1521 - Fixed Feast on the Fallen. 2014-07-19 19:33:08 +00:00
Sloth
79fe00ed1c - Fixed Hornet Nest. 2014-07-19 19:07:23 +00:00
Chris
7d8e3366ce [maven-release-plugin] prepare for next development iteration 2014-07-19 00:22:30 +00:00
Chris
4fd581fb5c [maven-release-plugin] prepare release forge-1.5.22 2014-07-19 00:22:17 +00:00
Chris
b9978689f4 Preparing the changes.txt file for the next beta build and release. 2014-07-18 22:57:10 +00:00
drdev
4538ea5ff1 Version bump to 1.5.22.011 2014-07-18 17:08:07 +00:00
drdev
ac0b532ea1 Fix XML serialization issue with quest items 2014-07-18 17:06:14 +00:00
drdev
68c0d231b4 Revert stat filter buttons to old behavior 2014-07-18 17:03:05 +00:00
drdev
fcc3818a00 Fix formatting for Champion keyword 2014-07-18 08:16:26 +00:00
drdev
d754c4efd0 Fix so "Creature" isn't capitalized in abilities that start with "Sacrifice a creature:" 2014-07-18 07:59:04 +00:00
drdev
b3edcf8620 Prevent printing out "an another" in card rules text 2014-07-18 07:52:17 +00:00
drdev
461e425908 Fix typo 2014-07-18 07:34:23 +00:00
drdev
7ab134bb1a Allow loading scripts for cards containing commas 2014-07-18 07:27:01 +00:00
drdev
0d8dad2d4f Prevent crash when selecting cards without scripts 2014-07-18 07:25:03 +00:00
drdev
6841b4a727 Disable searching in cost by default 2014-07-18 07:11:33 +00:00
drdev
88bd15a7c6 Fix so workshop can actually display card scripts 2014-07-18 07:10:02 +00:00
drdev
13426d26c1 Version bump to 1.5.22.010 2014-07-18 06:23:49 +00:00
drdev
fd5332ea71 Fix so *NEW* suffix appears in quest deck editor 2014-07-18 06:16:41 +00:00
drdev
14cc111e2c Prevent *NEW* appearing in lists that don't have New column 2014-07-18 06:07:12 +00:00
drdev
5df9136ae9 Fix so new cards appear on top in inventory
Fix so *NEW* appears next to new card names in spell shop
2014-07-18 06:00:34 +00:00
drdev
1c53386659 Prevent crashing if quest pet images fail to load 2014-07-18 05:33:33 +00:00
drdev
a3bb19ba6f Prevent description label being able to scroll 2014-07-18 05:24:27 +00:00
drdev
057ecf485d Version bump to 1.5.22.009 2014-07-18 05:09:54 +00:00
drdev
89a560aac2 Make bazaar layout work better on narrower screens 2014-07-18 05:04:10 +00:00
drdev
0ee9396952 Fix compile error 2014-07-18 03:48:53 +00:00
drdev
4090c14a44 Version bump to 1.5.22.008 2014-07-18 03:42:15 +00:00
drdev
8715642632 Fix so selected stall button displays with focus in Bazaar 2014-07-18 03:39:44 +00:00
drdev
2c7e92515b Support showing mana symbols in quest item descriptions 2014-07-18 03:34:11 +00:00
drdev
81731fcd77 Support buying quest items in mobile game 2014-07-18 03:29:59 +00:00
drdev
a658f46883 Make pets show mana icons for color and make punctuation consistent 2014-07-18 03:11:54 +00:00
drdev
da6d47ebd6 Fix punctuation typos in bazaar descriptions 2014-07-18 03:06:12 +00:00
drdev
d26ef417e3 Remove excess blank lines in bazaar item descriptions 2014-07-18 02:56:07 +00:00
Krazy
ca8d77e0c6 Updated changes.txt with a little clarification. 2014-07-18 02:50:58 +00:00
drdev
32c01adb19 Add a little horizontal padding around bazaar icons 2014-07-18 02:40:02 +00:00
drdev
b16a72954d Fix laying out bazaar screens 2014-07-18 02:36:35 +00:00
Sol
99521aeef2 - Updating the M15 Rankings 2014-07-18 02:30:40 +00:00
drdev
5cfd09c389 Update CHANGES.txt 2014-07-18 01:35:34 +00:00
drdev
a6bf55f3a0 Standardize lines separating list items 2014-07-18 01:22:53 +00:00
drdev
4d15ca850e Support laying out top half of bazaar pages 2014-07-18 00:40:58 +00:00
drdev
3df392a194 Turn off scroll indicators (for now) 2014-07-18 00:11:50 +00:00
Krazy
0728a42eb7 Added searching of card mana costs. Added simple boolean search parsing to card search boxes. 2014-07-17 22:38:11 +00:00
drdev
354a802044 Flesh out some of the Bazaar screen 2014-07-17 06:09:33 +00:00
drdev
f3cf0b01ec Prevent drawing right border for final visible tab 2014-07-17 05:45:48 +00:00
drdev
c590b6dc95 Improve tab page scrolling support 2014-07-17 05:38:12 +00:00
drdev
54f210767d Add indicators for FScrollPane 2014-07-17 05:32:39 +00:00
drdev
cd4b2f55b9 Refactor how Bazaar tab pages initialized 2014-07-17 05:03:54 +00:00
drdev
b04c5365ef Support tabs for Bazaar screen 2014-07-17 05:00:58 +00:00
drdev
135617ff9d Fix compile warning 2014-07-17 04:24:12 +00:00
drdev
03ecc1fc18 Version bump to 1.5.22.007 2014-07-17 04:12:16 +00:00
drdev
ed7f3e54a0 Prevent there being a possible crash when winning a quest match 2014-07-17 04:10:43 +00:00
drdev
fd839c81ec Fix so hidden groups don't show up at all 2014-07-17 03:38:38 +00:00
drdev
c09b003f19 Prevent showing groups with no cards in them 2014-07-17 03:30:11 +00:00
drdev
0ee0f9e0f1 Fix so set groups sorted by date in reverse chronological order 2014-07-17 03:26:32 +00:00
drdev
68bcae4101 Add Set group by option 2014-07-17 02:47:47 +00:00
drdev
ce8c6cdd07 Version bump to 1.5.22.006 2014-07-17 01:11:44 +00:00
drdev
d64c294d9b Add no-args constructors for other quest classes 2014-07-17 01:10:02 +00:00
drdev
c71cafcce2 Fix so duels screen opened if setting quest after Load or New quest screen was opened directly from the home screen 2014-07-16 23:56:00 +00:00
drdev
733d8a4b5d Add no-args constructor to QuestData for XML serialization 2014-07-16 23:47:07 +00:00
drdev
eed9fe0b4d Version bump to 1.5.22.005 2014-07-16 23:41:28 +00:00
drdev
f29efc9273 Prevent Random Deck button going back from Quest Decks screen 2014-07-16 23:39:59 +00:00
drdev
25fd7aced5 Prevent crash when starting your first quest 2014-07-16 23:38:07 +00:00
drdev
4fe5576317 Prevent New Deck not refreshing display right away from Quest Decks screen 2014-07-16 23:28:07 +00:00
drdev
b7ea7675a4 Fix issue that preventing starting quest mode if there was a flaw in the price list 2014-07-16 23:23:18 +00:00
excessum
0bd3aa87da - Fixed ability for Invasive Species 2014-07-16 13:33:41 +00:00
drdev
1f46f60f75 Version bump to 1.5.22.004 2014-07-16 05:09:41 +00:00
drdev
cb371350e0 Comment out screens to hide from quest menu for now 2014-07-16 05:07:48 +00:00
drdev
9755c94084 Update message titles 2014-07-16 05:06:08 +00:00
drdev
465ddbc2b5 Change WinLost screens to use dialogs to display rewards since there's no room to display on overlay 2014-07-16 04:44:26 +00:00
drdev
cd5f5fb617 Make it so when launching quest mode for the first time, it jumps to the New Quest screen 2014-07-16 03:48:33 +00:00
drdev
8a681df8e6 Prevent crash when winning quest match 2014-07-16 03:32:46 +00:00
drdev
b89672a45f Create QuestWinLose 2014-07-16 01:46:25 +00:00
Chris
8877225485 Added new card names to changes.txt. 2014-07-15 23:52:51 +00:00
Krazy
5007aa74d6 Final tweaks to quest loading screen. 2014-07-15 21:03:24 +00:00
Krazy
6cc4f4b7d7 Small tweaks to quest loading screen. 2014-07-15 20:30:37 +00:00
Krazy
0f35e49703 Redesigned the quest loading screen for the desktop version of Forge to match the new Android screen (displays more quest info). 2014-07-15 18:36:06 +00:00
elcnesh
515d6ef8c9 Fix Firestorm. 2014-07-15 11:32:24 +00:00
drdev
877461681e Finish spell shop screen 2014-07-15 06:43:14 +00:00
drdev
4a16b05ddf Improve rendering for packs in list view 2014-07-15 06:00:29 +00:00
drdev
def995aa95 Improve captions inline with desktop game 2014-07-15 05:46:20 +00:00
drdev
ec4cab89ca Support buying and selling from mobile spell shop 2014-07-15 05:42:15 +00:00
drdev
01883fb78f Actually support long press for item managers 2014-07-15 04:57:40 +00:00
drdev
9e74986e19 Support showing price for spell shop managers
Support long pressing item manager list items
2014-07-15 04:54:10 +00:00
drdev
cb868b2182 Prevent crash when opening quest mode 2014-07-15 04:18:55 +00:00
drdev
6afe46792c Refactor some spell shop logic to make it more reusable from mobile game 2014-07-15 04:13:46 +00:00
drdev
34dfbf1098 Fix so stack shows up correctly from triggered abilities 2014-07-14 13:23:17 +00:00
drdev
17d750d0cc Implement pet and zeppelin support 2014-07-14 12:45:09 +00:00
drdev
d0864ef8eb Implement quest challenges screen
Move items to stats screen
2014-07-14 12:13:08 +00:00
elcnesh
e2d624f398 Fix P/T determination when only base power or base toughness is set for a creature. 2014-07-14 10:02:18 +00:00
elcnesh
3351bb0947 Fix ability descriptions of Vhati il-Dal. 2014-07-14 09:52:35 +00:00
elcnesh
715876b297 Update oracle text of Sensation Gorger and fix Vhati-il-Dal. 2014-07-14 09:41:37 +00:00
elcnesh
712ddfae58 Update M15 Oracle changes, plus some P/T & type fixes to M15 cards ('n'-'z'). 2014-07-14 09:25:48 +00:00
elcnesh
72839e4e90 Update M15 Oracle changes, plus some cost & type fixes to M15 cards. 2014-07-14 09:05:36 +00:00
elcnesh
6cd71ffdd0 Fix line endings for M15 cards (+Dead Ringers), and move Rotfeaster Maggot. 2014-07-14 08:25:09 +00:00
swordshine
701aff8c6d - M15: Added Diffusion Sliver 2014-07-14 04:59:33 +00:00
swordshine
60f3204f0e - Updated the script of Reconnaissance (Looks like Wizards reverted the change this time) 2014-07-14 04:18:37 +00:00
Sol
605c71f03b - Goblin Rabblemaster doesn't grant PT bonus 2014-07-13 17:40:51 +00:00
swordshine
c4180c4798 - Update oracle texts for M15 cards 2014-07-13 14:28:59 +00:00
swordshine
9161856a4e - Update mtg-data 2014-07-13 14:22:04 +00:00
swordshine
cc44380941 - M15: Added Avacyn, Guardian Angel 2014-07-13 11:25:57 +00:00
drdev
a7d03546cb Prevent being unable to start a quest match after failing once 2014-07-13 02:52:02 +00:00
drdev
f13cec787b Improve logic for which quest screen gets opened 2014-07-13 02:37:06 +00:00
drdev
c80483bf1e Make loading quest work better 2014-07-13 02:08:02 +00:00
drdev
36a1e8148f Fix so quest screens updated when screen changes 2014-07-13 02:00:08 +00:00
excessum
b072d41fa4 - Fixed ability cost for Yisan, the Wanderer Bard 2014-07-13 01:22:39 +00:00
drdev
68a34e3ac4 Display more consistent name for quest decks screen title 2014-07-13 00:03:33 +00:00
drdev
787a4214d7 Add view deck and random deck buttons to Quest Decks screen 2014-07-12 21:59:59 +00:00
drdev
cc2464cdbc Fix so inventory updated when cards added/removed from deck 2014-07-12 21:28:47 +00:00
drdev
0190ccbedf Support editing quest decks 2014-07-12 21:10:39 +00:00
drdev
4d169dd4b9 Support showing mobile Forge version in BugReporter 2014-07-12 20:24:16 +00:00
Krazy
a50fb330a2 Cleaned up more quest draft logic. 2014-07-12 19:49:34 +00:00
Krazy
cbcd527dd5 Removed the quest draft logic from the UI controller to make porting to other platforms much easier. 2014-07-12 19:41:18 +00:00
drdev
d12c606b2e Support double tapping to start match 2014-07-12 17:48:39 +00:00
drdev
8029857ec3 Version bump to 1.5.22.003 2014-07-12 17:01:15 +00:00
drdev
1be0041eeb Fix whitespace issue 2014-07-12 16:57:38 +00:00
drdev
7a59eda43c Fix so average finger size doesn't exceed a certain amount relative to the overall screen size 2014-07-12 16:56:44 +00:00
drdev
4fe035089e Fix Start button size based on screen resolution 2014-07-12 16:25:58 +00:00
drdev
b56dd1a872 Set things up to make testing other screen sizes and resolutions easier 2014-07-12 15:53:49 +00:00
swordshine
26d3dfac75 - Fixed Siege Dragon 2014-07-12 14:35:04 +00:00
swordshine
5e748db716 - Reverted r26631 2014-07-12 08:44:15 +00:00
Sloth
f8f7be5617 - Fixed AI attaching Mask of Memory to creatures with 0 power. 2014-07-12 08:14:29 +00:00
elcnesh
e6992f2d50 Fix Greater Werewolf. 2014-07-12 07:36:27 +00:00
swordshine
0b8676072d - Added Spectra Ward 2014-07-12 06:03:47 +00:00
drdev
01975f5ab2 Support long press zoom for ListChooser and DualListBox 2014-07-12 05:36:28 +00:00
drdev
502fd6d049 Support long press zoom for stack 2014-07-12 05:28:18 +00:00
drdev
0f299fcc09 Support respecting avatar specified by quest event 2014-07-12 05:24:52 +00:00
drdev
a3fea9df01 Support starting quest duels 2014-07-12 04:44:28 +00:00
drdev
0ac7971d7d Support traveling 2014-07-12 04:03:43 +00:00
drdev
ee60b03ade Fix bugs with changing quests 2014-07-12 03:48:27 +00:00
drdev
73b206e7fe Flesh out duels screen 2014-07-12 03:27:14 +00:00
drdev
b7cf7f278a Support working on layout of duels screen 2014-07-12 00:26:28 +00:00
drdev
02a530ca39 Add version to splash screen
Update version to 1.5.22.002
2014-07-11 23:37:53 +00:00
drdev
a63e88c0f9 Add support for highlighting selected menu item 2014-07-11 23:18:56 +00:00
elcnesh
76c043fa06 Fix some more block-triggers. 2014-07-11 23:16:04 +00:00
Sol
bae6dae742 - Fix typo in spell description 2014-07-11 20:30:28 +00:00
elcnesh
69885ba1af Fix No Quarter. 2014-07-11 19:15:54 +00:00
elcnesh
57f972a754 Fix '[blocks or] becomes blocked by a creature' triggers to trigger once for each blocker ('m'-'z'). 2014-07-11 19:08:39 +00:00
Chris
ee3e5926da Added new card names to changes.txt. 2014-07-11 17:58:51 +00:00
swordshine
c5c4bf30ad - Update block data 2014-07-11 14:31:53 +00:00
swordshine
eefd76ba94 - Added Constricting Sliver 2014-07-11 14:28:17 +00:00
Sloth
bcb89d1a4b - Added M15 cards to trunk. 2014-07-11 14:17:57 +00:00
elcnesh
10a230f063 Fix '[blocks or] becomes blocked by a creature' triggers to trigger once for each blocker ('f'-'l'). 2014-07-11 12:32:38 +00:00
elcnesh
6286e57068 Fix '[blocks or] becomes blocked by a creature' triggers to trigger once for each blocker ('a'-'e'). 2014-07-11 11:03:56 +00:00
elcnesh
bf0cc2e926 Fix: when ending the turn, remove all additional phases/steps scheduled for this turn. 2014-07-11 10:48:54 +00:00
elcnesh
848a9f86f9 Fix Heroes' Podium counting opponent's creatures. 2014-07-11 08:06:26 +00:00
elcnesh
59f394bbc0 Fix Possibility Storm when the triggered card is countered. 2014-07-09 15:34:55 +00:00
elcnesh
b014a28051 Fix Wild Evocation lands counting as land drops for the turn. 2014-07-09 15:18:18 +00:00
Sloth
00ae5d6de8 - Improved attachAIAnimatePreference. 2014-07-09 14:48:16 +00:00
swordshine
20e8b3ae7a - M15: Added Eternal Thirst, Leeching Sliver, Rotfeaster Maggot, Shadowcloak Vampire, and Stain the Mind 2014-07-09 13:45:00 +00:00
elcnesh
98a15cb750 Fix Ogre Leadfoot. 2014-07-09 13:34:24 +00:00
elcnesh
63e6733e61 Fix copying replacement effects by copying the override ability rather than just the reference. 2014-07-09 13:03:14 +00:00
swordshine
dcaac37663 - Added extra cards to M15 edition file 2014-07-09 12:43:41 +00:00
swordshine
587e005356 - M15: Added Jalira, Master Polymorphist and Necromancer's Stockpile 2014-07-08 14:11:51 +00:00
swordshine
5711863c59 - M15: Added The Chain Veil 2014-07-08 13:23:59 +00:00
elcnesh
2ab802f413 Fix NPE when dealing with copied tokens. 2014-07-08 09:57:42 +00:00
elcnesh
3a9fed7fe6 Fix mana costs of some cards. 2014-07-08 09:04:09 +00:00
Chris
1ffe35670a Cleared out the changes.txt file, now ready for new material.
Added new card names to changes.txt.
2014-07-07 16:38:46 +00:00
elcnesh
9655fe720d Fix a number of card types (and some oracle texts and P/T values). 2014-07-07 13:43:37 +00:00
elcnesh
e5570fae04 Fix Traveling Plague.
The construction with Remember is necessary to actually retrieve the card in the graveyard, rather than the LKI of the card on the battlefield.
2014-07-07 07:07:08 +00:00
elcnesh
9411b73854 Fix Sphinx Ambassador by adding 'optional' clause. 2014-07-07 06:11:27 +00:00
drdev
a776cf31e9 Support showing current quest name in header caption 2014-07-07 04:29:20 +00:00
drdev
1eae4e423e Prevent breaking win streak label for desktop game 2014-07-07 04:20:10 +00:00
drdev
787bb94d6d Fix so quest stats updated 2014-07-07 04:16:15 +00:00
drdev
77bb8b60c1 Prevent showing menu on Load Quest screen 2014-07-07 03:40:49 +00:00
drdev
cb2a05e821 Show card count and credits in quest items 2014-07-07 03:39:22 +00:00
drdev
9036642242 Improve quest list display to include your current level 2014-07-06 23:20:36 +00:00
drdev
6a0d0d501f Tweak loading overlay messages 2014-07-06 23:01:04 +00:00
drdev
47b3adeba2 Support loading existing quests 2014-07-06 22:56:20 +00:00
drdev
af9131ebc8 Get embark to work from new quest screen 2014-07-06 20:04:52 +00:00
drdev
fb48b4245f Prevent back color flickering when multiple popups appear back to back 2014-07-06 19:50:47 +00:00
drdev
14b5b206d0 Prevent suppressing first tap away from key input component 2014-07-06 18:26:07 +00:00
drdev
b74d952610 Actually fix compile 2014-07-06 18:23:59 +00:00
drdev
920209e1c8 Fix compile 2014-07-06 18:23:31 +00:00
drdev
4d319dd24c Fix issue with popups not blocking 2014-07-06 18:23:15 +00:00
drdev
f1bdfaa819 Hook things up so new quest can be created 2014-07-06 18:21:17 +00:00
drdev
7dd6e74089 Add setting for skipping mobile mana pool prompt to mobile game and reposition it within desktop game 2014-07-06 17:57:38 +00:00
drdev
f65477e983 Slight optimization for new mana pool empty preference 2014-07-06 17:52:52 +00:00
elcnesh
674f1ba733 Fix Phage's creature types. 2014-07-06 15:03:06 +00:00
elcnesh
881420d741 Fix: have the correct player gain life from Oust. 2014-07-06 14:40:14 +00:00
elcnesh
4da4ddb5e5 Add preference to enable/disable mana pool emptying prompt. 2014-07-06 14:37:31 +00:00
elcnesh
7dc244fb46 Revert order of Eaten by Spiders and Murderous Spoils. 2014-07-06 14:01:32 +00:00
swordshine
fdcb39245a - M15: Added Blastfire Bolt, Brood Keeper, Burning Anger, Crowd's Favor, and Hammerhand 2014-07-06 11:11:41 +00:00
elcnesh
baaf7b06ad Fix Eaten by Spiders and Murderous Spoils by reversing the order.
Order doesn't match the card's written order anymore, but at least they now function as intended.
2014-07-06 10:11:54 +00:00
elcnesh
f7cb61b467 Cleanup ControlGainEffect and fix its Stack description. 2014-07-06 09:58:38 +00:00
swordshine
3eeff60811 - Added M15 edition file 2014-07-06 07:51:20 +00:00
swordshine
54ede1be67 - M15: Added Life's Legacy, Living Totem, and Netcaster Spider 2014-07-06 06:35:14 +00:00
drdev
341033bdf7 Increase size of and add icon to Embark button 2014-07-06 05:32:56 +00:00
drdev
e4e1368fb1 Flesh out New Quest screen 2014-07-06 05:25:57 +00:00
drdev
4e479d280d Shell out quest mode for mobile game 2014-07-06 03:18:18 +00:00
drdev
6ffb961183 Fix compile errors left over from last commit 2014-07-06 02:43:33 +00:00
drdev
c89cc33cd6 Refactor some quest code to make it reusable by mobile game 2014-07-06 02:37:23 +00:00
elcnesh
acc648cf08 Fix Gnarlid Pack's kicker cost and a missing SVar reference. 2014-07-05 23:50:51 +00:00
drdev
691fbf51d2 Version bump to 1.5.22.001 2014-07-04 21:33:28 +00:00
drdev
adc3ddf972 Fix scroll pane issues with drop down menus 2014-07-04 21:28:20 +00:00
Chris
12bcc312ba [maven-release-plugin] prepare for next development iteration 2014-07-04 15:39:59 +00:00
Chris
5489fc7d64 [maven-release-plugin] prepare release forge-1.5.21 2014-07-04 15:39:44 +00:00
Chris
e5dd8dd598 Preparing the changes.txt file for the next beta build and release. 2014-07-04 14:58:43 +00:00
Chris
d400f620f2 Added new card names to changes.txt. 2014-07-04 14:53:28 +00:00
swordshine
6cea243888 - M15: Added First Response and Feast on the Fallen 2014-07-04 14:34:13 +00:00
drdev
80f2d38261 Support keeping menu button pressed while menu open 2014-07-03 15:00:50 +00:00
swordshine
419d3df2a0 - Fixed Brago's Flicker trigger 2014-07-03 10:21:05 +00:00
drdev
4cfa7aa74f Create menu button support
Start working on Quest Mode
2014-07-03 01:57:48 +00:00
rikimbo
e63274d411 Minor change to PumpAI.pumpTgtAI so that if an irrelevant/redundant/unrecognized AiLogic tag is found, the process continues through to the default logic. 2014-07-02 00:44:30 +00:00
elcnesh
e30d7bbaa2 Fix Wanderwine Prophets. 2014-07-01 15:17:31 +00:00
elcnesh
d49b6a992f Add trigger that triggers once for each block made, and fix Dead-Iron Sledge by using it.
This should actually be used by any card with "Whenever this blocks/becomes blocked by a creature, ..."
2014-07-01 14:12:31 +00:00
Chris
3cb7831eee Added new card names to changes.txt. 2014-07-01 13:51:18 +00:00
Chris
402ec14bf7 Added new card names to changes.txt. 2014-07-01 13:50:01 +00:00
swordshine
8f52c2d379 - M15: Added Indulgent Tormentor, Mercurial Pretender, and Resolute Archangel 2014-07-01 12:43:09 +00:00
swordshine
628b4f5f40 - Fixed AddAbilities in Clone effect (the order of addExtraCharacteristics and copyCopiableAbilities is switched, so added this back) 2014-07-01 12:09:39 +00:00
elcnesh
2eb2affead Fix missing SVar reference in Soldevi Excavations. 2014-07-01 09:06:33 +00:00
drdev
462a6b5f0b Prevent warning about floating mana if stack isn't empty 2014-07-01 06:15:27 +00:00
drdev
8611f2b1fc Update CHANGES.txt 2014-07-01 06:12:34 +00:00
drdev
352b551038 Tweak message 2014-07-01 06:07:26 +00:00
drdev
43372d84c8 Version bump to 1.5.21.011 2014-07-01 06:04:27 +00:00
drdev
b1a9ceaca6 Ensure undo stack cleared when phase changes 2014-07-01 06:02:35 +00:00
swordshine
ba09fa98ed - M15: Added Generator Servant and Sliver Hivelord 2014-07-01 05:43:35 +00:00
drdev
bdaed80796 Update CHANGES.txt 2014-07-01 05:41:23 +00:00
drdev
6b040f9d16 Prompt when passing priority if mana in your mana pool would be lost 2014-07-01 05:30:53 +00:00
drdev
c6aeb45d0f Tweak min item width increase 2014-07-01 04:59:11 +00:00
drdev
8ff91cd800 Increase minimum menu item width 2014-07-01 04:53:09 +00:00
drdev
b51b67e6f0 Show Undo in prompt if last action is undoable
Clean up unnecessary items from Game menu
2014-07-01 04:46:24 +00:00
drdev
e32f335010 Fix bugs where cards would appear with wrong p/t or card type due to card details cache not being cleared between games 2014-07-01 04:22:42 +00:00
Sol
7c1eb77785 - Fix ability cost of Keldon Arsonist 2014-07-01 00:09:18 +00:00
swordshine
128d9a6039 - M15: Added Chief Engineer and Garruk, Apex Predator 2014-06-30 06:59:06 +00:00
drdev
3689a70762 Commit color tiles 2014-06-30 05:41:29 +00:00
drdev
54566e5d83 Fix so music is properly paused when minimized
Fix so music isn't paused when dialog opened
2014-06-29 19:54:46 +00:00
drdev
47ba47b06f Fix so music doesn't change when opening preferences page the first time 2014-06-29 19:36:18 +00:00
drdev
f5fa6515db Fix so match music switches back to menus music when closing match screen 2014-06-29 16:13:13 +00:00
drdev
b1f2a7e05f Support playing background music for desktop game 2014-06-29 15:56:40 +00:00
elcnesh
b6a2b283cb Patch Norin to function as a commander.
Not really a solution, as the general problem (tracking cards through zone-changing replacement effects) is a bit more involved, but at least this makes the card more functional.
2014-06-29 13:08:11 +00:00
elcnesh
507f9e9c42 Fix resolution order of Rhystic Study's trigger. 2014-06-29 12:26:07 +00:00
swordshine
84f3277680 - M15: Added Borderland Marauder, Goblin Kaboomist, Goblin Rabblemaster, Soul of Shandalar, Stoke the Flames 2014-06-29 12:19:54 +00:00
elcnesh
fa9c537af9 Always include zero mana when paying costs, so costs raises (like Oppressive Rays') are taken into account. 2014-06-29 12:08:37 +00:00
Sloth
58fa27c6ce - Updated the quest deck Raven 3. 2014-06-29 10:28:19 +00:00
drdev
b6aeb05170 Shell out desktop game for background music support 2014-06-29 04:36:51 +00:00
drdev
05baece7df Version bump to 1.5.21.010 2014-06-29 03:35:51 +00:00
drdev
93bcca743c Add setting for disabling background music 2014-06-29 03:34:14 +00:00
drdev
7c821455aa Support switching tracks when music completes 2014-06-29 03:22:46 +00:00
drdev
4a78323b3c Refactor how music is managed 2014-06-29 03:14:24 +00:00
drdev
6feb1e66c2 Don't ignore desktop.ini 2014-06-29 03:11:07 +00:00
drdev
b2bfe0a43d Trim music files down to 40 MB (8 files) 2014-06-29 02:54:43 +00:00
drdev
4135b2006e Support playing background music for mobile game 2014-06-28 23:52:09 +00:00
drdev
eee745010a Version bump to 1.5.21.009 2014-06-28 19:36:24 +00:00
drdev
9fd0132363 Start working on adding sound support 2014-06-28 19:15:55 +00:00
drdev
1051d882a5 Prevent exception being reported if color deck can't be generated the first try 2014-06-28 19:05:13 +00:00
drdev
bdae6bf24c Fix variant checkboxes 2014-06-28 16:00:59 +00:00
drdev
187c919c89 Fix issue where loyalty didn't update as counters added/removed 2014-06-28 13:18:05 +00:00
drdev
589b9394e3 Version bump to 1.5.21.008 2014-06-28 04:34:48 +00:00
drdev
4173bacca3 Change Vanguard to use list view by default 2014-06-28 04:33:17 +00:00
drdev
a911e33c44 Support updating vanguard button text 2014-06-27 23:47:32 +00:00
drdev
756d6a1654 Fix selected state of view options button 2014-06-27 23:36:06 +00:00
drdev
76e4414013 Fix layout of vanguard chooser 2014-06-27 23:32:41 +00:00
drdev
d00232d5dd Support selecting vanguard avatar 2014-06-27 23:30:17 +00:00
elcnesh
bc486d4091 Add script to unify card file format (\n as linebreak, always trailing newline). 2014-06-27 23:04:36 +00:00
elcnesh
495517c765 Update Sword of the Ages' functionality to new oracle text. Fix missing reference in Sasaya. 2014-06-27 23:00:56 +00:00
elcnesh
d5008f1f29 Have suspend trigger only on removing the last time counter, not any type of counter. 2014-06-27 22:49:23 +00:00
elcnesh
d5f7cdb729 Fix for r26453. 2014-06-27 22:11:27 +00:00
elcnesh
d7aa626c45 Add: ability to refer to Cards with which costs were payed (eg. discard, sacrifice) by actual card,
in addition to LKI.

Relevant for example if you want to exile a sacrificed card on resolution (as Sword of the Ages does).
Existing functionality is not affected, only adds more Defined-clauses.
2014-06-27 19:45:16 +00:00
drdev
d4ff20a5e7 Fix so button text updated based on selected decks 2014-06-27 16:26:37 +00:00
drdev
9220b12e3d Don't display count for commander section 2014-06-27 16:06:13 +00:00
drdev
5d529e4bef Support setting commander in editor 2014-06-27 16:04:01 +00:00
drdev
89c164e7f3 Improve deck editing support for variants 2014-06-27 15:42:09 +00:00
Chris
83ebc2ac3d Added new card names to changes.txt. 2014-06-27 14:22:37 +00:00
Chris
a18214b622 Added new card names to changes.txt. 2014-06-27 14:21:05 +00:00
elcnesh
3fae7b360f Fix oracle texts of some cards, and have their functionality match the new texts. 2014-06-27 14:04:55 +00:00
elcnesh
9ec62ebb25 Fix: Don't have Inifinite Reflection copy the creature it enchants. 2014-06-27 13:43:03 +00:00
drdev
74e64c36d7 Refactor deck chooser and editor to support variants 2014-06-27 05:03:24 +00:00
drdev
0fd838a2e9 Fix handling of effect card 2014-06-27 02:04:16 +00:00
drdev
269be19ef8 Re-enable variants combo box 2014-06-27 01:40:22 +00:00
drdev
6cf7051951 Version bump to 1.5.21.007 2014-06-27 00:33:16 +00:00
drdev
1f60f28d2b Fix concurrent modification for desktop game (hopefully) 2014-06-27 00:25:05 +00:00
drdev
2e95ac9f58 Fix so p/t overlay updated after counters added/removed 2014-06-26 23:37:57 +00:00
drdev
ef06a17db6 Code cleanup 2014-06-26 23:16:08 +00:00
drdev
65d4cf3e6e Prevent showing bug reported dialog if image fails to load 2014-06-26 23:15:32 +00:00
drdev
63b0648307 Prevent arrow tail extending too far
Make arrow border thickness scale with app
2014-06-26 23:12:04 +00:00
drdev
f02e057ffa Version bump to 1.5.21.006 2014-06-26 16:02:54 +00:00
drdev
f8105795be Refactor how arrows drawn so they appear at the proper layers 2014-06-26 15:58:10 +00:00
drdev
3245cdae36 Determine color of arrows based on whether they're connecting friends or foes 2014-06-26 15:09:25 +00:00
swordshine
6bdeda2f8e - M15: Added Ajani Steadfast 2014-06-26 14:25:45 +00:00
drdev
53b2d87e78 Refactor and cleanup targeting arrow code 2014-06-26 04:06:10 +00:00
drdev
f0a2809638 Remove unnecessary cases for target arrows 2014-06-26 01:14:26 +00:00
drdev
0a03f7b69a Draw outline around arrow 2014-06-26 01:07:25 +00:00
elcnesh
1597a870bf Remove unnecessary cast. 2014-06-25 14:56:13 +00:00
elcnesh
2271b1e366 Fix counting cards in multiplayer games. Change checking for duplicate Cards to using a Set, as it becomes too complicated to do it using a couple of booleans. 2014-06-25 14:53:51 +00:00
elcnesh
a7f0ff43ce Fix cards depending on damage dealt to opponents for multiplayer games.
Remove unused Count nr of lands played by opponent.
2014-06-25 14:11:10 +00:00
swordshine
64e469e8d9 - Fixed pump effect (u - z) 2014-06-25 13:42:57 +00:00
swordshine
618a4775f2 - Fixed pump effect (s - t) 2014-06-25 13:39:02 +00:00
swordshine
8652b229fc - Fixed pump effect (n - r) 2014-06-25 13:33:15 +00:00
swordshine
6aeab67784 - Fixed pump effect (i - m) 2014-06-25 13:30:40 +00:00
swordshine
7d98c63336 - Fixed pump effect (e - h) 2014-06-25 13:26:22 +00:00
swordshine
0e578d8607 - Added param "Defined$ Self" to fix Council Guardian (a - d) 2014-06-25 13:19:42 +00:00
elcnesh
dd70d399ea Fix some cards related to poison counters, which now function correctly in multiplayer games.
Clean up a method in Player.
2014-06-25 12:59:18 +00:00
elcnesh
48086b30b7 Start removing logic that depends on a single opponent, as this (naturally) doesn't work in multiplayer games.
'OppLifeTotal' is now removed, and started removing 'OppPoisonCounters'.
2014-06-25 10:07:23 +00:00
elcnesh
4eca4decac Fix copy effects so that added triggers (eg. Dethrone from Dack's Duplicate) function again. 2014-06-25 08:34:44 +00:00
drdev
ea7b5e1db7 Support drawing arrow head 2014-06-25 04:37:18 +00:00
drdev
8e4e039c4e Draw outline around arrows 2014-06-25 03:55:16 +00:00
drdev
aea9ce67b3 Improve origins of targeting overlay 2014-06-25 02:11:21 +00:00
drdev
60c443e3ce Improve targeting overlays 2014-06-25 01:50:14 +00:00
drdev
9a0d402139 Start working on targeting arrows 2014-06-24 21:34:03 +00:00
elcnesh
02728670bf Update oracle texts of cards starting with 'w' through 'z'. Fix space in file name of Wear//Tear. 2014-06-24 19:14:36 +00:00
elcnesh
aa0070f94e Update oracle texts of cards starting with 'u' or 'v'. 2014-06-24 19:11:23 +00:00
elcnesh
4a2816ed5b Update oracle texts of cards starting with 't'. Fix Tourach's Gate. 2014-06-24 18:50:38 +00:00
Chris
376ee650b4 Cleared out the changes.txt file, now ready for new material.
Added new card names to changes.txt.
2014-06-24 15:41:28 +00:00
swordshine
e0b478ca3a - M15: Added Master of Predicaments 2014-06-24 04:37:57 +00:00
drdev
9d351105dc Fix so cards actually appear in flashback zone 2014-06-24 04:21:14 +00:00
drdev
3f5ed1d0e9 Version bump to 1.5.21.005 2014-06-24 03:47:47 +00:00
drdev
83800cc274 Fix so animating non-creatures into creatures properly moves card to creatures row 2014-06-24 03:43:24 +00:00
drdev
979f21ed28 Prevent summoning sickness overlay flickering for non-creature permanents turned into creatures 2014-06-24 02:20:41 +00:00
drdev
5e13d9a8dc Fix so certain card details like P/T don't flicker as phases change if static effects are being applied 2014-06-24 02:15:30 +00:00
drdev
4223a96a7a Fix multikicker display for Gnarlid Pack 2014-06-24 01:01:58 +00:00
drdev
4358459d67 Fix issue with borders of flipped zone tabs 2014-06-24 00:55:46 +00:00
drdev
1326ddea9a Fix issue with adding cards to deck or sideboard in limited decks 2014-06-24 00:32:37 +00:00
swordshine
35f8fa6633 - Fixed a typo 2014-06-23 14:13:43 +00:00
swordshine
4e9793e60b - M15: Added Ob Nixilis, Unshackled 2014-06-23 14:10:05 +00:00
swordshine
b958a674e6 - Fixed RemoveCounter effect 2014-06-23 07:04:35 +00:00
drdev
4d9b74e3ad Version bump to 1.5.21.004 2014-06-22 22:00:10 +00:00
drdev
6c2e8e0eea Fix compile warnings 2014-06-22 21:57:56 +00:00
drdev
8bcee9762d Fix compile issues with upgrade to libgdx 1.2.0 2014-06-22 21:50:29 +00:00
drdev
4f4118daf4 Fix issue where quest icons wouldn't appear 2014-06-22 21:37:44 +00:00
drdev
37af01896f Upgrade libgdx to 1.2.0 2014-06-22 20:45:25 +00:00
drdev
5ca78b9a0d For limited decks, prevent being able to add more than is in other pool 2014-06-22 17:26:17 +00:00
drdev
adbe6550b2 Version bump to 1.5.21.003 2014-06-22 16:42:29 +00:00
drdev
406e27d9dc Support adding correct number from within main deck 2014-06-22 16:35:19 +00:00
drdev
33620c8c05 Add icons to menu items
Support adding additional copies of cards already in deck/sideboard
2014-06-22 16:20:14 +00:00
drdev
5c511f1ac2 Improve how double tap and hiding context menu work for item manager 2014-06-22 15:38:08 +00:00
drdev
732d3a3e58 Reduce size of editor context menu
Prevent menu overlapping selection
2014-06-22 15:14:12 +00:00
drdev
6ca9dacbd6 Version bump to 1.5.21.002 2014-06-22 03:36:17 +00:00
drdev
c89c3242e2 Support hiding menu for ItemListView 2014-06-22 03:29:30 +00:00
drdev
2d214f096a Implement context menus for different deck editor types 2014-06-22 02:57:03 +00:00
drdev
5b0cd4629b Support showing context menu for ItemManager 2014-06-21 16:27:24 +00:00
drdev
b75d4471ce Prevent Back button doing anything on Match screen so it's not accidentally bumped when going for OK or Cancel button 2014-06-21 03:51:26 +00:00
drdev
e4687798f5 Prevent menu button jumping to settings screen from match screen so OK button easier to tap 2014-06-21 03:49:42 +00:00
drdev
324fa60357 Support showing tooltip when stat type button long pressed 2014-06-21 03:37:17 +00:00
drdev
ce30fa2e96 Make toggle button filters more usable without a long press being required 2014-06-21 03:28:51 +00:00
drdev
46a7fe15a9 Prevent rendering counts for cards in catalog 2014-06-21 03:03:44 +00:00
drdev
932b3022d9 Prevent crash when removing cards from deck 2014-06-21 02:49:18 +00:00
drdev
62cf2fc06e Fix so editing deck is faster by delaying the loading of the catalog 2014-06-21 02:35:24 +00:00
drdev
ddb0eed610 Revert previous change 2014-06-21 01:55:38 +00:00
drdev
0476e998f6 Improve responsiveness of updating item manager view 2014-06-21 01:45:21 +00:00
swordshine
289ca59839 - Fixed Salvaging Station 2014-06-21 01:28:42 +00:00
drdev
47b515f191 Version bump to 1.5.21.001 2014-06-20 15:54:20 +00:00
Chris
97ea9856cb [maven-release-plugin] prepare for next development iteration 2014-06-20 14:00:24 +00:00
Chris
9410277163 [maven-release-plugin] prepare release forge-1.5.20 2014-06-20 14:00:12 +00:00
Chris
9278da615b Preparing the changes.txt file for the next beta build and release. 2014-06-20 13:29:55 +00:00
Chris
aa514eefa2 Added new card names to changes.txt. 2014-06-20 13:23:36 +00:00
elcnesh
a7cb515314 Update oracle texts of cards starting with 'r' or 's'. 2014-06-20 11:30:01 +00:00
elcnesh
298e078026 Update oracle texts of cards starting with 'p' or 'q'. 2014-06-20 11:28:28 +00:00
drdev
d817203809 Adjust which lands appear by default based on prevalent colors in deck 2014-06-20 05:11:04 +00:00
drdev
146a7d260e Fix so duplicate cards accounted for in symbol count 2014-06-20 04:52:07 +00:00
drdev
53df26d2f8 Swap order of mana symbol and count 2014-06-20 04:39:55 +00:00
drdev
94d13ba9b6 Add label with deck info at bottom of land panel 2014-06-20 04:34:54 +00:00
drdev
8bcc46a42d Tweak add lands dialog so lands appear larger and in a single row 2014-06-20 03:08:50 +00:00
drdev
b26cf24958 Prevent switching to custom deck until new deck saved 2014-06-20 02:35:58 +00:00
drdev
83fcd63fe7 Support generating decks 2014-06-20 01:30:14 +00:00
drdev
c84450e914 Adjust layout logic to make room for Generate New Deck button 2014-06-20 01:03:39 +00:00
drdev
8b853f5037 Allow duplicating preconstructed and quest opponent decks 2014-06-20 00:31:03 +00:00
elcnesh
9e4942a7d6 Update oracle texts of cards starting with 'n' or 'o'. 2014-06-19 21:56:12 +00:00
elcnesh
d315269dac Update oracle texts of cards starting with 'm'.
Also a functional fix to Mogg Bombers, which should deal the damage regardless of whether it's actually sacrificed on resolution of its trigger.
2014-06-19 21:48:10 +00:00
elcnesh
862aa5ddbb Update oracle texts of cards starting with 'l'. 2014-06-19 21:30:06 +00:00
elcnesh
0d4d25c111 Update oracle texts of cards starting with 'j' or 'k'. 2014-06-19 21:23:56 +00:00
elcnesh
1c1167b7db Update oracle texts of cards starting with 'i'. 2014-06-19 21:16:39 +00:00
Krazy
fae0dfeb45 Had hoped to find time to fix targeting overlay CPU usage this week, but was unable to. This adds the functional code back in with no fixes. 2014-06-19 17:24:43 +00:00
elcnesh
36e3fb4333 Update oracle texts of cards starting with 'h'. 2014-06-19 15:54:27 +00:00
elcnesh
27c42a1802 Update oracle texts of cards starting with 'g'. 2014-06-19 15:11:59 +00:00
elcnesh
86935bbcd1 Update oracle texts of cards starting with 'f'.
Also remove space from filename of Fist of Suns.
2014-06-19 14:15:29 +00:00
elcnesh
493334fceb Update oracle texts of cards starting with 'e'. 2014-06-19 13:56:03 +00:00
elcnesh
f1d5ecdb35 Fix Bile Blight affecting noncreature permanents. 2014-06-19 13:33:43 +00:00
swordshine
f05a178021 - Fix last commit 2014-06-19 05:56:49 +00:00
swordshine
8c66788dfb - Added Dead Ringers 2014-06-19 05:53:37 +00:00
Sol
e2fcf9354b - Adding TriggerZone for Snowfall 2014-06-19 03:16:49 +00:00
drdev
83bec0a7c1 Version bump to 1.5.20.008 2014-06-19 02:45:12 +00:00
drdev
ff56b649f3 Support deleting decks without crashing 2014-06-19 02:37:35 +00:00
drdev
5050b25daa Support creating new deck 2014-06-19 02:35:11 +00:00
drdev
72653430a1 Add New Deck and Edit Deck buttons 2014-06-19 01:56:47 +00:00
drdev
27f15f0301 Remove unused functions 2014-06-19 01:35:39 +00:00
drdev
3dc9735aec Improve responsiveness of opening ConstructedScreen by loading decks asynchronously 2014-06-19 01:31:07 +00:00
drdev
c7894866cc Delay deleting font cache until after assets downloaded 2014-06-19 00:01:32 +00:00
excessum
c6b0cb31b5 - Prevent AI from paying the trigger for Athreos, God of Passage for dying tokens 2014-06-18 12:27:40 +00:00
elcnesh
41edb42e56 Fix generated reminder texts of Convoke and Delve. 2014-06-18 08:40:38 +00:00
elcnesh
ad0ea71a52 Update oracle texts of cards starting with 'd'. 2014-06-18 08:38:26 +00:00
swordshine
5e43fc1300 - Fixed UntapAi so cards like Snap, Palinchron will never uptap lands controlled by opponents 2014-06-18 06:03:55 +00:00
swordshine
1e60b68d49 - Fixed Myr Retriever and friends 2014-06-18 05:53:25 +00:00
elcnesh
fe13a7c9fa Update oracle texts of cards starting with 'c'. 2014-06-17 14:27:57 +00:00
elcnesh
4228ddd582 Update oracle texts of cards starting with 'b'. 2014-06-17 11:02:29 +00:00
elcnesh
373617db08 Update oracle texts of cards starting with 'a'. 2014-06-17 10:47:14 +00:00
swordshine
a5f33854f9 - Fixed Urborg 2014-06-17 05:31:08 +00:00
drdev
8f323cbd9b Make deleting old resource files it's own progress bar step 2014-06-17 02:11:16 +00:00
drdev
c5b8a76668 Prevent deleting res/ folder until after assets/zip downloaded 2014-06-17 02:05:43 +00:00
drdev
77083143bd Prevent Forge process sticking around after exiting on Android devices 2014-06-17 01:40:25 +00:00
drdev
219207e4f6 Version bump to 1.5.20.007 2014-06-17 01:15:15 +00:00
drdev
ad3d459d88 Improve card art rendering for split cards 2014-06-17 00:57:45 +00:00
drdev
6c49f9651c Fix error when Flames of the Firebrand targets a player 2014-06-16 23:05:37 +00:00
drdev
521a17207b Move Graphics class to its own file 2014-06-16 22:59:03 +00:00
elcnesh
018fe1145c Cleanup: unify all card files' line endings to '\n' and make sure each file ends with a newline.
Nonfunctional change that allows the oracle script to update the oracle texts of cards in the future.
2014-06-16 17:15:06 +00:00
drdev
6a4ec0e3da Cleanup graphics code 2014-06-15 23:48:19 +00:00
drdev
5b21c3399d Fix rendering of mana cost for split cards 2014-06-15 23:12:39 +00:00
drdev
5c511f7785 Version bump to 1.5.20.006 2014-06-15 22:08:43 +00:00
drdev
7d30810bd8 Fix so font cache deleted when changing themes and after applying update 2014-06-15 22:07:28 +00:00
elcnesh
8efc6bda85 Fix a number of problems with copying permanents.
Copying between face-down permanents, flip cards and transform cards wasn't always working as described in rule 706. This should fix most of those problems.
2014-06-14 22:29:14 +00:00
elcnesh
ac6a2965f7 Reveal a face-down card as it leaves the battlefield (rule 707.9). 2014-06-14 21:42:22 +00:00
drdev
28d045a5d7 Version bump to 1.5.20.005 2014-06-14 14:52:33 +00:00
drdev
29a771dd44 Prevent caching more than one font regardless of switching themes 2014-06-14 14:46:11 +00:00
excessum
c2f1aae631 - Fixed bug with Polukranos logic if the target(s) are not the highest evaluated ones 2014-06-14 14:44:32 +00:00
drdev
6f7c19a366 Show loading screen while changing themes 2014-06-14 14:24:34 +00:00
excessum
c4c74cccfd - Allow AI to use Bloodrush ability 2014-06-14 14:19:04 +00:00
swordshine
176eb0236d - Fixed Dovescape and friends 2014-06-14 13:07:09 +00:00
swordshine
1df53d1bee - Fixed Vines of Vastwood 2014-06-13 13:56:21 +00:00
swordshine
963177e940 - Fixed DamageDealAi (r26280 totally broke cards like Shock) 2014-06-13 07:53:57 +00:00
rikimbo
12de3043d8 Fixed an issue where if an ability had more than one instance of the same type of CostPart (such as that of Demon's Herald, which has three sacrifice costs), the AI was able to get away with paying the cost only once. 2014-06-13 00:17:15 +00:00
rikimbo
3c66861b48 Added logic so that the AI can now use triggered abilities that put X counters on the source permanent, where X is a mana cost paid (eg. Hero of Leina Tower). The AI action is now to spend all remaining mana on X. 2014-06-12 22:50:22 +00:00
drdev
d0a0006b48 Fix issue with saving draft decks and saving after renaming deck
Version bump to 1.5.20.004
2014-06-12 15:58:56 +00:00
drdev
167ebfb991 Prevent zoom toggle caring which direction you fling 2014-06-12 03:40:23 +00:00
drdev
512d96572d Fix typo 2014-06-12 03:39:02 +00:00
drdev
650659ed80 Fix size issue with buttons 2014-06-12 02:23:57 +00:00
drdev
264f421de8 Version bump to 1.5.20.003 2014-06-12 02:13:22 +00:00
drdev
75fc4e7d33 Prevent count label getting cut off 2014-06-12 02:12:17 +00:00
drdev
cd6700b087 Prevent adding basic lands to sealed deck by default for mobile game 2014-06-12 01:50:09 +00:00
drdev
35ebc4e901 Version bump to 1.5.20.002 2014-06-12 01:18:40 +00:00
drdev
8c36dcc8fe Remove Auto button 2014-06-12 01:12:10 +00:00
drdev
4500fc0e44 Support actually adding lands to deck 2014-06-11 22:08:07 +00:00
drdev
337c829677 Rename to Add Basic Lands 2014-06-11 21:53:13 +00:00
drdev
9bd2666116 Fix art generation for add lands dialog 2014-06-11 21:42:07 +00:00
drdev
6f1153479a Fix layout issues with Add Lands dialog 2014-06-11 21:09:56 +00:00
drdev
afe7d180a6 Create AddLandsDialog 2014-06-11 20:43:59 +00:00
drdev
a007e48c4e Remove unused imports 2014-06-11 19:01:51 +00:00
Chris
ed3494a2c0 Added new card names to changes.txt. 2014-06-11 15:45:19 +00:00
Chris
18e3a5b09a Cleared out the changes.txt file, now ready for new material. 2014-06-11 15:29:54 +00:00
drdev
ef49639193 Support renaming decks 2014-06-11 14:25:53 +00:00
excessum
e80b8a9422 - Fixed bug with PowerDmg targets being reset in DamageDealAi 2014-06-11 13:39:36 +00:00
drdev
a8b64a4721 Add popup menu to more button 2014-06-11 03:38:14 +00:00
drdev
4dcf77617b Support updating name as changes made and saved 2014-06-11 03:14:20 +00:00
drdev
d23d9a9665 Add header to deck editor 2014-06-11 02:58:58 +00:00
swordshine
c349c3df29 - Prevent potential NPE 2014-06-11 02:55:58 +00:00
swordshine
a8c926b74e - Update oracle texts for CNS cards 2014-06-11 02:42:30 +00:00
swordshine
2f3b60fafa - Update mtg-data 2014-06-11 02:38:04 +00:00
swordshine
b77cebd9f1 - Added Mystic Barrier 2014-06-10 13:46:54 +00:00
elcnesh
3bab44c173 Fix: crash when a player leaves the game. 2014-06-10 11:17:19 +00:00
swordshine
6d7be31a50 - Attempt to fix a potential NPE in PumpAiBase for cards in alternate modes. 2014-06-10 05:37:59 +00:00
drdev
24f648276d Improve readability for read-only fields 2014-06-10 04:12:09 +00:00
drdev
b9cc83e37f Prevent editing name of decks (for now) 2014-06-10 04:01:28 +00:00
drdev
61a610dc0d Support deleting decks from options page 2014-06-10 03:55:04 +00:00
drdev
588f545d51 Fix so closing editor without saving properly restores deck from file 2014-06-10 03:46:51 +00:00
drdev
6f24598c5a Support retaining selected draft deck and sealed deck 2014-06-10 02:45:30 +00:00
drdev
5821c0f5fc Support saving deck, prompting to save if changes made, and refreshing decks list when returning to previous screen 2014-06-10 02:33:11 +00:00
Krazy
5307a8fbe2 Fixed the UI thread maxing out CPU cores when rendering targeting arrows. 2014-06-10 01:06:19 +00:00
elcnesh
e70c29dce3 Fix: Forsaken Drifters' trigger is not optional. 2014-06-09 20:57:15 +00:00
elcnesh
5cbc4e5703 Fix NPE in AI decision on giving attacking creature protection. 2014-06-09 20:30:23 +00:00
elcnesh
537a792dcc Fix cost changes and play restrictions on morphs.
Dream Chisel now works on all morphs (including Zoetic Cavern), and cards like Meddling Mage don't prohibit the named card to be cast face down.
2014-06-09 20:10:48 +00:00
elcnesh
9807361a39 Fix NPE on startup if you don't have Quest achievements yet. 2014-06-09 11:57:42 +00:00
drdev
29fc7a7d78 Flesh out options page some 2014-06-09 03:07:13 +00:00
drdev
1ff6afe5ea Make tabs take up full width 2014-06-09 02:43:14 +00:00
drdev
e45b70470f Make tabs take up full screen width
Add Options page to deck editor
2014-06-09 02:34:39 +00:00
rikimbo
3aa95c01ca Fixed an issue where when a Licid creature was in its alternate state, its picture would not be shown correctly. 2014-06-09 00:52:40 +00:00
drdev
fa2b6a0dac Support moving cards between main and sideboard by double tapping them 2014-06-08 22:38:20 +00:00
drdev
a7523ea539 Support starting sealed deck game 2014-06-08 22:15:36 +00:00
drdev
5ec6e504bc Support generating sealed deck for mobile game 2014-06-08 21:56:57 +00:00
drdev
2721901ea0 Support editing existing draft decks 2014-06-08 21:07:46 +00:00
drdev
262f11fba4 Refactor draft screen to use new FDeckEditor 2014-06-08 20:56:46 +00:00
Krazy
1c0696e5bb Removed debugging code. 2014-06-08 19:16:52 +00:00
Krazy
ea646ff9ad Fixes for old quests not working with tournaments. 2014-06-08 19:15:40 +00:00
elcnesh
c12aee1354 Fix: Opaline Sliver's ability should trigger on becoming the target of _any_ spell, not just instants and sorceries. 2014-06-08 15:16:48 +00:00
swordshine
f38e8e546f - Added Grave Scrabbler 2014-06-08 13:28:53 +00:00
elcnesh
0dfa4c1ab2 Cleanup: use Lang for formatting numbers. 2014-06-08 13:04:30 +00:00
swordshine
0829445185 - Added Grenzo's Rebuttal 2014-06-08 11:33:28 +00:00
swordshine
8ccdcf93c8 - Added Order of Succession 2014-06-08 11:01:14 +00:00
swordshine
876e9260fe - Fixed Suffer the Past 2014-06-08 05:30:15 +00:00
excessum
b8aa37891d - Fixed missing conditional from r26240 2014-06-08 02:06:59 +00:00
excessum
69b76f31d3 - AI will not always use Boros Charm for damage at opponent EOT unless DamageDealAi.shouldTgtP() holds 2014-06-08 02:03:43 +00:00
drdev
2138b11a63 Start working on deck editor screen 2014-06-08 01:25:50 +00:00
drdev
aead126c92 Improve layout of draft screen 2014-06-08 00:08:56 +00:00
drdev
4c1cabb442 Reduce height of deck item lines 2014-06-07 23:33:29 +00:00
drdev
b7a56f1d1c Add loading screen for draft 2014-06-07 21:51:12 +00:00
drdev
1f7dcdc9db Make loading overlay able to be more generic
Prevent adding lands to draft pool by default
2014-06-07 21:38:32 +00:00
drdev
2416bc230f Improve saving draft when finished and hiding Pack page 2014-06-07 18:22:19 +00:00
drdev
6036cf38e1 Fix reprompting issue with input dialogs 2014-06-07 18:18:39 +00:00
drdev
ab8c07cb52 Support building deck while drafting 2014-06-07 17:47:44 +00:00
drdev
eb942adf41 Allow changing from Zoom to Details and back with a quick fling action 2014-06-07 16:42:21 +00:00
swordshine
fba3ba212b - Added Time Distortion 2014-06-07 11:46:48 +00:00
excessum
345cacade9 - Changed useRemovalNow() condition from isSpell() to !isTrigger. Added "PlayMain1" to Xenagod to make use of pre-combat trigger. 2014-06-07 11:06:49 +00:00
swordshine
29f7c7741f - Fixed Woodvine Elemental 2014-06-07 09:21:55 +00:00
drdev
bc8dc0f451 Rename tabs and include counts in them 2014-06-07 05:54:24 +00:00
drdev
3a2b62f572 Prevent extra gap in image view when not piling by anything 2014-06-07 05:46:02 +00:00
drdev
09190ea026 Allow showing picks and selecting picks 2014-06-07 05:44:17 +00:00
drdev
7124150328 Flesh out drafting process tab pages 2014-06-07 05:37:00 +00:00
drdev
233d6a99c0 Create drafting process screen and prevent leaving it without user being prompted 2014-06-07 05:06:59 +00:00
drdev
354b861d14 Support building new draft 2014-06-07 04:31:19 +00:00
drdev
9a8d1c4678 Make match loader show properly without getting stuck open 2014-06-07 04:24:40 +00:00
drdev
c0b54d3084 Flesh out draft screen some more 2014-06-07 04:12:36 +00:00
drdev
20a7da9302 Start working on draft screen 2014-06-07 03:38:35 +00:00
drdev
3f19d543ef Version bump to 1.5.20.001 2014-06-07 02:32:53 +00:00
drdev
a51cce626a Open folder if icon single tapped 2014-06-07 02:31:50 +00:00
drdev
801eaf0fed Support saving changes to storage locations 2014-06-07 02:13:32 +00:00
drdev
abad25de40 Add file rename support
Update to 1.5.20
2014-06-07 01:25:03 +00:00
swordshine
e60a00033b - Merged CNS branch, added CNS edition file 2014-06-06 15:21:33 +00:00
Chris
1cdf2362e3 [maven-release-plugin] prepare for next development iteration 2014-06-06 14:22:01 +00:00
Chris
5e1e874c33 [maven-release-plugin] prepare release forge-1.5.19 2014-06-06 14:21:47 +00:00
Chris
250dad16bc Preparing the changes.txt file for the next beta build and release. 2014-06-06 13:46:35 +00:00
Chris
d79cdbddb0 Added new card names to changes.txt. 2014-06-06 13:41:43 +00:00
Krazy
e877613d32 Finished up the tournament mode. Added changes to changes.txt. See forums for complete details. 2014-06-06 07:31:57 +00:00
swordshine
65fa1dd5d2 - Fixed a potential NPE in AnimateAi 2014-06-06 04:51:55 +00:00
drdev
4180a391f7 Support deleting folders/files via long press menu 2014-06-06 04:30:59 +00:00
swordshine
bd2958f5e9 - Added Risky Move 2014-06-06 04:30:04 +00:00
drdev
24bd966535 Fix editing cache dir 2014-06-06 04:00:09 +00:00
drdev
7b8563f62b Support creating new folders 2014-06-06 03:58:08 +00:00
drdev
9acaaca552 Add return value validation 2014-06-06 03:35:01 +00:00
drdev
950e4ed97e Prevent buttons on dialogs not working if you hold down more than half a second 2014-06-06 03:17:35 +00:00
drdev
e59c1f1010 Rename Storage Options to Storage Locations 2014-06-06 03:11:41 +00:00
drdev
03d09306aa Round some tab width numbers to make them look better 2014-06-06 03:08:19 +00:00
drdev
d9c8f64e09 Reduce size of tabs a bit 2014-06-06 03:06:22 +00:00
drdev
5cab70dc62 Add back icon to file text field 2014-06-06 03:02:28 +00:00
drdev
d51fe586ab Fix selection of scaled down text in text field 2014-06-06 02:34:11 +00:00
drdev
4aa70cb5c0 Prevent getting stuck on ViewWinLose by pressing Escape or Back 2014-06-06 02:26:38 +00:00
drdev
1deebe6111 Support opening folders and going back 2014-06-06 02:22:57 +00:00
drdev
9881d5c194 Fix freeze after accepting file chooser 2014-06-05 22:42:42 +00:00
drdev
f7f82db756 Flesh out file chooser 2014-06-05 22:33:17 +00:00
drdev
e124c76e5a Fix selection logic for text fields 2014-06-05 21:47:17 +00:00
drdev
a5573cd0e4 Fix file chooser layout 2014-06-05 21:42:06 +00:00
Krazy
1939d0602e Massively reduced draft image file size. 2014-06-05 21:38:28 +00:00
Krazy
9f776f0d1a Changed the way draft tokens work. Players can now spend tokens freely while drafts are generated every 5 turns regardless of token count. 2014-06-05 21:29:13 +00:00
drdev
0b7a442958 Add folder icon for file chooser dialog 2014-06-05 21:23:14 +00:00
drdev
ff76126e8e Improve items for changing storage options 2014-06-05 20:41:44 +00:00
Krazy
2ebdbfcb7a Added another possible booster configuration for tournaments. 2014-06-05 20:41:14 +00:00
Krazy
6e2a9be30d Removed ability to concede for AI in tournaments.
Rewrote booster configuration selection for tournaments.
Minor balance adjustments for tournaments.
2014-06-05 20:37:15 +00:00
drdev
7fe6732684 Refactor ForgeProfileProperties to allow changes at runtime 2014-06-05 20:27:30 +00:00
drdev
ba561341ea More cleanup of ForgeProfileProperties 2014-06-05 19:29:33 +00:00
drdev
4f15de6639 Refactor so profile props can be loaded for mobile game 2014-06-05 19:21:50 +00:00
elcnesh
8c1bd75c6b Commander damage from your own commander can be lethal, so do not omit this number when displaying commander damage.
Format commander damage in multiplayer games a bit nicer.
2014-06-05 14:20:41 +00:00
swordshine
ef13b0ac4a - Attempt to fix Venarian Gold 2014-06-05 14:15:28 +00:00
swordshine
bbb4e1da7b - Added Hollow Warrior 2014-06-05 13:39:19 +00:00
excessum
7143cfc8b1 - Fixed wrong type for Mark for Death 2014-06-05 12:42:06 +00:00
excessum
816b65fbb1 - Update for PumpAiBase.pumpedCreature() to copy counters onto pumped Card 2014-06-05 11:26:27 +00:00
elcnesh
8fbd507854 Fix: Have certain effects happen in turn order.
Also reset the turn order when restarting the game.
2014-06-05 11:05:48 +00:00
drdev
0244fc4461 Start work on file picker dialog 2014-06-05 03:38:37 +00:00
Sol
e04b64f7be - Initial checkin for Winston Draft mode. The menu item for Winston Draft is currently commented out, but it should be functional even though the AI is randomnly taking piles based on pile size. 2014-06-05 02:39:48 +00:00
swordshine
cc79d33206 - Added Tahngarth's Glare 2014-06-05 02:21:47 +00:00
drdev
36e45a4cf4 Version bump to 1.5.19.009 2014-06-04 12:57:47 +00:00
drdev
acb9fdcc40 Remove minimum on list chooser selection 2014-06-04 12:50:00 +00:00
Krazy
22a71e67aa Fixed a minor typo. 2014-06-04 06:38:45 +00:00
drdev
a933ce7484 Fix prompt and min/max for color choose effects 2014-06-04 03:07:31 +00:00
drdev
6c5a1fc4d1 Prevent deselecting items if min and max are the same so you can change which items are selected 2014-06-04 02:48:43 +00:00
drdev
e34f3fd1d8 Disable View Deck for random deck categories 2014-06-04 02:41:17 +00:00
drdev
442228c308 Fix spell of "Gauntlet" 2014-06-04 02:38:34 +00:00
Krazy
423a9f1687 Rewrote draft generation and rotations. 2014-06-03 23:58:50 +00:00
drdev
b874b39241 Fine tune list selection support to define min and max number of selections allowed 2014-06-03 22:51:30 +00:00
drdev
96c0194f50 Ensure selected items are sorted when multiple selections allowed
Prevent activating on double tap if touched down on different item first time than second time
2014-06-03 22:27:18 +00:00
drdev
e92bdc665f Improve multi-select list appearance
Optimize list item tap and render logic by passing index as parameter
2014-06-03 22:18:32 +00:00
elcnesh
0a51c45081 Fix putting creatures onto the battlefield blocking. They are inserting into the existing damage assignment order. 2014-06-03 14:24:36 +00:00
elcnesh
a9cda27936 Add ability to reverse turn order. 2014-06-03 14:16:12 +00:00
Chris
301907a664 Added new card names to changes.txt. 2014-06-03 13:11:45 +00:00
Sloth
06f5e460eb - Added the quest opponent Aqueduct 3. 2014-06-03 07:32:00 +00:00
Sloth
57bdab6a24 - The AI will no longer kill itself with Mana Confluence. 2014-06-03 06:08:07 +00:00
Krazy
5b073a4f56 Few tournament tweaks and fixes. 2014-06-03 00:25:28 +00:00
swordshine
2738b2f79b - Added Ice Cave 2014-06-02 13:58:46 +00:00
excessum
6412dd2702 - AI will check for targets for Oblivion Ring effects before casting them 2014-06-02 13:57:52 +00:00
swordshine
fce7250373 - Fixed Unifying Theory 2014-06-02 13:20:21 +00:00
swordshine
c6da06f3b1 - Fixed Temporal Extortion 2014-06-02 12:23:59 +00:00
excessum
7afd1cea5d - Fix for CharmAi with probabilistic choices that might resolve with a null choice 2014-06-02 12:10:33 +00:00
swordshine
35284ad13a - CNS: Added Bite of the Black Rose, and Marchesa's Emissary 2014-06-02 09:15:06 +00:00
swordshine
66627f06a0 - Added Oracle texts 2014-06-02 06:05:04 +00:00
drdev
23247d82ae Improve new setting names 2014-06-02 04:30:43 +00:00
drdev
27ce50eeab Add vibration options 2014-06-02 04:26:00 +00:00
drdev
433b13e2ff Optimize how prompt buttons are updated to prevent messages getting stuck or buttons being temporarily disabled then re-enabled 2014-06-02 04:00:54 +00:00
drdev
90068f41d7 Make log accept any Object 2014-06-02 03:18:14 +00:00
drdev
bb5dc1dee9 Go back to using large heap since it didn't help to stop using it 2014-06-02 00:37:10 +00:00
drdev
93f66cef46 Version bump to 1.5.19.008 2014-06-01 23:29:39 +00:00
drdev
fd9577d1e1 Remove use of large heap to improve game performance 2014-06-01 23:25:28 +00:00
drdev
dce65ebf77 Prevent showing card information in Details view if card should be hidden 2014-06-01 23:11:53 +00:00
drdev
980b82b687 Prevent showing foil effect for hidden cards 2014-06-01 23:00:46 +00:00
Krazy
c7357eaacd Prevent draft scumming by removing the draft from the quest if the draft is left early. 2014-06-01 21:13:58 +00:00
Krazy
9fdc946bd7 Tournament results are now recorded and displayed. 2014-06-01 20:39:42 +00:00
Krazy
3006081872 Fixed drafted cards not being added to your pool in tournament mode. Put measures in place to stop a rare NPE. 2014-06-01 19:52:58 +00:00
drdev
917a3b4a96 Fix crash with ListChooser for pick a pile effects 2014-06-01 19:32:12 +00:00
Sol
95e77eb40e - Improve the dialogs related to damage replacement when controlling multiple planeswalkers. 2014-06-01 17:16:05 +00:00
drdev
b236ca8c03 Version bump to 1.5.19.007 2014-06-01 16:54:09 +00:00
drdev
28e873aded Support showing poison counters under life total 2014-06-01 16:49:32 +00:00
swordshine
943ff54013 - Missing file in r26122 2014-06-01 14:51:19 +00:00
swordshine
994bb6dbdc - Added Thick-Skinned Goblin and Shah of Naar Isle 2014-06-01 14:39:40 +00:00
swordshine
2fef2a6dc6 - Added Hammerheim 2014-06-01 12:51:37 +00:00
excessum
581553e3f9 - Minor tweak to r26118 2014-06-01 11:52:27 +00:00
excessum
821298eaf5 - PumpAiBase update for buffing attackers 2014-06-01 10:45:21 +00:00
swordshine
890fde3baf - Added Adarkar Unicorn 2014-06-01 10:01:18 +00:00
excessum
51bdf2484d - Extend AI pump spell usage to PumpAll 2014-06-01 08:52:43 +00:00
swordshine
d5326d61c0 - Added Snowfall 2014-06-01 08:37:09 +00:00
swordshine
0be2903bad - Added Balduvian Fallen 2014-06-01 07:58:31 +00:00
Krazy
f7af4ad823 Small tournament bug fix. 2014-06-01 06:04:03 +00:00
Krazy
0ce6c5a045 Bug fixes for tournament mode. 2014-06-01 05:51:37 +00:00
Krazy
4962c9d91e Improvements to tournament screen selection. 2014-06-01 05:25:22 +00:00
Krazy
f7d82c00d5 Fixed crash on startup. 2014-06-01 05:19:50 +00:00
swordshine
b459ca2ec0 - Fixed a potential NPE 2014-06-01 05:10:51 +00:00
Krazy
3d19965896 Can now continue interrupted tournaments.
Now enforcing credit requirements for entry to tournaments.
2014-06-01 05:08:13 +00:00
drdev
d7da319aa5 Prevent crash when AI attacks 2014-06-01 05:05:19 +00:00
drdev
b8d29b992d Support rendering card damage about p/t box 2014-06-01 04:56:06 +00:00
Krazy
0aefe88a7d Added image to tournament deck building screen.
Added tournament prizes.
Added extra confirmation dialogues to "dangerous" actions in tournament mode.
Several tournament bug fixes and UI improvements.
2014-06-01 04:52:48 +00:00
drdev
8498d299a5 Prevent crash if card art can't be found 2014-06-01 04:20:06 +00:00
drdev
56b87d9d15 Prevent crash when assigning damage for creature with trample 2014-06-01 04:09:01 +00:00
Sol
f2e7347ad3 - Since Morph creatures don't have an official Card in the database, they need to be copied instead of being looked up 2014-06-01 02:46:14 +00:00
drdev
f813eef30f Fix logic for determining which card panel to bring to front 2014-06-01 01:57:14 +00:00
drdev
da45846f20 Support cascading cards in hand 2014-06-01 01:24:59 +00:00
drdev
c926227995 2014-05-31 22:46:33 +00:00
drdev
8b1587b09d Version bump to 1.5.19.006 2014-05-31 22:45:52 +00:00
Sloth
3601b109ac - Added SVar:PlayMain1:TRUE to 2 cards. 2014-05-31 22:08:03 +00:00
Krazy
e05948fb99 Edit deck stage of draft tournaments now persists between loading and saving quests. 2014-05-31 21:53:51 +00:00
Krazy
289e1c35c5 Initial commit of the Draft Tournament for Quests. 2014-05-31 21:04:29 +00:00
drdev
24f4dd0e24 Prevent stacking tokens on top of non-tokens 2014-05-31 20:47:11 +00:00
drdev
8474f0abec Simplify blocker mesage
Support tapping to undeclare blocker
Auto-select attacker to declare blockers for
2014-05-31 20:39:07 +00:00
drdev
daefff97c4 Add card overlay settings and prevent losing scroll position on settings screen 2014-05-31 20:06:55 +00:00
drdev
be2de74a0b Add setting to hide match background image 2014-05-31 19:50:41 +00:00
drdev
1986ab8769 Fix weird font issue on progress bar
Prevent Forge not being able to reopen if its already running
2014-05-31 19:26:22 +00:00
Sloth
26bb62f027 - Updated 2 quest decks. 2014-05-31 19:01:11 +00:00
drdev
71bdaa1724 Fix so Gdx.app.exit actually closes app 2014-05-31 17:15:40 +00:00
drdev
a718d5ac8d Version bump to 1.5.19.005 2014-05-31 16:56:07 +00:00
drdev
1687445dbb Reanme Cancel to Call Back for calling back attackers 2014-05-31 16:38:44 +00:00
drdev
4029d0d452 Fix so Cancel button text restored for certain inputs 2014-05-31 16:25:59 +00:00
drdev
c4ec40aa55 Increase min Android version to 11 (3.0) and allow using large heap 2014-05-31 16:22:01 +00:00
Sol
a15a9b9929 - Added Chronicles to the 4th edition "block" (since it's considered an extension of that Base set) and to the boosterbox list
- Fixing booster box numbers: 8 card boosters come in 60 boosters per box, 12 card boosters come in 45 boosters per box.
2014-05-31 15:27:33 +00:00
excessum
9e50785b73 - Improved AI for creating attackers using pump effects 2014-05-31 12:30:25 +00:00
swordshine
069a8a9e40 - Moved Soulbond checks to checkStaticAbilities 2014-05-31 12:10:05 +00:00
excessum
c713895f7a - PumpAiBase update to support Haste and better odds for multiple beneficial effects from a single pump. Removed RemAiDeck for Judge's Familiar since it is almost impossible to find a situation where a 1-mana Force Spike is bad 2014-05-31 12:02:41 +00:00
swordshine
084928b926 - Added Soul Sculptor 2014-05-31 12:01:11 +00:00
swordshine
7ae0860355 - Move controllerChangeZoneCorrection to checkStaticAbilities 2014-05-31 10:57:26 +00:00
swordshine
d4f9badca0 - Added Nix 2014-05-31 08:48:35 +00:00
swordshine
76c6812355 - Added Halfdane 2014-05-31 01:53:13 +00:00
drdev
9405b8022e Remove all log messages 2014-05-31 00:09:00 +00:00
drdev
4be66ac2c4 Improve InputAttack to make tapping undeclare attacker if banding not possible, simplify message, and allow Alpha Strike and Cancelling attackers from right prompt button 2014-05-30 23:57:14 +00:00
drdev
02eb3dd0de Turn Cancel button into End Turn for basic priority prompt 2014-05-30 22:41:01 +00:00
Chris
29bc93aa1d Added new card names to changes.txt. 2014-05-30 22:00:14 +00:00
drdev
e18f879d40 Add support for exiting Forge using back button from Home screen 2014-05-30 21:59:54 +00:00
drdev
60b6343823 Version bump to 1.5.19.004 2014-05-30 20:50:54 +00:00
drdev
a5d1f4e157 Add code for checking for updates 2014-05-30 20:47:34 +00:00
Krazy
b89648bed2 Something about creature stacking seems to be causing the ConcurrentModificationExceptions. Disabling until I get around to fixing it. 2014-05-30 20:32:35 +00:00
drdev
3701501e73 Make assets downloading progress show correctly 2014-05-30 20:03:37 +00:00
drdev
cd84d5e96a Tweak how skin reloaded after assets downloaded 2014-05-30 19:54:50 +00:00
drdev
2c071507da Fix skin loading when resource directory not yet loaded 2014-05-30 19:45:11 +00:00
Krazy
08fe857ef3 Potentially fixed a common ConcurrentModificationException. 2014-05-30 19:34:47 +00:00
Sloth
ea3e86700e - Added SVar:RemAIDeck:True to cards like Stifle. The AI is not ready for them yet. 2014-05-30 13:26:56 +00:00
drdev
fcbe79ee3f Make progress towards having download support work 2014-05-30 04:59:32 +00:00
drdev
df8d38475a Version bump to 1.5.19.003 2014-05-30 00:53:08 +00:00
drdev
86dd678604 Show progress trail for scanning for existing items 2014-05-30 00:46:46 +00:00
drdev
d52387ad15 Update splash screen message to impress that updating resource files may take awhile 2014-05-30 00:40:23 +00:00
drdev
231f39264e Fix ETA for progress bar 2014-05-30 00:16:16 +00:00
drdev
f28cac12bf Prevent assets update check when running from GUI 2014-05-30 00:08:41 +00:00
drdev
90d6897ca1 Fix progress bar back color 2014-05-30 00:07:18 +00:00
drdev
69d546b83b Fix so resource files unzipped properly and skin reloaded afterward 2014-05-30 00:05:36 +00:00
drdev
80070d5301 Code cleanup 2014-05-29 22:49:27 +00:00
drdev
34951f5847 Support progress trail for certain splash screen periods 2014-05-29 22:47:38 +00:00
swordshine
cfbd8c31b0 - Added Jeleva, Nephalia's Scourge and Marath, Will of the Wild 2014-05-29 04:59:25 +00:00
drdev
02b2975c0d Make progress towards being able to automatically download assets files on startup 2014-05-29 04:54:30 +00:00
Krazy
681d257b8e Fixed Android pom to correctly zip and package the cardsfolder. 2014-05-29 04:26:29 +00:00
drdev
f6adcf2353 Fix so cardsfolder is zipped within main assets zip 2014-05-29 03:33:24 +00:00
drdev
e2c8c1095d Comment out HelpPage for now 2014-05-29 03:18:15 +00:00
drdev
e3c98c3782 Get downloaders working from mobile game 2014-05-29 03:14:39 +00:00
drdev
7021873675 Restore tab page for settings screen 2014-05-29 02:27:33 +00:00
drdev
f110f15877 Prepare 1.5.19.002 release 2014-05-29 02:14:46 +00:00
Chris
c2f92c3a20 Added new card names to changes.txt. 2014-05-29 01:18:21 +00:00
Krazy
3c4e455810 Changed jarsigner algorithm to work on less-than-brand-new versions of Android. 2014-05-28 18:36:50 +00:00
swordshine
f08f4fec26 - Added Prossh, Skyraider of Kher 2014-05-28 14:03:13 +00:00
swordshine
30e67c4556 - Fixed a possible NPE 2014-05-28 06:48:52 +00:00
Krazy
3304a458d0 Random duel button now only regenerates duels if a duel can be started. This prevents the list from getting refreshed every time it fails to start a game. 2014-05-28 05:43:56 +00:00
Krazy
58fc6b426a Changed win streak label height on the Challenges submenu to fit the entirety of the text, bringing it in line with the duels submenu. 2014-05-28 05:31:58 +00:00
swordshine
2453bcd0c2 - Added Lightning Storm 2014-05-28 05:20:51 +00:00
drdev
431415f485 Add pages for Files and Help 2014-05-28 04:09:32 +00:00
drdev
1a99cb05ab Support screen with one or more tab pages and use for settings screen 2014-05-28 03:54:44 +00:00
drdev
d5d3fd3bb5 Refactor how header for screens handled
Add GuiDownloader for mobile app
2014-05-28 02:13:16 +00:00
drdev
226145ca22 Further refactor downloader 2014-05-28 01:24:49 +00:00
drdev
99762835d1 Fix so downloader actually shows progress 2014-05-28 00:31:39 +00:00
drdev
5c2f3ddf85 Fix so downloader doesn't cause infinite loop 2014-05-28 00:28:40 +00:00
swordshine
c07f8d5e9b - Added Equipoise 2014-05-27 12:51:56 +00:00
drdev
df0e320a5f Refactor gui downloaders to be reusable by mobile app 2014-05-27 05:57:03 +00:00
drdev
25305fd6d6 Tweak how forge-android is published 2014-05-27 04:31:16 +00:00
Krazy
22ae54c2bd Added a button that starts a duel against a random opponent in quest mode.
Fixed some Android pom spacing.
Fixed a bug when generating booster boxes.
2014-05-27 02:52:01 +00:00
drdev
c646adf1e5 Ignore .keystore files 2014-05-27 02:35:01 +00:00
drdev
6bb4f874db Show more useful message when not paused for playback 2014-05-27 00:44:03 +00:00
drdev
f622a417f9 Fix alignment issue with wrapped text 2014-05-27 00:32:13 +00:00
drdev
0bdf7e83f1 Auto-pause playback if mouse down anywhere above prompt or if device pauses game 2014-05-27 00:21:16 +00:00
drdev
1f4c5ef2e8 Improve performance of opening ConstructedScreen 2014-05-26 23:44:20 +00:00
drdev
58daa4c628 Tweak load screen padding 2014-05-26 23:29:04 +00:00
drdev
a9c43c1ede Adjust previous fix to make it work properly 2014-05-26 23:18:05 +00:00
drdev
84b5591612 Fix checking for GuiThread on Android 2014-05-26 22:55:44 +00:00
drdev
5da8fcfc66 Add source for LwjglApplication 2014-05-26 22:35:49 +00:00
drdev
bcb5b5031d Make fonts greater than maximum font size work quickly 2014-05-26 22:05:09 +00:00
drdev
8c2312bf07 Refactor font getting and setting 2014-05-26 21:43:29 +00:00
drdev
205a00690a Refactor FSkinFont to avoid exposing BitmapFont instance 2014-05-26 20:53:50 +00:00
drdev
ae8cb58c33 Optimize font loading to happen on startup without blocking UI thread any more than necessary 2014-05-26 20:31:22 +00:00
Krazy
b0826714d0 Re-fixed r26007's bug fix in an android-friendly way. 2014-05-26 19:32:00 +00:00
drdev
57697095fd Improve final splash screen message 2014-05-26 19:25:23 +00:00
drdev
3672dbee06 Delete comment out code 2014-05-26 19:19:33 +00:00
Krazy
e1c35e06a2 Added FTP capabilities for Android build. Removed duplicate package-info.java files. 2014-05-26 18:40:42 +00:00
drdev
b5f580b164 Prevent generating fonts of size > 72 2014-05-26 17:53:36 +00:00
drdev
a90293c264 Support caching generated fonts for quicker load on subsequent attempts 2014-05-26 17:34:36 +00:00
Krazy
20924826df Fixed Forge crashing on startup when running for the first time. 2014-05-26 16:19:34 +00:00
drdev
afb346d647 Update libgdx-freetype.so 2014-05-26 15:56:26 +00:00
drdev
137db75a99 Prevent hiding name/mana cost if default card image shown 2014-05-26 15:33:06 +00:00
drdev
a286dcf3fd Prevent cutting off cards when zoomed in really far 2014-05-26 15:18:09 +00:00
drdev
a69be98713 Optimize rendering so objects outside visible area but within parent that's rendered aren't drawn 2014-05-26 14:56:25 +00:00
swordshine
34c20250a4 - Added Reversal of Fortune 2014-05-26 14:34:12 +00:00
drdev
ef9a52cef1 Fix variable naming issue 2014-05-26 14:32:41 +00:00
drdev
d2a6b6db4a Adjust visible settings for one that's work 2014-05-26 14:08:17 +00:00
drdev
2602b17064 Comment out sound setting for now 2014-05-26 13:53:59 +00:00
drdev
4f066354ee Optimize text renderer for scroll panes 2014-05-26 13:37:10 +00:00
excessum
de91e28b4f - AI update for pump spells 2014-05-26 12:27:52 +00:00
swordshine
933ea121b0 - Update scripts 2014-05-26 12:01:11 +00:00
drdev
103c74661f Remove pointless method for ending key input 2014-05-26 01:33:00 +00:00
drdev
aee6853ce1 Fix alignment of loading screen icon 2014-05-26 01:24:58 +00:00
drdev
6765e8a98e Make it so loading screen appears after clicking Start button 2014-05-26 01:13:56 +00:00
Krazy
504b092a99 Potential fix for Banishing Light/Mortal Obstinacy crash. Minor testing is successful with no immediately apparent side-effects. 2014-05-26 00:51:47 +00:00
Krazy
a2c17a8c64 Added Android build process. 2014-05-26 00:38:23 +00:00
drdev
2be0e36343 End key input if Back button pressed while keyboard open 2014-05-26 00:18:56 +00:00
drdev
1c3b767935 Fix issue when card remained tapped when switching zones 2014-05-25 23:45:45 +00:00
drdev
d49498d437 Improve layout of VAssignDamage 2014-05-25 23:11:15 +00:00
drdev
e892ad6c9a Fix text renderer bounds issue
Prevent setting up game state when no player has priority
2014-05-25 22:21:03 +00:00
Chris
a245c2dd31 Cleared out the changes.txt file, now ready for new material. 2014-05-25 21:39:33 +00:00
drdev
da5660571c Fix so VAssignDamage can actually get opened 2014-05-25 17:45:16 +00:00
drdev
44031906af Fix alignment of message box messages 2014-05-25 17:28:08 +00:00
drdev
54332a6ecf Support border behind card panels 2014-05-25 17:17:08 +00:00
drdev
bd6c5ce3f8 Fix up VAssignDamage 2014-05-25 16:50:18 +00:00
drdev
a9fd423482 Fix unselecting or zooming selected items in image view 2014-05-25 15:26:14 +00:00
drdev
984a01ed68 Show card overlays in listchooser and stack 2014-05-25 15:17:20 +00:00
drdev
b1d03a85d5 Tweak name and ID overlay 2014-05-25 14:53:29 +00:00
swordshine
5b0c83f65a - CNS: Added Grudge Keeper 2014-05-25 07:18:34 +00:00
swordshine
1366f05a8f - Update scripts 2014-05-25 04:50:05 +00:00
drdev
1b86b3f2c2 Tweak order of overlays 2014-05-25 04:44:29 +00:00
drdev
e6f9d68d8a Fix so shapes rotated too 2014-05-25 04:37:37 +00:00
drdev
3f287df7ca Improve appearance of outlined text 2014-05-25 04:12:59 +00:00
drdev
12b543ff37 Support displaying outlined name labels as needed 2014-05-25 04:06:54 +00:00
swordshine
548b02e9e4 - Update scripts 2014-05-25 03:54:05 +00:00
drdev
0c1beeb26d Make card id labels visible 2014-05-25 03:46:49 +00:00
drdev
ac37de0b5f Draw p/t overlay 2014-05-25 02:05:01 +00:00
drdev
20f72d324f Support showing certain card overlays 2014-05-24 22:08:35 +00:00
drdev
abc441fb01 Prevent auto-selecting card in image view when filters change 2014-05-24 20:13:38 +00:00
drdev
55bacc8f10 Improve display of group by combo box 2014-05-24 20:12:22 +00:00
drdev
bb0991a830 Scale radio button circle 2014-05-24 19:53:51 +00:00
drdev
59694962bc Fix Maven version issues 2014-05-24 19:50:46 +00:00
drdev
cc432ecc69 Allow deselecting image view item by tapping again
Change Creatures/Spells/Lands group by to "Default" to make it more concise
2014-05-24 19:44:24 +00:00
drdev
0163db63a6 Prevent highlighting reminder text in prompt magnify view 2014-05-24 19:32:13 +00:00
drdev
981e3ace7b Fix so buttons can be clicked while prompt magnify open 2014-05-24 19:28:36 +00:00
drdev
354ebfa7d9 More wrapping fixes 2014-05-24 19:05:43 +00:00
drdev
1ebd0628e9 Allow magnify view for prompt 2014-05-24 18:13:33 +00:00
drdev
4cab2d9ad7 Shrink font for game log on ViewWinLose 2014-05-24 17:56:22 +00:00
drdev
ed5626d5e6 Fix wrapping issue with reminder text 2014-05-24 17:53:06 +00:00
drdev
a6c300943c Use text renderer in log 2014-05-24 17:24:27 +00:00
drdev
bb69fd26da Support showing magnified view of ViewWinLose log when tapping on it 2014-05-24 17:19:15 +00:00
swordshine
eef787261a - Added Goblin Game and Menacing Ogre 2014-05-24 16:54:05 +00:00
swordshine
a4ee8d7b0a - CNS: Added Academy Elite, Dack's Duplicate, Deathreap Ritual, and Realm Seekers 2014-05-24 06:50:21 +00:00
drdev
3f47d54a93 Use rotation transform to render tapped cards so overlays can be rotated too 2014-05-24 05:30:12 +00:00
drdev
23a9621de7 Fix weird Ctrl+MouseWheel issue 2014-05-24 04:30:36 +00:00
drdev
3cafad02de Avoid taps being thrown out when fling animation has basically stopped 2014-05-24 04:21:20 +00:00
drdev
b178c37640 Make it so part of next card is visible in image view so it's more obvious if scrolling is needed 2014-05-24 04:10:07 +00:00
drdev
e91042d49a Prevent card panel being selected if finger not on rendered card 2014-05-24 04:00:52 +00:00
swordshine
56801c5032 - CNS: Added Coercive Portal and Council's Judgment 2014-05-24 03:55:15 +00:00
drdev
5ae465ede4 Fix issue with multiple selection list 2014-05-24 03:32:56 +00:00
drdev
d88c73d2c1 Fix so string only deck managers work ok 2014-05-24 03:27:39 +00:00
drdev
ebd079d205 Prevent wrap of view buttons 2014-05-24 02:21:04 +00:00
drdev
da34644021 Fix issue with view button alignment
Tweak height of player panels in players drop down
2014-05-24 02:12:36 +00:00
Krazy
712569cffe [maven-release-plugin] prepare for next development iteration 2014-05-23 21:11:25 +00:00
Krazy
07861bfd47 [maven-release-plugin] prepare release forge-1.5.18 2014-05-23 21:11:07 +00:00
Krazy
2372dce223 Removed debugging line. 2014-05-23 20:51:33 +00:00
drdev
68c4b49d8b Reverse order of players on drop down 2014-05-23 19:59:54 +00:00
drdev
b8b961f739 Implement simple players drop down 2014-05-23 19:55:19 +00:00
Krazy
a2546c33db Tweaked booster box generation, resulting in more variety. Added changes to the change log, finalizing it for release. 2014-05-23 19:01:13 +00:00
Chris
7eb9fb084d Added new card names to changes.txt.
Preparing the changes.txt file for the next beta build and release.
2014-05-23 12:22:01 +00:00
drdev
bad48d173d Implement AvatarSelector 2014-05-23 12:20:36 +00:00
drdev
5bf3759d16 Diable players tab and team combo boxes for now 2014-05-23 11:29:37 +00:00
drdev
3fc0e512ba Make DISABLED_COMPOSITE apply to all disabled objects
Disable players and variants combo boxes for now
2014-05-23 11:20:41 +00:00
drdev
87eedb94cc Disable buttons on home screen for unimplemented functionality 2014-05-23 11:10:26 +00:00
drdev
849e7acbf3 Fix some scaling issues 2014-05-23 11:05:30 +00:00
drdev
69d016ce7a Standardize checkbox drawing 2014-05-23 01:36:04 +00:00
drdev
508293e561 Fix FOptionPane icon size at higher resolutions 2014-05-23 01:26:50 +00:00
drdev
31a6bf16cc Support zoom in image view 2014-05-23 00:42:42 +00:00
drdev
cf8efce2f0 Fix default selection of seemingly random card 2014-05-23 00:24:54 +00:00
drdev
d074a5ff38 Fix image view selection 2014-05-22 23:58:07 +00:00
swordshine
013e291321 - Fixed Call to the Kindred 2014-05-22 11:35:23 +00:00
swordshine
7095cdda62 - CNS: Added Grenzo, Dungeon Warden, Muzzio, Visionary Architect, and Treasonous Ogre 2014-05-22 05:03:42 +00:00
swordshine
0b8c417b33 - Fixed Urza's lands 2014-05-22 04:02:22 +00:00
drdev
5a1bf1205d Fix selection in image view 2014-05-22 02:47:51 +00:00
drdev
5d576ad315 Show selected card on top 2014-05-22 02:24:24 +00:00
drdev
ddff18bf29 Fix issue when collapsing group 2014-05-22 02:16:28 +00:00
swordshine
f67ea4a7f0 - Fixed TwoPilesEffect 2014-05-22 01:43:02 +00:00
excessum
a2102d4a4a - Replaced AiAttackController.shouldThisAttack() with ComputerUtilCard.doesSpecifiedCreatureAttackAI() that takes AI aggressiveness into account 2014-05-21 12:23:48 +00:00
drdev
56a4006ce4 Start working on input support for ImageView 2014-05-21 04:04:33 +00:00
drdev
7d2504306e Fix layout of image view 2014-05-21 03:19:43 +00:00
swordshine
66ee308ef9 - Fixed UntapUpto 2014-05-20 06:07:07 +00:00
Sloth
5a0031e4cc - Added a hard version of the Brother Voodoo quest opponent. 2014-05-20 05:54:15 +00:00
swordshine
7c173076d0 - CNS: Added Drakestown Forgotten and Scourge of the Throne 2014-05-20 05:10:34 +00:00
drdev
696c0ed0c2 Support drawing group headers 2014-05-19 17:19:19 +00:00
drdev
5c95d2f5db Make options panel work for image view 2014-05-19 17:07:40 +00:00
drdev
04b67d9b1c Fix so card back not shown for cards in dialog 2014-05-19 15:57:59 +00:00
drdev
777c275715 Add a minimum width to Log 2014-05-19 15:41:31 +00:00
drdev
61fbfa4bf8 Fix scaling of FOptionPane icon 2014-05-19 15:36:48 +00:00
Chris
619872cd52 Added new card names to changes.txt. 2014-05-19 14:37:50 +00:00
swordshine
833d944f14 - CNS: Added Plea for Power, Selvala's Charge, and Split Decision 2014-05-19 13:00:09 +00:00
swordshine
933488f9e9 - CNS: Added Brago's Representative 2014-05-19 06:00:43 +00:00
swordshine
9e2faccccd - Fixed Rampaging Baloths 2014-05-19 02:25:52 +00:00
drdev
1d55df335f Fix so card stacks work properly so newer cards appear on top and tapping the same land multiple times will tap lands under it automatically 2014-05-18 16:58:17 +00:00
drdev
0543a2a06d Prevent cards scrolling off screen after zooming 2014-05-18 12:31:59 +00:00
drdev
91d0c89b8a Support selecting cards further back in stack if tapped card not selectable 2014-05-17 21:38:41 +00:00
drdev
1baf8009b0 Prevent mana pool zooming 2014-05-17 20:47:20 +00:00
drdev
3d32f868a1 Improve horizontal zoom accuracy 2014-05-17 20:37:15 +00:00
drdev
1e5986e0ac Fix zoom focal point issue 2014-05-17 18:45:06 +00:00
drdev
10c48cfcf8 Improve zoom support to zero in on focal point 2014-05-17 18:10:21 +00:00
drdev
d19aa2c88a Prevent scrolling in opposite direction of main finger direction when dealing with multiple scroll panes 2014-05-17 16:24:30 +00:00
excessum
08039be686 - Added AI for Pongify and Rapid Hybridization that compares the token's value to the destroyed target 2014-05-17 08:48:44 +00:00
excessum
cb46b9c0c3 - Changed TokenAi.spawnToken() into a static method for easier usage 2014-05-17 08:40:15 +00:00
excessum
60c427ed25 - Allow AI to create tokens in response to sacrifice effects to protect more valuable targets 2014-05-17 03:05:36 +00:00
Sloth
fb9f440a4c - Improved declareAttackers AI function. 2014-05-16 16:50:58 +00:00
swordshine
72e5118a73 - Added Wall of Shadows 2014-05-16 13:38:40 +00:00
Sloth
0bc30e08ad - Added the medium quest deck Brother Voodoo 2 (by Nordos). 2014-05-16 13:38:34 +00:00
Sol
6a2d79b29d - Fix for Convoke basically allowing Users to tap any cards (even opposing cards) to generate Convoke mana. 2014-05-16 02:02:44 +00:00
swordshine
30d48b17e0 - Fixed Yare 2014-05-16 00:54:00 +00:00
swordshine
1cc02b58c1 - Conspiracy: Added Marchesa, the Black Rose 2014-05-15 09:01:32 +00:00
swordshine
8b33b78831 - Fixed two cards 2014-05-15 05:22:57 +00:00
drdev
91639c7d4f Fix press rendering 2014-05-15 02:45:13 +00:00
Krazy
d7f1f6e6e0 Mythic rare card generator now returns null for sets without mythic rare cards. This is used to fix win streak rewards. 2014-05-15 00:48:48 +00:00
drdev
dd4e2e5e29 Fix minor issue with zoom 2014-05-14 23:16:41 +00:00
drdev
7eddd9754e Fix zoom amount 2014-05-14 23:08:07 +00:00
drdev
b14dbe0f1a Fix checkmark rendering 2014-05-14 22:51:28 +00:00
drdev
147a78c176 Fix setting layout for higher resolutions 2014-05-14 22:40:30 +00:00
swordshine
eb0cdb0486 - Fixed Heliod's token image 2014-05-14 10:52:00 +00:00
Sloth
4d50be74c3 - Updated some AI SVars. 2014-05-14 10:09:06 +00:00
swordshine
68abe338fc - Conspiracy: Added Tyrant's Choice 2014-05-14 05:19:02 +00:00
drdev
9efcac2be7 Support zooming field 2014-05-14 04:04:48 +00:00
drdev
6a09c02327 Support scrolling and zooming with mouse wheel in desktop 2014-05-14 03:05:57 +00:00
swordshine
c04f226bd5 - Fixed Seshiro the Anointed Avatar 2014-05-14 02:53:56 +00:00
drdev
f072840db2 Prevent crash when selecting cards for cleanup 2014-05-14 01:38:35 +00:00
drdev
d4c05b46ed Reduce vibrate on long press further
Add vibrate effect when you lose life
2014-05-14 01:27:21 +00:00
drdev
a311f5e4b1 Reduce long press delay further and decrease vibrate time 2014-05-14 01:13:01 +00:00
drdev
0a8d2303e1 Reduce long press delay and vibrate when it's successful 2014-05-14 01:03:30 +00:00
drdev
51670f1144 Remove menu button 2014-05-14 00:14:16 +00:00
drdev
499ae40026 Prevent showing menu if overlay open 2014-05-14 00:03:24 +00:00
drdev
ce0eb099ee Implement Back and Menu key support 2014-05-13 23:48:01 +00:00
drdev
7b181fa846 Support zooming card via long press 2014-05-13 23:28:44 +00:00
Chris
22ea91dbc5 Added new card names to changes.txt. 2014-05-13 22:17:38 +00:00
swordshine
d802a4c8aa - Hum of the Raidx is ready for multiplayer 2014-05-13 05:19:11 +00:00
swordshine
7a932e4147 - Fixed spell's converted mana cost when that spell contains X cost and is no longer on the stack 2014-05-13 04:53:40 +00:00
Krazy
42e1a875ed Really fixed booster box prices this time. 2014-05-13 03:54:26 +00:00
drdev
b949f4e5b2 Improve previous fix 2014-05-13 03:49:14 +00:00
drdev
816cdcbb8c Fix details border size 2014-05-13 03:32:16 +00:00
drdev
85355aefb2 Allow showing card details in dialog 2014-05-13 03:25:45 +00:00
drdev
16c8b33cde Ensure stack wide enough on narrower displays 2014-05-13 02:56:27 +00:00
drdev
b50af5269a Remove Combat tab and right separator from Stack 2014-05-13 02:46:58 +00:00
drdev
aafc4dd4a0 Prevent activating unplayable abilities 2014-05-13 02:30:19 +00:00
excessum
3662440e23 - Allow AI to animate creatures in response to sacrifice effects to protect more valuable targets 2014-05-13 02:15:10 +00:00
drdev
584097f3f0 Increase default font size of SpellAbility ListChooser 2014-05-13 02:02:21 +00:00
drdev
343af70af9 Refactor so single tap selects cards 2014-05-13 02:00:41 +00:00
drdev
35fa0e3b63 Fix field separator 2014-05-13 01:42:10 +00:00
swordshine
7a8b1d52ed - Fixed Voracious Cobra's description 2014-05-13 00:30:10 +00:00
Krazy
6b72ccee66 Fixed some booster box prices. 2014-05-12 17:16:42 +00:00
drdev
c6a0a03262 Improve height of match screen menu bar 2014-05-11 20:53:05 +00:00
drdev
9a2b0c1657 Fix card highlight thickness 2014-05-11 20:42:43 +00:00
drdev
3ea7b8a9ff Fix field separator position 2014-05-11 20:38:17 +00:00
drdev
a9f99af688 Make field separator thicker at higher resolutions 2014-05-11 20:35:03 +00:00
drdev
36230e137e Revert previous commit 2014-05-11 20:30:27 +00:00
drdev
8aaa61a044 Flip info tab image and label for top panel 2014-05-11 20:26:08 +00:00
drdev
1c1de67f32 Improve display of phase markers and info tabs at higher resolution 2014-05-11 20:16:44 +00:00
drdev
4af6e5224e Catch file not found errors better 2014-05-11 18:17:34 +00:00
Krazy
343c19a588 Fixed win streak bonuses trying to choose mythic rares for sets that do not have them. 2014-05-11 16:34:12 +00:00
drdev
e90fcc0fd3 Tweak some scaling for higher resolutions 2014-05-11 15:15:04 +00:00
swordshine
a8545035c7 - Fixed Battlefield Thaumaturge not reducing cost of Polymorphous Rush 2014-05-11 14:22:35 +00:00
excessum
47c455a967 - Tweak to 25825 to check for regeneration shields and fix useRemovalNow() 2014-05-11 13:56:15 +00:00
swordshine
e6d6daff74 - Added Guardian Beast 2014-05-11 11:39:29 +00:00
swordshine
99378ea949 - Minor oracle updates 2014-05-11 07:00:51 +00:00
swordshine
156bc6fa85 - Update mtg-data
- Update Reconnaissance according to the errata
2014-05-11 06:42:05 +00:00
excessum
6f555670c2 - Allow AI to use ChangeZone effects against a blocker before trying to bounce its own attacker. Ensure that the AI will use its removal on a blocker if it can save an attacker 2014-05-11 02:54:48 +00:00
drdev
ad907512bc Fix min button width on option pane 2014-05-10 23:35:56 +00:00
drdev
7113870546 Fix Start button size 2014-05-10 23:27:18 +00:00
drdev
0934e1e831 Improve scaling for certain UI elements 2014-05-10 23:20:30 +00:00
drdev
4f59dfd0b8 Code cleanup 2014-05-10 22:20:50 +00:00
drdev
abd337a4f8 Improve scaling for higher resolutions 2014-05-10 22:11:26 +00:00
drdev
490f6ae4d2 Add libgdx-freetype.so 2014-05-10 18:48:15 +00:00
drdev
68a356f5b2 Use OpenGL2 for Android so images don't need dimensions that are powers of 2 2014-05-10 18:31:11 +00:00
drdev
9137f883dc Use android compatible method for loading and item manager preferences 2014-05-10 18:11:42 +00:00
drdev
020fb47c5e Use android compatible method for loading and saving deck preferences 2014-05-10 17:38:57 +00:00
drdev
81f8219d59 Use android compatible method for loading and saving card preferences 2014-05-10 17:27:37 +00:00
swordshine
4250b8eafb - Fixed Hagra Diabolist 2014-05-10 13:51:08 +00:00
swordshine
b2ba987fe3 - Converted Imperial Mask for multiplayer 2014-05-10 12:25:09 +00:00
Sloth
9b04597c54 - Added the hard quest opponent Pyro 3. 2014-05-10 11:57:40 +00:00
swordshine
69054d33d8 - Fixed Treetop Defense 2014-05-10 11:22:30 +00:00
swordshine
cdfa06f25a - Converted Gift of Immortality to delayed trigger 2014-05-10 11:12:50 +00:00
swordshine
259a64f6b4 - Fixed Sacttering Stroke 2014-05-10 10:06:19 +00:00
swordshine
676bd996c5 - Fixed one more card 2014-05-10 07:27:46 +00:00
excessum
e382b29212 - Improved AI logic when attacking by applying AiBlockController logic block for each attacker 2014-05-10 06:28:01 +00:00
swordshine
b37be577cf - Fixed Mana Drain and friends 2014-05-10 06:23:30 +00:00
Sloth
fb41eb5992 - Improved DestroyAllAi (AI will now check if the human can kill the ai next turn). 2014-05-09 16:03:52 +00:00
drdev
97c5354889 Flesh out XML read and write utility methods 2014-05-09 04:06:31 +00:00
swordshine
b100812ed0 - Converted hardcoded EOT delayed trigger in CopyPermanentEffect 2014-05-09 03:53:51 +00:00
swordshine
9bef4762e1 - Update scripts 2014-05-09 01:52:26 +00:00
drdev
0c6c1f897c Refactor sound support so it can work on both desktop and android 2014-05-09 01:08:52 +00:00
drdev
82f121a7ef Switch from Gdx.files.local to Gdx.files.absolute
Ensure directories created for data and cache
2014-05-08 18:02:47 +00:00
drdev
3926826bcb Refactor so error handler setup earlier 2014-05-08 17:35:22 +00:00
Krazy
d4d6592d53 A few minor tweaks for wording and calculating when rewards are awarded. (Ex: Jackpot is now awarded on the 80th win, not the 81st.) 2014-05-08 17:30:20 +00:00
drdev
bf64e177e7 Rename forge.view to forge.app
Alter external storage location
2014-05-08 15:07:28 +00:00
drdev
7a10e183ce Add support for debug logging
Tweak assets path for android
2014-05-08 13:26:25 +00:00
swordshine
ae382760d0 - Fixed Bronze Horse
- Fixed a crash when Precursor Golem is targeted with an Electrolyze
2014-05-08 04:56:36 +00:00
drdev
e03b435154 Fix mobile Maven build 2014-05-08 04:23:08 +00:00
swordshine
c0c0186a4b - Prevent remembering unchanged cards in ChangeZoneEffect to fix Vanish into Memory 2014-05-08 01:37:44 +00:00
swordshine
c3086b844f - Fixed Argothian Wurm by Xyx 2014-05-08 01:08:00 +00:00
swordshine
7a4a562562 - Attempt to fix changing targets of wrapped abilities 2014-05-07 14:04:49 +00:00
swordshine
dad0b7821b - Fixed re-suspend cards 2014-05-07 13:44:24 +00:00
swordshine
6516686fb6 - Fixed Dark Supplicant 2014-05-07 12:55:58 +00:00
swordshine
b2064cb0f0 - Fixed Takklemaggot 2014-05-07 12:51:44 +00:00
swordshine
b7d3630d6a - Fixed Cruel Feeding by Zirbert 2014-05-07 04:08:39 +00:00
drdev
66e9c32ae4 Fix project setup 2014-05-07 03:57:03 +00:00
swordshine
2685419a05 - Attempt to fix another crash based on getAbility of RepeatEachEffect (Experimental Kraj) 2014-05-06 01:57:14 +00:00
swordshine
74504f22fe - Attempt to fix a crash when cloned cards activate a delayed trigger effect. (e.g. Clone(AEtherling) activates the first ability) 2014-05-05 14:15:17 +00:00
swordshine
96174c8972 - Update two scripts 2014-05-05 09:59:11 +00:00
swordshine
c91f1854ea - Fix Premature Burial so it works when casting from other's hand 2014-05-05 05:43:29 +00:00
swordshine
429c340166 - Fixed Panoptic Mirror 2014-05-05 04:32:45 +00:00
swordshine
01d24e1e37 - Attempt to fix cards like It that Betrays 2014-05-05 04:05:28 +00:00
swordshine
89cf695545 - Added Heartwood Storyteller Avatar 2014-05-05 02:04:25 +00:00
drdev
8e11cde662 Show scrollbar as needed for Players pane 2014-05-05 01:14:13 +00:00
drdev
511875929f Update CHANGES.txt 2014-05-04 21:27:27 +00:00
drdev
4ba4533c61 Show storm count in card detail pane for storm cards 2014-05-04 21:25:00 +00:00
drdev
4aa8d57647 Support using TextRenderer to calculate text bounds 2014-05-04 19:05:59 +00:00
drdev
d8eaea4c00 Fix so visibility of Dev menu is set based on DEV_MODE flag 2014-05-04 18:44:16 +00:00
drdev
c2a75f9bce Fix so DEV_MODE flag updated appropriately 2014-05-04 18:27:18 +00:00
drdev
9b4af1a58b Ignore Thumbs.db 2014-05-04 16:41:30 +00:00
drdev
aa7aa7ac95 Support special card and SpellAbility rendering for DualListBox 2014-05-04 16:24:32 +00:00
swordshine
531fefb993 - Added Mana Web 2014-05-04 12:01:08 +00:00
Krazy
effd8cb2c8 Adjusted credit reward for life total differences. 2014-05-04 06:20:26 +00:00
drdev
f2ff5cc850 Fix so clicking on card detail pane properly flips cards 2014-05-04 05:10:48 +00:00
drdev
cdf8dd84ee Refactor so mobile game can determine whether card can be flipped 2014-05-04 05:01:47 +00:00
Krazy
b869d5732f Fixed a spacing problem. 2014-05-04 04:49:32 +00:00
Krazy
c7e4eb83ab Fixed creatures row being created when no creatures were on the field while creature stacking is enabled. 2014-05-04 04:47:24 +00:00
drdev
cf85a22492 Support using FDeckViewer to show deck list for Gui player from match screens of mobile and desktop games 2014-05-04 04:41:45 +00:00
Krazy
056c8d0438 Added optional (default off) stacking for creatures in the same way that artifacts, enchantments, and lands are stacked. 2014-05-04 04:34:18 +00:00
drdev
d5eb533906 Support rendering items for Card objects more accurately 2014-05-04 03:53:22 +00:00
drdev
8f5d27e24b Improve card zoom rendering size 2014-05-04 02:59:32 +00:00
drdev
7904f2bb76 Improve quality of card art by eliminating edges and making size consistent 2014-05-04 02:06:03 +00:00
drdev
3307455c7d Prevent card art flickering in list 2014-05-04 01:26:41 +00:00
drdev
2294d49e6a Support rendering cards in ListChooser 2014-05-04 01:10:29 +00:00
drdev
dcbec88fd7 Refactor ListChooser to support different renderers based on list type 2014-05-04 00:29:39 +00:00
Chris
1434c5ebb2 Added new card names to changes.txt. 2014-05-03 22:11:08 +00:00
drdev
62cb0c105f Remove gen folder from SVN 2014-05-03 21:40:12 +00:00
drdev
5c7c13c106 Remove gen folder from SVN 2014-05-03 21:38:42 +00:00
drdev
b742d07341 Add check box menu items and support for tapping stack item to zoom or select options 2014-05-03 21:17:39 +00:00
drdev
5abecfe77d Improve wrapping in and around symbols 2014-05-03 20:23:11 +00:00
drdev
72fa4ed80f Support wrapping in DualListBox 2014-05-03 17:41:39 +00:00
drdev
efbeb6dcdb Support certain match screen shortcuts 2014-05-03 17:38:57 +00:00
drdev
4c3014e49e Add basic key modifier shortcuts to FTextField 2014-05-03 17:32:47 +00:00
drdev
3bfc8a926e Support using Escape to cancel card selection 2014-05-03 17:21:11 +00:00
drdev
774dafc813 Make DualListBox key handling match desktop game 2014-05-03 17:12:01 +00:00
drdev
258f1d52ba Fix key events on DualListBox to prevent hiding without selecting anything 2014-05-03 17:10:59 +00:00
Krazy
f9d9bf6484 Fixed Enchanted Evening and other similar cards. 2014-05-03 17:06:20 +00:00
drdev
aaa398cedc Prevent crash when pressing Enter or Space on ListChooser 2014-05-03 17:03:52 +00:00
drdev
83add199c1 Handle disabled buttons for sake of certain keyboard shortcuts 2014-05-03 16:58:57 +00:00
drdev
946b7bfacf Add more keyboard shortcuts for navigating screens 2014-05-03 16:55:27 +00:00
drdev
d5d5ab0364 Tweak keyDown logic at top level 2014-05-03 16:43:28 +00:00
drdev
144e02eb1a Fix key input in and around combo boxes 2014-05-03 16:42:28 +00:00
drdev
dcf6bd9c1e Hook shortcut handlers for Match screen, FButton, and FOptionPane 2014-05-03 16:38:26 +00:00
drdev
8dbe2887ff Support starting key input without a touch event happening first 2014-05-03 15:57:04 +00:00
drdev
bddfff41f2 Auto-focus ListChooser search field on desktop
Increase width of buttons on DualListBox
Make border on ListChooser show up on certain themes
2014-05-03 15:36:56 +00:00
drdev
1c9edb4380 Fix custom select screen 2014-05-03 15:11:26 +00:00
drdev
b9dafed0ea Get DualListBox fleshed out 2014-05-03 15:07:10 +00:00
drdev
4a392fd465 Fix alignment of prompt in FOptionPane 2014-05-03 14:24:14 +00:00
swordshine
e933ecc70c - Added three bid life cards 2014-05-03 12:54:33 +00:00
swordshine
d4783e1b89 - Update Storm count in Players panel 2014-05-03 08:37:54 +00:00
excessum
37a7f291f1 - Check for intrinsic regenerate abilities before using targeted regenerate 2014-05-03 03:55:00 +00:00
drdev
4fd2df0093 Add support for checking for assets when opening android app 2014-05-03 01:40:06 +00:00
drdev
1729ce8a02 Support overriding location of user and cache dirs for android 2014-05-02 21:18:01 +00:00
Krazy
92749f64f8 Removed redundant version line from android pom. 2014-05-02 15:13:54 +00:00
swordshine
79db3bde17 - Attempt to fix an SBA issue (http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=14307&start=120#p151485) 2014-05-02 13:33:05 +00:00
swordshine
420e804a07 - Fixed Tribute 2014-05-02 12:48:40 +00:00
swordshine
eba7491804 - Fixed Nivmagus Elemental so it can exile ciphered spells 2014-05-02 12:35:17 +00:00
swordshine
7b4d766442 - Fixed Cultivate and friends so they only shuffle the library once. 2014-05-02 07:12:54 +00:00
Maxmtg
bb9c7dcec7 moved aux gui classes to a dedicated package to keep the root package clean. 2014-05-02 05:59:47 +00:00
Maxmtg
2c14552c7f package to hold aux gui classes 2014-05-02 05:57:55 +00:00
swordshine
bc58bd6de5 - Fixed Crown of Vigor 2014-05-02 05:49:51 +00:00
Maxmtg
74f9a5f722 Detach network code from game and gui. 2014-05-02 05:40:50 +00:00
swordshine
876d333498 - Update scripts 2014-05-02 05:34:52 +00:00
swordshine
6cd67b8012 - Fixed Lethal Vapors 2014-05-02 04:57:10 +00:00
drdev
0ed941b09a Increase allowed memory for build 2014-05-02 02:58:26 +00:00
Krazy
d37cc14fcb More android pom tweaks. 2014-05-02 01:31:32 +00:00
Krazy
cf79591985 Added a much higher memory allowance for Android builds. 2014-05-01 23:39:06 +00:00
Chris
86bdec3767 Attempt to fix forge-gui-desktop/src/main/config/forge.sh 2014-05-01 15:10:12 +00:00
swordshine
b143450d97 - more cards ready for multiplayer games
- Fixed a LKI issue when using RepeatEach effect (for each XX destroyed/exiled this way, its controller ...)
2014-05-01 14:18:01 +00:00
swordshine
5a671223b7 - Fixed a bug in CostTapType 2014-05-01 10:53:21 +00:00
swordshine
77b9021145 - Update HumanCostDecision for Sage of Hours 2014-05-01 09:30:24 +00:00
swordshine
5c7b881c49 - Update clash effects for multiplayer games 2014-05-01 08:32:24 +00:00
swordshine
49d7aa2b03 - Converted Vanish into Memory 2014-05-01 08:04:50 +00:00
swordshine
c924e0b760 - fix two cards containing delayed triggers 2014-05-01 07:06:51 +00:00
excessum
01c2b528b1 - Removed obsolete code from ProtectAi 2014-05-01 05:06:09 +00:00
excessum
8bcbc00fc4 - Remove invalid targets after resolved Shroud/Hexproof/Protect from list of threatened objects to prevent duplicate saves 2014-05-01 04:10:05 +00:00
Sol
e1f851360f - Adding a nullcheck for the PumpAI Targeting 2014-05-01 03:56:41 +00:00
Krazy
dc109993da Testing specifying more memory for the android build process specified in the pom. 2014-05-01 03:43:44 +00:00
swordshine
65454ef540 - Attempt to fix a bug so triggered abilities check the timestamps of cards before resolving 2014-05-01 02:52:39 +00:00
excessum
6192e66a00 - Allow AI to use pump-all spells/abilities as interrupts to opponent's removal. 2014-05-01 02:47:59 +00:00
excessum
b2fb1ecd05 - Added check in pumpAgainstRemoval() to prevent illegal number of targets 2014-05-01 02:16:13 +00:00
excessum
e1c791eabd - Added AI support for multi-target pumps as interrupts to opponent's removal 2014-05-01 02:13:03 +00:00
Sloth
0127161620 - Added infinite loop protection to prevent cases like AI using Sky Hussar. 2014-04-30 18:59:53 +00:00
Krazy
75d4184905 Adjusted credit reward calculation for overkill/life gain.
Commit message for the previous commit: Fixed a bug that would cause an infinite loop in the AI code for choosing tap/untap targets.
2014-04-30 18:26:25 +00:00
Krazy
e711c1bca1 2014-04-30 17:11:11 +00:00
Chris
d3a3ef878e Added new card names to changes.txt. 2014-04-30 14:45:12 +00:00
excessum
6e0a528c41 - check for regeneration shields when using curses to deal lethal damage 2014-04-30 14:11:07 +00:00
excessum
85883108ca - Allow AI to use pump spells/abilities as interrupts to opponent's removal. Added support for curses to predictThreatenedObjects() 2014-04-30 13:28:41 +00:00
swordshine
521ab9c3fd - Fixed AnimateAllEffect so it update card state now 2014-04-30 13:19:06 +00:00
swordshine
3185143f9f - Conspiracy: Added Brago, King Eternal 2014-04-30 08:45:37 +00:00
drdev
679a29fdfd Improve layout of DualListBox 2014-04-30 00:45:33 +00:00
Krazy
7a7f7fca5b Players can now win credits for overkill or gaining lots of life, as these strategies tend to make the player miss out on bonus credits for fast games. Life total differences of up to 2550 will award 1 credit for every 10 life over 50. Also increased cost of new quest item. 2014-04-29 19:32:27 +00:00
Krazy
5d77df7941 Small update to android pom to keep Eclipse from complaining when using ADT. 2014-04-29 17:07:41 +00:00
Sloth
11799fd2ca - Fixed AI not targeting with Armistice. 2014-04-29 06:56:24 +00:00
Sloth
cb18d42769 - Added DGM to the Ravnica world. 2014-04-29 06:43:58 +00:00
drdev
2394b8fb19 Prevent crash when resolving Ponder on mobile game 2014-04-29 04:42:53 +00:00
drdev
21a1c26cc7 Implement DualListBox for mobile 2014-04-29 04:28:57 +00:00
Krazy
96b9b3da00 Finished up basic android .apk building support. See forum for details. 2014-04-29 03:49:11 +00:00
drdev
f4c1b90e34 Fix stack description of Ponder 2014-04-29 03:12:02 +00:00
drdev
a3800f7835 Commit mobile maven prefs 2014-04-29 02:38:54 +00:00
Krazy
da420eeb68 Part two of the previous commit. Because SVN is not Git. 2014-04-29 01:57:31 +00:00
Krazy
b59a0ef265 Added an expensive quest item that increases the variety of boosters when awarded for wins. 2014-04-29 01:56:40 +00:00
drdev
b2bc1975ec Remove unused assets files 2014-04-29 01:38:32 +00:00
drdev
eb6e6d9b80 Fix padding for settings screen 2014-04-29 00:58:29 +00:00
drdev
44711aca4e Update stack to use same colors as card detail border 2014-04-28 19:42:48 +00:00
Krazy
f1f07e7c92 Added rewards for maintaining large win streaks in quest mode. 2014-04-28 19:18:34 +00:00
drdev
f770986aa9 Fix so multiple abilities can be selected via menu in desktop app
Remove straggler java.awt reference in forge-core
2014-04-28 18:43:03 +00:00
asepetci
7ffbaf9a36 Updated draft rankings 2014-04-28 07:49:39 +00:00
drdev
3e76589214 Add setting for scaling image larger 2014-04-28 03:49:22 +00:00
drdev
75ff9e5f97 Fix FList scroll into view logic 2014-04-28 03:41:58 +00:00
drdev
22afad3eaf Support tapping art to show zoom/detail 2014-04-28 03:33:36 +00:00
drdev
02b0fd2d63 Tweak item manager filter layout 2014-04-28 03:04:36 +00:00
drdev
769e5dee4b Reduce height of filters 2014-04-28 02:11:20 +00:00
drdev
d6c8e794cf Improve card list rendering 2014-04-28 01:58:58 +00:00
Krazy
a1575b6399 Quick fix for building forge-gui-mobile-dev. forge-gui-android incomplete still. 2014-04-28 01:23:55 +00:00
Sol
32fc73802d - Routing Flashback button through the InputProxy to attempt fix for Oracle of Mul Daya/trigger issue 2014-04-28 00:51:24 +00:00
drdev
2592002bcf Fix so forge-gui-mobile compiles 2014-04-27 22:36:29 +00:00
drdev
e6efda2716 Remove remaining references to java.awt from forge-gui and forge-gui-mobile 2014-04-27 22:07:12 +00:00
swordshine
8858249b69 - Fixed Necra Sanctuary 2014-04-27 06:33:59 +00:00
swordshine
a2251f92cc - Fixed Knowledge and Power 2014-04-27 06:04:12 +00:00
drdev
9a39a4e80e Work on card list rendering 2014-04-27 05:10:36 +00:00
Krazy
65211b16cd Reverted the change that turned forge-gui-mobile into a complete module. It was causing problems building the desktop version of the game. Will explore real fixes later. 2014-04-27 05:10:16 +00:00
Krazy
73cf1096bb Set up the stuff to build the game for Android. See the Maven module forum topic for details. 2014-04-27 02:22:24 +00:00
excessum
811d59ed24 - Fixed bug with extra targets when activating Polukranos, World Eater 2014-04-27 02:18:41 +00:00
drdev
f34498277b Support toggling favorite decks 2014-04-27 01:20:38 +00:00
drdev
8b6d184027 Tweak set label to appear in proper font 2014-04-27 01:02:05 +00:00
drdev
384181c8ce Increase set label padding for DeckManager list items 2014-04-27 00:55:23 +00:00
drdev
5ebb06c1b1 Fix icon/text alignment on FLabels 2014-04-27 00:14:38 +00:00
drdev
76f03c61b6 Improve deck manager list view some more 2014-04-26 23:57:54 +00:00
moomarc
39a204c5ba - Uploaded booster box images and added url list
- Uploaded and updated urls for JOU booster images
- Uploaded and updated urls for BNG token images
- Updated scripts for BNG token generators with set specific images
2014-04-26 23:23:20 +00:00
drdev
5bafe18d8d Improve deck manager item rendering 2014-04-26 22:26:04 +00:00
Chris
4338318b91 Merged Xitax's fixed fatpack-images.txt file. 2014-04-26 20:53:00 +00:00
Sloth
34b40f1fd4 - Two small text fixes. 2014-04-26 18:45:48 +00:00
Sloth
ddab7674be - Temporary fix for lands played from outside the hand having triggers fired delayed (i hope someone knows some more about inputs than me). 2014-04-26 18:41:07 +00:00
Chris
7d797219a9 Cleared out the changes.txt file, now ready for new material. 2014-04-26 12:55:44 +00:00
swordshine
6334441d88 - Update scripts for Conclave's Blessing 2014-04-26 08:31:18 +00:00
swordshine
deae8f7a12 - Fixed Erayo and Ichneumon Druid 2014-04-26 08:18:11 +00:00
swordshine
7b5dd899cf - Update scripts 2014-04-26 05:52:17 +00:00
drdev
e3ba07c23a Support center and right aligned text and increase maximum prompt font size 2014-04-26 05:10:06 +00:00
excessum
c044332de1 - Prevent AI from using Nature's Panoply with zero targets 2014-04-26 05:08:25 +00:00
drdev
d1ea863a91 Support clipping text if needed 2014-04-26 04:25:06 +00:00
drdev
4cd91d3b46 Support vertically centering rendered text 2014-04-26 04:15:11 +00:00
drdev
2f28001b9f Show ??? as name for face-down cards 2014-04-26 03:41:33 +00:00
drdev
7ce2759742 Ensure space before start of reminder text is included 2014-04-26 03:30:06 +00:00
drdev
4296805359 Fix reminder text rendering 2014-04-26 03:25:26 +00:00
drdev
183752c9ae Tweak symbol size 2014-04-26 03:05:13 +00:00
drdev
af55c75f4f Support rendering symbols in card text 2014-04-26 02:56:26 +00:00
swordshine
4098a6b873 - Update scripts for Sedge Sliver 2014-04-26 02:48:10 +00:00
Chris
bdd2e3ad16 Add fixed forge.sh file. 2014-04-26 00:24:26 +00:00
Chris
ecf88d2dc4 Delete bad forge.sh file. 2014-04-26 00:22:36 +00:00
Krazy
82fd3bdae1 Fixed a typo 2014-04-25 23:46:20 +00:00
Chris
06c8293341 [maven-release-plugin] prepare for next development iteration 2014-04-25 15:55:15 +00:00
Chris
50d849a4ff [maven-release-plugin] prepare release forge-1.5.17 2014-04-25 15:55:03 +00:00
Chris
773ada0412 Preparing the changes.txt file for the next beta build and release. 2014-04-25 15:26:07 +00:00
Sol
5981ee1989 - JOU Oracle R-Z 2014-04-25 14:30:14 +00:00
Sol
44a13194c5 - JOU Oracle H-Q 2014-04-25 14:28:49 +00:00
Sol
50f9d39957 - Oracle for JOU A-G 2014-04-25 14:27:51 +00:00
Sol
a8d7fd69d9 - Renaming two misnamed scripts 2014-04-25 14:25:34 +00:00
Chris
f10a890beb [maven-release-plugin] prepare for next development iteration 2014-04-25 14:24:18 +00:00
Chris
18dccd6a98 [maven-release-plugin] prepare release forge-1.5.16 2014-04-25 14:24:05 +00:00
Chris
d1767cb425 Preparing the changes.txt file for the next beta build and release. 2014-04-25 13:37:08 +00:00
Chris
5afea2159f Added new card names to changes.txt. 2014-04-25 13:34:15 +00:00
Krazy
f7cb94a0f4 Fixed set typo in Fates Foreseen deck. 2014-04-25 01:42:49 +00:00
Krazy
bf6d84a954 Added JOU intro decks. 2014-04-25 01:38:52 +00:00
Krazy
ed8b8e68c1 Added card stacking for "other" cards. 2014-04-25 00:56:29 +00:00
Krazy
c1d794765e Fixed height of win streak label so that it doesn't get cut off. 2014-04-24 22:37:03 +00:00
Sloth
c8dc342616 - Updated some quest decks. 2014-04-24 16:32:38 +00:00
Sloth
dffdaad6b5 - Improved and fixed AI using Ashiok, Nightmare Weaver. 2014-04-24 16:12:14 +00:00
swordshine
84d93b7e41 - Fixed StackDescription of Exsanguinate 2014-04-24 13:00:11 +00:00
swordshine
9516f2a502 - Conspiracy: Added Magister of Worth 2014-04-24 12:54:39 +00:00
swordshine
a25fcb2f16 - Update scripts 2014-04-24 12:44:10 +00:00
Krazy
15f1edfbeb Added price for JOU booster box. 2014-04-24 04:45:31 +00:00
drdev
dc67f872e8 Work towards getting Android app to run 2014-04-23 22:02:51 +00:00
Sloth
34480385e8 - Fixed infinite loop caused by Ashiok. 2014-04-23 13:49:51 +00:00
swordshine
96b18b59bb - Update scripts 2014-04-23 12:53:13 +00:00
excessum
002f7d1d95 - Fixed bug with normal pump spells falling into useRemovalNow() 2014-04-23 12:42:45 +00:00
Chris
5a522b8e6b Added new card names to changes.txt. 2014-04-23 11:03:52 +00:00
swordshine
2b092d7444 - Update scripts 2014-04-23 02:38:56 +00:00
swordshine
a707250d33 - Remove keyword "CARDNAME can't attack if defending player controls an untapped" 2014-04-23 02:27:33 +00:00
drdev
dca3f4e89a Fix minor issue with ListChooser sizing 2014-04-23 02:17:14 +00:00
drdev
8b6d8a6bcb Fix minor issue with ListChooser sizing 2014-04-23 02:15:56 +00:00
drdev
9689efc1d1 Make more items able to show in ListChooser 2014-04-23 02:05:11 +00:00
swordshine
b932f37070 - Conspiracy: Added Dack Fayden 2014-04-23 00:24:09 +00:00
swordshine
69ee4a03d8 - Fixed Underworld Coinsmith 2014-04-23 00:20:05 +00:00
Krazy
310d34e357 Changed number of boosters in MMA boxes to 24 from 36. 2014-04-22 23:16:23 +00:00
Krazy
73fd1e29f1 Added optional large card viewers for use with high resolution card images. 2014-04-22 22:52:00 +00:00
Chris
b480b52bc0 Added new card names to changes.txt. 2014-04-22 13:44:20 +00:00
Sloth
48cd9250f9 - Added the JOU cards to trunk. 2014-04-22 12:46:47 +00:00
swordshine
3ac679ebb7 - Fixed a name 2014-04-22 12:13:38 +00:00
swordshine
7cec807a31 - JOU: Added Sightless Brawler 2014-04-22 11:25:51 +00:00
swordshine
e165b64199 - Updated edition and block data 2014-04-22 05:15:13 +00:00
swordshine
4463d883df - JOU: Added Daring Thief (there is an UI bug, see http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=6333&start=2835#p150788) 2014-04-22 05:12:41 +00:00
Krazy
3b4964ba4a Updated the ante rarity code. Previously, it would add both Rare and MythicRare rarities to the pool of choices, but it considers both interchangeable. This led to a large increase of Rare and MythicRare cards being chosen. The game now adds only one. 2014-04-22 03:34:37 +00:00
Krazy
8c884753e1 Separated credit report for previous wins from the base credit amount. 2014-04-22 02:03:44 +00:00
Chris
4c49df83fe Fixed the forge.command file in forge-gui-desktop/src/main/config/ and I can now build a widows-linux archive that will launch on a Mac via the forge.command file. 2014-04-22 00:23:10 +00:00
Chris
3f14d71f32 Added a fluff piece to the changes.txt file. 2014-04-21 14:59:52 +00:00
Chris
bee94bbc20 Added new card names to changes.txt. 2014-04-21 14:58:11 +00:00
swordshine
7a1097f5e9 - JOU: Added 4 black cards 2014-04-21 13:26:39 +00:00
swordshine
bcba7b7c3b - Fixed Biomantic Mastery 2014-04-21 06:41:57 +00:00
Krazy
c487103715 Adjusted wins per set unlocks preference limits. 2014-04-21 04:24:51 +00:00
Krazy
b1d4b53c55 Added quest preference for number of wins per set unlock. 2014-04-21 04:14:36 +00:00
swordshine
40483b9437 - Fixed filterListByType 2014-04-21 03:03:38 +00:00
swordshine
6c6d760f19 - Fixed Night // Day 2014-04-21 03:02:05 +00:00
drdev
ded19e2505 Support searching ListChooser dialog with lots of items 2014-04-21 01:58:14 +00:00
Krazy
879bc96d52 Updated booster box listing and added prices for all booster boxes. 2014-04-21 01:40:20 +00:00
drdev
d5620708d4 Support raising changed event 2014-04-21 00:52:52 +00:00
drdev
70fedb87df Support typing into text fields 2014-04-21 00:44:53 +00:00
swordshine
9f6e258acb - Update scripts 2014-04-21 00:30:36 +00:00
Krazy
7fddd89ca5 Somehow half the code wasn't included in the previous commit. This fixes that. 2014-04-21 00:16:56 +00:00
Krazy
dbe80258c0 Added Booster Boxes to the quest shop. Added option to open booster boxes and fat packs one booster at a time to the preferences (default off). Re-worked FatPack class to accommodate. CardListViewers are now tall enough to hold the entire contents of a booster pack (15 cards) without creating a scrollbar (a 14px height increase). 2014-04-20 23:26:20 +00:00
Krazy
61723676ed Added ability to toggle matching rarity for anted cards in the game's preferences. In the event that rarities cannot be matched, the game will fall back to the original system of choosing antes. 2014-04-20 21:15:37 +00:00
Krazy
d76588684f Fixes to the gui-desktop pom.xml to include previously missed files. 2014-04-20 20:03:21 +00:00
drdev
029e3d640a Support key input 2014-04-20 19:25:13 +00:00
Chris
fa83940583 Added new card names to changes.txt. 2014-04-20 18:58:55 +00:00
Krazy
288c5308a0 Updated DeckHintsTest.java to set the GuiBase interface before running tests, allowing it to complete successfully. 2014-04-20 17:58:47 +00:00
drdev
8fc7a560a7 Optimize FList rendering 2014-04-20 17:44:32 +00:00
excessum
5252609d7b - Allow AI to use removal as interrupts to opponent's pump/enchant. Removed a check for duplicate kills in DamageDealAi and added a TODO for a general duplicate removal algorithm in its place. Fixed a bug in PumpAi that prevents curses from being used when the stack is not empty. 2014-04-20 02:41:05 +00:00
Chris
64c167ae44 Now using KrazyTheFox's updated pom file. 2014-04-20 01:26:33 +00:00
drdev
b5c10f7acd Support tinting card detail boxes 2014-04-19 23:19:23 +00:00
drdev
b758129933 Support rendering set and rarity in details 2014-04-19 22:42:37 +00:00
Chris
d0e9599cc4 Added new card names to changes.txt. 2014-04-19 22:11:35 +00:00
drdev
cdb5440933 Improve and standardize rarity colors 2014-04-19 21:31:04 +00:00
drdev
5a4eccf604 Improve mana cost rendering 2014-04-19 17:59:10 +00:00
drdev
42767532ac Flesh out card details more 2014-04-19 16:10:04 +00:00
excessum
a4b41c94c2 - Allow AI to hold back removal based on chance instead of always using them when a suitable target is available 2014-04-19 05:19:29 +00:00
drdev
9654c025e6 Start fleshing out card details view 2014-04-18 03:21:53 +00:00
excessum
d1609866ff - Minor update to EffectAI to prevent negative "fight" logic from falling through to the random return in canPlayAI(). Prevent Polukranos activation from targeting shielded or creatures that can regenerate. 2014-04-18 03:15:27 +00:00
drdev
d8646997b0 Update desktop application to use new border colors 2014-04-18 02:55:33 +00:00
drdev
adb57bed8a Move card border color determination to utility class 2014-04-18 02:51:00 +00:00
drdev
42c04bdcdb Break out card detail formatting into shared utility class 2014-04-18 01:23:21 +00:00
drdev
f8d8d51957 Support keeping zoom/details open if mouse released with it open 2014-04-18 01:01:42 +00:00
Sloth
cd3caa920b - Updated the quest deck Dr No 3. 2014-04-17 13:21:58 +00:00
swordshine
277ba65f2d - JOU: Added Silence the Believers 2014-04-17 11:11:53 +00:00
Sloth
5159250da6 - Log entries of Replacement effects will now replace "CARDNAME" with the name of the card. 2014-04-17 10:56:53 +00:00
Sloth
4e4702db5d - Fixed ordering of AI spellability priorities. 2014-04-17 09:33:15 +00:00
swordshine
39194d7d80 - JOU: Added Desperate Stand and Disciple of Deceit 2014-04-17 06:39:16 +00:00
drdev
e0a9a8f467 Support show card zoom 2014-04-17 04:01:02 +00:00
swordshine
60d4b4a281 - JOU: Added Bearer of the Heavens, Harness by Force, and Hypnotic Siren 2014-04-17 01:48:31 +00:00
drdev
54cb352ce0 Support Zoom and Details options 2014-04-17 01:46:34 +00:00
drdev
7fba37ca36 Improve responsiveness 2014-04-17 00:13:04 +00:00
drdev
57bab78676 Make option text transparent when not pressed 2014-04-17 00:04:17 +00:00
drdev
2d56178cfc Support double tapping card to select first option 2014-04-16 23:06:54 +00:00
drdev
d5e4fb9fd6 Support highlighting options when dragging up 2014-04-16 22:45:13 +00:00
swordshine
d1deb9aef8 - JOU: Added Battlefield Thaumaturge and Crystalline Nautilus 2014-04-16 06:33:56 +00:00
swordshine
c06522480a - JOU: Added Godhunter Octopus 2014-04-16 04:18:23 +00:00
drdev
cc4d4965d7 Support dragging up to select ability 2014-04-16 04:15:20 +00:00
drdev
908a0ccfe9 Fix so selected card appears on top 2014-04-16 03:54:42 +00:00
drdev
b9a1556a2a Fix selection border for tapped cards 2014-04-16 03:43:18 +00:00
drdev
322079030f Support selecting which mana ability to use in advance 2014-04-16 03:37:30 +00:00
drdev
8c6095e65a Support selecting cards 2014-04-16 03:12:23 +00:00
Sol
98ef69eea1 - Updating format b/r lists 2014-04-16 00:47:19 +00:00
Chris
745aad5c99 Added new card names to changes.txt 2014-04-15 22:52:25 +00:00
Sloth
3cea12e3dc - NPE protection (Delayed Triggers have no Execute param). 2014-04-15 14:10:22 +00:00
excessum
ec9331ceb8 - Minor update to FightAI 2014-04-15 13:44:10 +00:00
excessum
3f0e238919 - Improved FightAI by considering regeneration shields and Heroic triggers that place +1/+1 counters 2014-04-15 13:12:52 +00:00
Sloth
4d9644fc77 - Fixed Tidewalker. 2014-04-15 09:56:05 +00:00
Sloth
d6ab10a98d - Fixed Mindclaw Shaman. 2014-04-15 09:45:45 +00:00
Sloth
e1f0fab2bc - Little fix in ProtectAI. 2014-04-15 09:30:27 +00:00
swordshine
b406d7382d - JOU: Added Eidolon of Rhetoric 2014-04-15 08:24:12 +00:00
drdev
00db8ef1dc Support moving dialogs around by dragging titlebar 2014-04-15 05:13:04 +00:00
drdev
5471cd32a4 Fix threading issues with wait callbacks 2014-04-15 04:32:31 +00:00
drdev
8f95c98a3d Implement ListChooser 2014-04-15 03:51:19 +00:00
drdev
2afc9d1694 Improve bug report dialog for mobile game 2014-04-15 01:23:21 +00:00
drdev
0946824d44 Prevent error when clicking Dev menu 2014-04-15 00:15:25 +00:00
drdev
ce796fa073 Add error traps to main render and resize functions 2014-04-15 00:12:33 +00:00
drdev
41c074efb8 Add try/catch blocks to all input entry methods in order to minimize impact of unhandled exceptions 2014-04-14 21:14:59 +00:00
drdev
53828fdcfa Prevent crash when clicking Forge button 2014-04-14 21:05:00 +00:00
drdev
3d39ce235f Refactor error handling code 2014-04-14 20:56:40 +00:00
drdev
3c7b8efb72 Fix dev menu options to run in game thread so they don't cause crash 2014-04-14 19:53:48 +00:00
drdev
b41bafd584 Fix text size in corner buttons 2014-04-14 19:42:07 +00:00
drdev
66e5ce2c7e Improve option pane display 2014-04-14 19:40:13 +00:00
drdev
e7016a328b Flesh out dialog support for mobile game 2014-04-14 18:41:23 +00:00
Chris
15e619dee4 Added new card names to changes.txt. 2014-04-14 12:37:16 +00:00
Sloth
82aad02edb - Added a TributeAILogic for Oracle of Bones. 2014-04-14 11:21:01 +00:00
Sloth
d7aae2e285 - Fixed Mindmoil. 2014-04-14 11:09:42 +00:00
Sloth
53d47add26 - Misc AI updates. 2014-04-14 08:42:45 +00:00
Sloth
49af3c0075 - The AI will now activate mana abilities of permanents about to be destroyed. 2014-04-13 21:38:33 +00:00
Sloth
e28a0ce1a8 - Improved AI anticipating abilities granting Deathtouch. 2014-04-13 21:28:57 +00:00
Sloth
9bb6a6477b - Expanded use of dealsFirstStrikeDamage AI function. 2014-04-13 19:32:23 +00:00
Sloth
d1598fbd72 - Fixed a possible NPE in getHiddenExtrinsicKeyword. 2014-04-13 14:29:10 +00:00
Sloth
402d02b508 - Improved shouldPumpCard for cases where the opposing combatant can't be damaged anyway. 2014-04-13 11:04:09 +00:00
drdev
780ae3e9ea Define invoke and wait for mobile 2014-04-13 00:49:15 +00:00
drdev
c6cc0ab964 Prevent crash when declaring attackers/blockers 2014-04-12 08:31:31 +00:00
drdev
fdd81ef263 Tweak CardManager layout stuff 2014-04-12 08:19:41 +00:00
drdev
0a7bf17e4b Reduce length of caption in deck viewer 2014-04-12 08:09:33 +00:00
drdev
65304dd2ad Support rendering and selecting items in ItemManager 2014-04-12 07:56:17 +00:00
Sloth
850efa69c7 - Cleanup and NPE protection in ProtectAI. 2014-04-12 07:26:50 +00:00
drdev
4861826c9e Code cleanup 2014-04-12 06:25:37 +00:00
excessum
76a1362acd - AI will optimise damage avoided when blocking attackers with Trample 2014-04-12 06:08:12 +00:00
drdev
64418f4e41 Allow tapping submenu item to hide submenu 2014-04-12 06:07:13 +00:00
drdev
51b7c8bf6d Improve submenu rendering 2014-04-12 06:04:01 +00:00
drdev
2bba9c9d8d Improve handling of submenus 2014-04-12 05:52:50 +00:00
drdev
3bbf98b4d4 Improve behavior for closing menus 2014-04-12 05:15:39 +00:00
drdev
32c50dec13 Fix format tooltip 2014-04-12 05:07:31 +00:00
drdev
8631916993 Prevent horizontal line appearing when filters hidden 2014-04-12 05:01:03 +00:00
drdev
4afab1c6d1 Improve caption slightly more 2014-04-12 04:56:48 +00:00
drdev
5085b85331 Improve ItemManager layout 2014-04-12 04:49:57 +00:00
drdev
d4a5aaa110 Cleanup filters layout 2014-04-12 03:35:49 +00:00
excessum
d4ff26aee5 - Basic AI upgrade to check if possible animated creatures should block before deciding to animate them. 2014-04-12 03:18:17 +00:00
drdev
6ccd9da332 Refactor text rendering so clip put in place to prevent text escaping bounds if it can't be shrunk to fit 2014-04-12 01:45:07 +00:00
drdev
576d758583 Use comma instead of semi-colon delimiter and fix game type order 2014-04-12 01:25:29 +00:00
drdev
118f1ad349 Improve support for selecting multiple variants 2014-04-12 01:15:18 +00:00
drdev
ccd19efb56 Fix so Advanced variants updates layout 2014-04-12 00:17:11 +00:00
drdev
23f7bbac09 Support showing variant buttons based on applied variants 2014-04-12 00:07:58 +00:00
drdev
5572e3fa64 Refactor some shared logic into SFilterUtil 2014-04-11 21:48:50 +00:00
drdev
8331020dc1 Fix splash progress bar when loading cards 2014-04-11 21:05:28 +00:00
drdev
7f43f35255 Prevent hiding header components in FDeckChooser 2014-04-11 20:56:43 +00:00
Chris
b40e607c77 Added new card names to changes.txt. 2014-04-11 16:30:00 +00:00
drdev
4722f915f2 Support clicking on life to pay phrexian mana 2014-04-11 15:48:36 +00:00
drdev
0ebe9fb7e6 Support actually starting a match again 2014-04-11 15:36:35 +00:00
drdev
be8acb8333 Support loading and displaying previous deck in Constructed screen 2014-04-11 15:22:09 +00:00
moomarc
679cd77899 - Make card detail visible when choosing a Vanguard avatar 2014-04-11 10:50:26 +00:00
moomarc
7a17a9f3b6 - Fix for generating theme decks 2014-04-11 10:12:53 +00:00
drdev
8acda1aada Flesh out variants a bit more 2014-04-11 04:05:45 +00:00
drdev
9687e3e661 Fix so combo boxes aren't cut off 2014-04-11 03:27:59 +00:00
drdev
4ecd5c8e42 Add Advanced option for variants 2014-04-11 03:23:39 +00:00
drdev
8ee750b744 Ensure borders show up 2014-04-11 03:08:51 +00:00
drdev
7b0ca709ac Support changing player count 2014-04-11 02:58:22 +00:00
swordshine
b6aede3549 - Fixed Keranos 2014-04-11 00:55:00 +00:00
drdev
01e6cc5c41 Fix file paths 2014-04-10 23:54:11 +00:00
drdev
60574377d6 Get mobile game working again by implementing IGuiBase interface 2014-04-10 23:49:18 +00:00
swordshine
22d1d5b1f0 - JOU: Added Dictate of the Twin Gods, Eidolon of Blossoms, Satyr Hoplite 2014-04-10 13:07:38 +00:00
moomarc
eba88e1a48 2014-04-10 12:23:01 +00:00
swordshine
2962a34aae - Fixed Weight of Conscience 2014-04-10 08:35:52 +00:00
swordshine
1ef35c1387 - JOU: Added Kruphix, God of Horizons 2014-04-10 08:08:13 +00:00
drdev
9e8c3414e4 Add myself as a developer and forge-gui-desktop to main pom.xml 2014-04-10 02:54:39 +00:00
drdev
221be3d93d Fix so FatPacks load
Fix references to non-existant quest icon files
2014-04-10 02:43:51 +00:00
drdev
53c090def2 Prevent crash when failing to load quest items 2014-04-10 02:29:56 +00:00
swordshine
7ffd2864cf - JOU: Added Godsend and Sage of Hours 2014-04-10 00:41:55 +00:00
drdev
f927409335 Fix crash when showing message box with no icon 2014-04-10 00:22:16 +00:00
drdev
a97ded530a Update install file references 2014-04-10 00:21:53 +00:00
drdev
f09112f747 Fix relative paths for files in install directory 2014-04-10 00:10:19 +00:00
drdev
525a18fbfa Refactor mobile game to use forge-gui references 2014-04-09 04:05:49 +00:00
drdev
0b9de60f0b Update project names 2014-04-09 01:45:14 +00:00
drdev
87ba4b9f1b Rename mobile projects 2014-04-09 01:33:36 +00:00
drdev
0193bf6e4d Code cleanup 2014-04-09 01:27:46 +00:00
drdev
bed7240d5c Fix getAvatarCount 2014-04-09 01:18:44 +00:00
drdev
a317e10871 Cleanup GuiDesktop 2014-04-09 01:13:28 +00:00
drdev
12b02fefbe Fix sideboarding 2014-04-09 01:07:04 +00:00
drdev
1fb1c98ef7 Fix crash when determining avatar 2014-04-09 00:13:29 +00:00
drdev
acb7ff4bac Fix icon size for stat labels 2014-04-08 23:42:40 +00:00
drdev
0512aa4856 Ignore target directory 2014-04-08 23:23:36 +00:00
drdev
9439bbbc57 Refactor out swing-related code from forge-gui into new forge-gui-desktop module 2014-04-08 23:01:39 +00:00
excessum
18dd421935 - More bug fixes for Rev 25363 2014-04-08 11:51:27 +00:00
swordshine
3ce7932f48 - JOU: Added Ajani's Presence 2014-04-08 10:34:56 +00:00
moomarc
01bb1e0298 - Fixed text of Armada Wurm 2014-04-08 10:07:45 +00:00
Sol
6bec531abf - Triggers with costs don't need OptionalDecider, since trigger costs are never mandatory 2014-04-08 02:08:27 +00:00
Chris
c355b7f2ae Added new card names to changes.txt. 2014-04-07 16:09:05 +00:00
excessum
18433f2244 - Bug fix for Rev 25363 2014-04-07 13:56:59 +00:00
excessum
67a5848b26 - Update for ProtectAI. AI can now use Protect effects to 1) counter certain targeted spells 2) protect against lethal damage 3) create an unblockable attacker depending on expected damage 2014-04-07 13:46:10 +00:00
Sloth
544afe181e - Added SVar:NonStackingAttachEffect:True to some more auras. 2014-04-07 12:56:05 +00:00
Sloth
80fd5f3c32 - Added SVar:NonStackingAttachEffect:True to some auras. 2014-04-07 12:23:08 +00:00
swordshine
0326c26632 - Fixed Serene Master 2014-04-07 07:57:14 +00:00
swordshine
58f02d0bc1 - Fixed NPE caused by Jhoira Avatar 2014-04-07 05:06:17 +00:00
drdev
8de3157cbe Add quest classes to mobile game 2014-04-06 20:23:03 +00:00
drdev
2df3525918 Support selecting teams 2014-04-06 16:38:29 +00:00
Sloth
e1d7dae168 - Updated some quest decks and a challenge. 2014-04-06 13:54:58 +00:00
swordshine
338bbab074 - Fixed Decree of Pain 2014-04-06 11:00:09 +00:00
swordshine
18112f9d31 - Update scripts for CopySpellAbility effects 2014-04-06 10:53:00 +00:00
Sloth
331e1ae505 - Extended use of the dealsFirstStrikeDamage function. 2014-04-06 07:52:22 +00:00
Sloth
ab6d4c933f - Updated some quest decks. 2014-04-06 06:31:55 +00:00
swordshine
90166d32e0 - Fixed Swirling Sandstorm 2014-04-06 05:50:51 +00:00
drdev
aca1e1bc4f Add item manager to mobile game 2014-04-06 05:04:13 +00:00
Sloth
f15bd570cd - Updated some quest decks. 2014-04-05 19:41:24 +00:00
drdev
cc833c86bb Improve gesture support in and around toggle switches 2014-04-05 19:38:43 +00:00
Sloth
39a7e2b882 - Improves AiAttackController. 2014-04-05 19:28:16 +00:00
drdev
7d236e0227 Improve toggle switch appearance 2014-04-05 18:59:12 +00:00
Sloth
ee88f0ab95 - The AI will now predict P/T changes from effects in the command zone (like Jace, Architect of Thought's +1 ability). 2014-04-05 07:50:43 +00:00
swordshine
aabb5888fe - Added Game of Chaos 2014-04-05 06:39:18 +00:00
Sloth
96338eb652 - AI will now try to chump block with creatures that have SacMe SVars > 3 (for example Rukh Egg). 2014-04-05 06:12:34 +00:00
drdev
a71f9c46eb Add toggle switch for changing between Human and AI 2014-04-04 22:16:02 +00:00
Sloth
69d1c2ceea - Improved isUsefulPumpKeyword. 2014-04-04 20:02:16 +00:00
Sloth
fd88585bd4 - Expanded the predictThreatenedObjects AI function. 2014-04-04 18:42:50 +00:00
Sloth
b8825ceb8b - Minor AI updates. 2014-04-04 15:18:00 +00:00
excessum
60eee41d72 - Basic AI upgrade to check if possible animated creatures should attack before deciding to animate them. 2014-04-04 14:40:28 +00:00
Sloth
f90b74a864 - The AI will now try to avoid destroying cards with the SacMe SVar. 2014-04-04 14:37:30 +00:00
Sloth
9d2b6a1f9f - Little AI updates. 2014-04-03 21:57:39 +00:00
Sloth
06dcc00517 - The AI will now check static abilities when checking possible animated blockers (Svogthos, the Restless Tomb). 2014-04-03 12:54:29 +00:00
swordshine
373e7cc9ca - Fix Bifurcate 2014-04-03 06:50:04 +00:00
swordshine
b8221a6f89 - experimental fix for Lim-Dul's Vault 2014-04-03 06:33:06 +00:00
drdev
083afd6ed5 Add divot to combo box 2014-04-03 04:46:19 +00:00
drdev
9fbb1eedb8 Flesh out ConstructedScreen more
Support alphaComposite for Graphics
2014-04-03 04:21:59 +00:00
Sol
41d864cbe8 - Fix Knollspine Invocation not being able to be activated due to when CanPlay() is called relative to AnnounceX() 2014-04-03 03:03:26 +00:00
Sol
a0fdf02280 - Fixed Night Soil from needing X-2 cards to remove instead of 2. 2014-04-03 02:00:39 +00:00
Sloth
0de3d58651 - The AI will now check activation restrictions when checking possible animated blockers. 2014-04-02 14:48:34 +00:00
Sloth
cea352d029 - NPE prevention in AiAttackController. 2014-04-02 05:30:21 +00:00
drdev
8e207fd1e0 Work on ConstructedScreen 2014-04-02 00:00:07 +00:00
excessum
e0b93081c2 - Basic AI upgrade to check for possible animated creatures (ie. manlands) before deciding attackers 2014-04-01 14:50:54 +00:00
Sloth
fb9d515404 - Updated some quest decks. 2014-04-01 07:59:24 +00:00
moomarc
6f1d20ec5d - Updated new cards list in CHANGES.txt 2014-04-01 07:38:46 +00:00
Sloth
4dc993a3e4 - Fixed NPE caused by Skyship Weatherlight when no card is left. 2014-04-01 07:25:25 +00:00
moomarc
a38a733734 - Updated precon names on server to lowercase. Fixes issue where unix systems wouldn't recognise the images due to mismatched case. 2014-04-01 07:08:24 +00:00
moomarc
d5fbed3b98 - Script tweaks 2014-03-31 14:32:16 +00:00
moomarc
b175dd703a - Added Quarum Trench Gnomes 2014-03-31 14:21:09 +00:00
moomarc
be3661edee - Added Harvest Mage (see http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=14167 for existing issue that is more noticeable with Harvest Mage) 2014-03-31 13:25:29 +00:00
drdev
156c0c1a4f Start working on Constructed screen 2014-03-31 03:46:55 +00:00
drdev
756b9e58fb Get land stacking working 2014-03-31 01:57:08 +00:00
drdev
b42a3e3c54 Ensure card panels reset between games 2014-03-31 01:38:45 +00:00
drdev
9843d323c5 Tweak fling gesture 2014-03-31 01:20:54 +00:00
drdev
f42830f615 Fix fling gestures 2014-03-31 00:55:43 +00:00
drdev
44144cc70d Support fling gestures 2014-03-30 23:09:34 +00:00
drdev
7803bde1b5 Prevent crash if playing for ante 2014-03-30 23:09:10 +00:00
Sol
8110a19f7b - Add ID to cardname may untap cards. 2014-03-30 21:11:36 +00:00
Sol
42297e47b7 - Fix when Ichneumon Druid triggers 2014-03-30 20:33:14 +00:00
Sol
8160c3a2de - Improve Stack Description of Animate when only changing a creatures Power 2014-03-30 20:09:29 +00:00
Sol
8516ca6e03 - Fixed Time Vault not untapping when skipping a turn, and allowing you to untap any of your tapped Time Vaults not just the first one 2014-03-30 19:49:13 +00:00
drdev
01e88e1047 Support scrolling background texture with list 2014-03-30 19:38:39 +00:00
Sol
bb1c853f10 - Fix lifeTotal Condition not using CalculateAmount (makes Timely Reinforcement first ability work properly) 2014-03-30 19:26:37 +00:00
Chris
54f573bcbd - Cleared out the changes.txt file, now ready for new material.
- Added new card names to changes.txt.
2014-03-30 13:51:21 +00:00
swordshine
e31bbe28c5 - Convert keyword "maxLevel" to SVar 2014-03-30 07:57:38 +00:00
swordshine
3ec3982e01 - Update scripts 2014-03-30 05:55:33 +00:00
drdev
cf523464b5 Support scrolling creatures and lands independently
Support stacking cards
2014-03-30 05:42:37 +00:00
drdev
d25982eebe Prevent stack being forced to re-show after resolving an item on it 2014-03-29 23:34:39 +00:00
drdev
5f30f26d6a Fix so new cards added to a zone are scrolled into view automatically 2014-03-29 23:29:00 +00:00
drdev
82aefc0169 Improving scrolling support for stack and log 2014-03-29 23:01:48 +00:00
drdev
0a2e6184dc Support panning scrollable regions 2014-03-29 22:11:44 +00:00
drdev
13c16e1360 Fix match and update texture for Arabian Nights skin
Commit more awesome skins by 1224Deko
2014-03-29 21:35:28 +00:00
Sloth
d07c327e71 - Added a hard version of the quest opponent Bilbo Baggins.
- Updated some quest decks.
2014-03-29 20:25:12 +00:00
Sol
bebf1be6db - Better fix for BoosterGenerator NPE 2014-03-29 16:31:54 +00:00
Sol
f58e85396c - Fix NPE in BoosterGenerator when trying to generate a Foil card for an "empty" Pack (as seen in Fat Packs with no extra cards) 2014-03-29 16:28:59 +00:00
drdev
d7810d6784 Support rendering game log 2014-03-29 16:25:13 +00:00
drdev
3f65674a72 Fix stack padding 2014-03-29 15:35:03 +00:00
drdev
f778f291df Fix tab rendering 2014-03-29 15:24:00 +00:00
drdev
6821d83f95 Fix rendering logic 2014-03-29 15:12:17 +00:00
drdev
4f58ecd08d Support repeating background texture 2014-03-29 03:14:15 +00:00
drdev
f82e8b277c Fix Arabian Nights background texture so it can load in mobile game 2014-03-29 02:28:06 +00:00
drdev
5e36fe0105 Improve splash screen background 2014-03-29 01:54:08 +00:00
drdev
e746b98ae2 Support showing [Empty] label if Stack selected when stack is empty 2014-03-29 00:01:34 +00:00
drdev
6db1e14404 Prevent drop downs covering prompt 2014-03-28 23:20:35 +00:00
drdev
fa3bd276ba Improve drop down appearance 2014-03-28 21:31:55 +00:00
Sloth
f1eb3b9251 - Fixed a possible NPE caused by Scars of the Veteran. 2014-03-28 21:24:03 +00:00
Sloth
624133a1af - Added Mindstorm Crown. 2014-03-28 17:16:52 +00:00
Sloth
be903a1deb - Added the zendikar quest world by serrasmurf. 2014-03-28 15:03:26 +00:00
Chris
e53957f1c4 [maven-release-plugin] prepare for next development iteration 2014-03-28 13:08:58 +00:00
Chris
4202b382dc [maven-release-plugin] prepare release forge-1.5.15 2014-03-28 13:08:42 +00:00
Chris
df19a14017 Preparing the changes.txt file for the next beta build and release. 2014-03-28 12:33:12 +00:00
drdev
da2a087a87 Update CHANGES.txt 2014-03-28 00:49:07 +00:00
drdev
5735aebb8c Improve stack layout and prevent horizontal scrolling
Ensure stack scrolled to top when updated
Ensure Setup Game State looks in default user games folder
2014-03-28 00:45:30 +00:00
excessum
2371d52c9d - AI support for Polukranos, World Eater 2014-03-27 13:52:03 +00:00
asepetci
a629f4c42a Updated draft rankings 2014-03-27 10:00:57 +00:00
drdev
bb69e27c5a Update CHANGES.txt 2014-03-27 04:55:42 +00:00
drdev
4f485594fc Support showing source card images within stack items
Update CHANGES.txt
2014-03-27 04:53:16 +00:00
drdev
d43dfb788d Fix so extra hand panes removed after losing control of another player 2014-03-27 03:44:44 +00:00
drdev
49a70ccf48 Refactor how MindSlaver logic works so mindSlaveMaster can view their cards in addition to those of the player they've taken over 2014-03-27 03:14:25 +00:00
drdev
9304137b80 Prevent being able to see certain cards when modal opened 2014-03-27 02:18:47 +00:00
drdev
aca3051029 Prevent being able to identify cards you're not allowed to see 2014-03-27 01:59:18 +00:00
drdev
35563a415d Fix issue when field disappears 2014-03-27 00:40:35 +00:00
Sloth
d5c2b3bacd - Improved the playImmediately AI function. 2014-03-26 20:04:18 +00:00
Sloth
ef6d1f440e - Fixed a bug when Nivmagus Elemental tries to exile copied spells. 2014-03-26 19:31:22 +00:00
Sloth
d11b8fb546 - Fixed Precursor Golem. 2014-03-26 15:28:21 +00:00
excessum
d1a1c7f3b1 - Added "IsCurse" to Bile Blight. Removed "AI cannot use" flags from Bile Blight and Devour Flesh. Added AITgt block for AnimateAI to allow Sealock Monster's monstrosity trigger to have a proper (still random) target. 2014-03-26 12:37:25 +00:00
drdev
af7d7b6ff8 Improve stack display for multiple items 2014-03-26 02:44:26 +00:00
drdev
d3a9fb107d Support setting up game state 2014-03-26 02:24:54 +00:00
drdev
6f68535120 Prevent crashing if deck generation fails 2014-03-26 02:00:43 +00:00
Sloth
ba430215f6 - Improved AI dealing with Web of Inertia. 2014-03-25 21:16:35 +00:00
Sloth
306c7a6678 - Improved AI using Tamiyo, the Moon Sage. 2014-03-25 13:17:07 +00:00
Sloth
58ecdb59a7 - Fixed Ivory Gargoyle and Molten Firebird. 2014-03-25 12:58:09 +00:00
Sloth
c6008dfea4 - Improved isUsefulPumpKeyword. 2014-03-24 14:09:47 +00:00
drdev
13259c9896 Improve appearance of multiple items on stack 2014-03-24 02:39:33 +00:00
Sol
b6f245071f - Improve how Storm Count works, recording the current storm count onto the trigger instead of relying on a potentially incorrect count amount. 2014-03-24 02:15:31 +00:00
drdev
51a20a21d2 Fix issue with card zoom following double-click activation 2014-03-24 01:38:36 +00:00
Sol
cf3425cfde - Add mana symbol to Goblin Flotilla trigger desc 2014-03-24 00:53:45 +00:00
Sloth
5e38f04fa2 - Fixed AI ignoring NeedsToPlay SVars when playing lands. 2014-03-23 22:57:09 +00:00
drdev
a3ed2dbb14 Get stack working 2014-03-23 19:06:08 +00:00
Sloth
27e07fd9dd - Fixed a bug in predictToughnessBonusOfAttacker/Blocker (thanks excessum). 2014-03-23 14:11:55 +00:00
Sloth
2677323657 - The AI will no longer use TapType costs for Pump abilities. 2014-03-23 08:52:30 +00:00
Sloth
a5899de0e3 - Fixed AI calculating Monstrosity abilities twice. 2014-03-23 08:38:42 +00:00
excessum
a7b8410f25 - AI support for "deal damage equal to power". Tweak to sort "fight" list by card efficiency instead of power/cmc. 2014-03-23 06:56:24 +00:00
excessum
6e1c19f660 - Consider if attacker/blocker can go monstrous when attacking/blocking. Only considers added P1/P1 counters at present and NOT extra abilities. 2014-03-23 03:13:22 +00:00
drdev
d37c6fc9a4 Improve menu item and icon size 2014-03-22 22:58:06 +00:00
drdev
548b080cbc Add delay after clicking menu item 2014-03-22 22:45:57 +00:00
drdev
58b91ee603 Update menu bar for match screen 2014-03-22 22:35:42 +00:00
drdev
1aac485377 Implement menu structures 2014-03-22 20:53:17 +00:00
drdev
3469bd4eaa Tweak previous fix 2014-03-22 16:29:11 +00:00
drdev
9d4bd7489e Prevent crash if Generate Mana dev tool used before game begins 2014-03-22 16:22:34 +00:00
drdev
bffa4259a0 Flesh out Dev pane 2014-03-22 02:30:39 +00:00
Sloth
4a83127c69 - Fixed Mercadian Atlas. 2014-03-21 14:40:40 +00:00
swordshine
f470120924 - Fixed NPE 2014-03-21 12:13:33 +00:00
drdev
748356b8bf Start working on VDev 2014-03-20 23:47:02 +00:00
excessum
9f810d131f - AI fix for "fight" keyword. Added "AILogic$ Main2" to Domri Rade's +1 to allow AI to choose -2 ability if available. 2014-03-20 12:58:04 +00:00
drdev
7c3bcda327 Fix clipboard 2014-03-20 02:38:03 +00:00
drdev
6bcd655198 Support determining scroll bounds 2014-03-20 02:20:19 +00:00
drdev
2c3d96228c Refactor how overlays are shown and hidden 2014-03-19 23:56:02 +00:00
drdev
93c02e9425 Flesh out Guantlet stuff and stuff for winning/losing games 2014-03-19 22:58:08 +00:00
swordshine
c787d02de5 - Tweak Planeswalker's redirection effect 2014-03-19 13:48:27 +00:00
swordshine
5cc0b20654 - Remove hidden keyword "At the beginning of the end step, exile CARDNAME." 2014-03-19 04:55:34 +00:00
swordshine
7eb4279a6c - Update scripts 2014-03-19 03:40:30 +00:00
Sol
6c747b5857 - Check if creatures in combat are actually still creatures during state checks 2014-03-19 01:34:18 +00:00
swordshine
e67a152654 - Update scripts 2014-03-19 01:17:26 +00:00
Sol
8075435210 - Flip incorrect short circuit boolean in checkBlockPayments 2014-03-18 23:32:37 +00:00
drdev
875befff35 Add match screen menu bar 2014-03-18 15:03:57 +00:00
swordshine
d933d79ef9 - Update scripts 2014-03-18 14:06:01 +00:00
swordshine
2038216017 - Started to convert "At the beginning of the end step, exile CARDNAME." to delayed triggers 2014-03-18 13:22:57 +00:00
swordshine
531672aed8 - remove hidden keyword "At the beginning of the next end step, destroy CARDNAME if it attacked this turn." 2014-03-18 12:15:02 +00:00
swordshine
41970a601c - Remove hidden keyword "At the beginning of the end step, destroy CARDNAME." 2014-03-18 11:58:56 +00:00
swordshine
86769d8321 - Remove hidden keyword "At the beginning of the end step, sacrifice CARDNAME." 2014-03-18 10:39:16 +00:00
swordshine
d32cc1f5ba - Update more scripts 2014-03-18 04:26:30 +00:00
swordshine
9cb3ed42d9 - Update more scripts 2014-03-18 02:18:46 +00:00
swordshine
47f0f3367a - Update scripts containing hidden keywords "At the beginning of the end step, sacrifice CARDNAME." 2014-03-18 01:16:16 +00:00
Sol
682a0cff62 - Filter out ETB Tapped Lands in one drop logic for playing lands (Improve not playing Karoo lands without a land in play) 2014-03-18 00:57:52 +00:00
swordshine
e03d626ef9 - Tweak AI 2014-03-17 13:08:57 +00:00
swordshine
9de574b38f - Update scripts for Sneak Attack. Started to convert hidden keyword "At the beginning of the end step, destroy/exile/sacrifice CARDNAME." 2014-03-17 08:49:40 +00:00
swordshine
e485704cb4 - Update scripts for Gemini Engine 2014-03-17 08:43:52 +00:00
swordshine
396f4071de - The source of Geist of Saint Traft's delayed trigger should not be the token. 2014-03-17 04:56:01 +00:00
swordshine
565cb20407 - Fixed Heat Shimmer 2014-03-17 04:41:30 +00:00
drdev
3a40132ba3 Start working on header for match screen 2014-03-16 21:58:15 +00:00
Sol
33edd69fa4 - Adding a fakeSA into Blocker Payment 2014-03-16 13:55:45 +00:00
Chris
21939e6ba0 Added new card names to changes.txt. 2014-03-16 13:24:05 +00:00
Chris
8fb49522aa Added a fluff piece to the changes.txt file. 2014-03-16 13:23:04 +00:00
Chris
2a83c6e662 Preparing the changes.txt file for the next beta build and release. 2014-03-16 13:21:50 +00:00
Sloth
8b6f325af2 - Fixed Soulcatchers' Aerie. 2014-03-16 12:52:59 +00:00
swordshine
ad8dc923db - Update scripts (m - z) 2014-03-16 12:16:57 +00:00
swordshine
86ee4c0c78 - Update scripts for delayed triggers (a - l) 2014-03-16 11:00:35 +00:00
swordshine
3ea49c0a45 - Fixed incorrect remembered objects in delayed triggers (Necropotencenow draws one card for each of its delayed triggers). More cards will be converted 2014-03-16 09:33:58 +00:00
swordshine
efa06e6830 - Fixed Bestow so Far // Away works correctly 2014-03-16 05:44:05 +00:00
swordshine
beb54c9a4d - Fixed Gangrenous Zombies 2014-03-16 04:24:54 +00:00
swordshine
30cd3954c3 - Added Legerdemain and Gauntlets of Chaos
- Fixed isManaAbility
2014-03-16 03:48:38 +00:00
swordshine
f123611655 - Added Crooked Scales 2014-03-16 03:46:06 +00:00
drdev
d6a290d165 Fix auto font-shrinking for FButtons 2014-03-15 21:01:15 +00:00
drdev
eee31f1fd4 Support auto-shrinking font to fit 2014-03-15 20:44:49 +00:00
Sloth
b06d7bc3cc - Fixd Parallel Thoughts. 2014-03-15 19:53:22 +00:00
drdev
4e27765277 Add flashback and command zones 2014-03-15 19:47:20 +00:00
Sloth
59761d1fce - Fixed Perplex. 2014-03-15 12:38:09 +00:00
Sloth
c634f7a6cf - Fixed InputSelectCardsForConvoke. 2014-03-15 09:09:39 +00:00
drdev
8aa77b684b Support targeting players 2014-03-15 04:11:41 +00:00
drdev
12ded99dcd Support showing and updating mana pool 2014-03-15 03:45:12 +00:00
drdev
fb37d4ea57 Fix Card.canBeShownTo 2014-03-14 23:09:45 +00:00
Chris
70c89f29c1 [maven-release-plugin] prepare for next development iteration 2014-03-14 16:59:37 +00:00
Chris
be44e84f34 [maven-release-plugin] prepare release forge-1.5.14 2014-03-14 16:59:26 +00:00
Chris
3794ddbde4 Preparing the changes.txt file for the next beta build and release. 2014-03-14 15:35:31 +00:00
Chris
42b054238d Added new card names to changes.txt. 2014-03-14 15:25:59 +00:00
Sol
abdd8c85e9 - Reverting changes from r25173 to Card.java that broke a lot of things. DrDev, please revisit this after release and test it via main Forge before committing. 2014-03-14 12:49:05 +00:00
swordshine
4645e7a2ff - Added Collective Voyage 2014-03-14 05:16:59 +00:00
drdev
a605fc3851 Fix so decks can be saved as without being lost 2014-03-14 00:21:21 +00:00
drdev
811b733cbe Support showing hidden cards if in developer mode 2014-03-13 22:45:18 +00:00
drdev
1bd2df2d28 Ensure cards hidden if you shouldn't be able to see them 2014-03-13 22:32:58 +00:00
Chris
dc5be10721 Added new card names to changes.txt. 2014-03-13 13:44:20 +00:00
swordshine
64e71155af - Update scripts 2014-03-13 11:35:34 +00:00
swordshine
a44c27aae5 - Added Dakkon Blackblade Avatar 2014-03-13 11:09:10 +00:00
swordshine
e66c9db6ab - Added Alliance of Arms 2014-03-13 10:56:05 +00:00
drdev
ae1deffc5e Center option text 2014-03-13 03:05:44 +00:00
drdev
fd0640f678 Include prompt message in base input zoom view 2014-03-13 03:01:12 +00:00
drdev
2e7547998a Support zooming while mana payment input 2014-03-13 02:39:42 +00:00
drdev
61dfce9d6b Prevent keeping zoom view open when declaring blockers 2014-03-13 01:22:16 +00:00
drdev
dc1b80db1b Ensure zoom view prompt is updated 2014-03-13 01:14:54 +00:00
drdev
4054d1af71 Support zoom view when declaring blockers 2014-03-13 01:09:55 +00:00
drdev
af2db370f7 Support zooming when confirming mulligan 2014-03-13 00:54:49 +00:00
drdev
a1b624f3ee Support using zoom view for InputAttack 2014-03-13 00:37:18 +00:00
swordshine
eb444c2d69 - Prevent infinite loop for Death Match
- Added Shared Trauma
2014-03-13 00:31:16 +00:00
drdev
f4fbdddab7 Change Back to Hide 2014-03-12 23:25:46 +00:00
drdev
3f8c55eac3 Prevent showing option list if no options 2014-03-12 23:15:43 +00:00
drdev
ec8c7ae319 Support double-tap to activate card without zooming 2014-03-12 23:04:00 +00:00
drdev
df9f85f7be Support tapping card to activate its first option 2014-03-12 22:46:48 +00:00
drdev
2491d0782e Pull in targeting changes to forge-m-base 2014-03-12 22:28:26 +00:00
Sloth
93d9663e0a - Added Forgotten Lore. 2014-03-12 16:17:53 +00:00
swordshine
58b7d546a5 - Added Shrouded Lore 2014-03-12 13:24:40 +00:00
swordshine
61830aabe5 - Added Mana-Charged Dragon
- Update scripts for some RepeatEach cards
2014-03-12 13:06:34 +00:00
swordshine
c056a98347 - Simple scripts for Windfall 2014-03-12 12:17:30 +00:00
swordshine
64f32e0008 - A temporary fix for Windfall (References "SVar:MaxDiscard:Number$0" in spellability do not update, so temporarily remove the related references) 2014-03-12 12:01:04 +00:00
swordshine
ba24c30718 - Fixed last commit 2014-03-12 08:32:10 +00:00
swordshine
c6476d2490 - Move TargetSelection check to InputSelectTargets, so Prey Upon cannot target two creatures controlled by one opponent any more 2014-03-12 08:28:52 +00:00
swordshine
3fce6a5f2c - Move TargetsWithRelatedProperty to canTarget 2014-03-12 04:42:59 +00:00
swordshine
96e03e5fcf - Added Minds Aglow 2014-03-12 04:41:29 +00:00
swordshine
36d2134352 - Remove unique targets check in getValidCardsToTarget(), it's already handled in canTarget 2014-03-12 04:17:31 +00:00
Sol
7bdfeefb1d - Experimental fix for a single creature being declared as an Attacker twice 2014-03-12 02:24:10 +00:00
Chris
89afe46f92 Added new card names to changes.txt. 2014-03-11 14:22:17 +00:00
drdev
02cbd370a8 Prevent showing unplayable options in zoom
Prevent showing duplicate cards on field when zoomed
2014-03-11 05:11:25 +00:00
swordshine
b6e1c02f07 - Added Mogg Assassin 2014-03-11 04:42:18 +00:00
drdev
62868732c2 Support using prompt to go Back or expand/collapse option list 2014-03-11 04:30:22 +00:00
swordshine
84ee4b0488 - Added Cuombajj Witches 2014-03-11 04:08:42 +00:00
drdev
779b067eb2 Support selecting abilities on zoom view 2014-03-11 03:53:42 +00:00
drdev
4c554d7c39 Add card zoom support 2014-03-11 02:44:27 +00:00
swordshine
b00d3547bc - Added Preacher 2014-03-11 01:47:29 +00:00
swordshine
54ba797151 - Added Arena, Echo Chamber, and Magus of the Arena 2014-03-11 00:21:27 +00:00
Sloth
09f7632ad2 - Fixed the AI logic "Evasion" for Gorilla War Cry. 2014-03-10 23:07:06 +00:00
Sol
0fbd8248f8 - Added snippet to Changes regarding about Quest Pets 2014-03-10 17:54:50 +00:00
swordshine
2b14baabb5 - Added Evangelize 2014-03-10 13:32:03 +00:00
swordshine
a0b26dfe02 - Updated cube by juzamjedi 2014-03-10 13:29:31 +00:00
drdev
00a911412a Add padding to prompt message 2014-03-10 04:10:02 +00:00
drdev
f3d9a76d0d Improve corner button appearance 2014-03-10 04:05:15 +00:00
drdev
c4c2de03f9 Improve appearance of disable button 2014-03-10 03:20:27 +00:00
drdev
8e1862e488 Prevent prompt buttons looking weird when starting game 2014-03-10 02:41:07 +00:00
drdev
80998fb488 Support tapping cards 2014-03-10 02:35:12 +00:00
drdev
beb5269aad Flesh out logic for updating field
Ensure match preferences saved
2014-03-10 01:37:47 +00:00
swordshine
a4be2a944d - Converted keyword "Permanents don't untap during their controllers' untap steps" to a static ablility
- Added Dream Tides, Magnetic Mountain, Mudslide, Thelon's Curse
2014-03-10 00:32:54 +00:00
drdev
891b1fa2fd Support selecting cards 2014-03-09 21:48:18 +00:00
drdev
e9b007db19 Support updating zone displays 2014-03-09 21:37:02 +00:00
drdev
eed7fbbabf Support passing priority 2014-03-09 21:20:08 +00:00
drdev
5a821a7e3f Code cleanup 2014-03-09 21:02:23 +00:00
drdev
00b73bce10 Code cleanup 2014-03-09 20:53:48 +00:00
drdev
3ce0c595ce Flesh out PlayerControllerHuman 2014-03-09 20:44:44 +00:00
drdev
c5ededc74b Flesh out logic necessary to start and update game state 2014-03-09 19:59:29 +00:00
Chris
8412792bdf edit 2014-03-09 13:56:00 +00:00
Chris
cc425d8d88 Added new card names to changes.txt.
Added a fluff piece to the changes.txt file.
2014-03-09 13:55:20 +00:00
abbcdfin
e45fe26e1b Show the card being discarded for discard replacement effects 2014-03-09 13:46:15 +00:00
Sloth
177d6f3346 - Fixed replicate cost not being calculated correctly sometimes. 2014-03-09 12:09:20 +00:00
swordshine
ba8923ae5c - Added Winter's Chill 2014-03-09 10:18:52 +00:00
drdev
a79fd3f240 Pull in necessary files from forge-gui to start being able to flesh out gameplay 2014-03-09 07:16:18 +00:00
swordshine
5abb581109 - Added Emberwilde Djinn 2014-03-09 06:19:30 +00:00
drdev
ffab69b0b4 Support loading more information into model 2014-03-09 05:05:16 +00:00
swordshine
d5b516a7cb - Added Mind Bomb and Well of Lost Dreams 2014-03-09 04:58:50 +00:00
swordshine
03ce7bd1c3 - Update scripts 2014-03-09 04:57:33 +00:00
drdev
dabc4ff638 Fix size discrepancy when showing 5 rows 2014-03-09 04:41:31 +00:00
drdev
77bdc7a950 Adjust card sizes appropriately when zones shown/hidden 2014-03-09 04:17:36 +00:00
drdev
d2e9b7720e Support switching and hiding zones 2014-03-09 03:47:34 +00:00
drdev
551c00eec6 Use better temporary screen title 2014-03-08 21:56:33 +00:00
drdev
1c8c5a398d Improve life display 2014-03-08 21:51:03 +00:00
drdev
1a5fccc4fb Code cleanup 2014-03-08 21:13:10 +00:00
drdev
8e07c9eaf9 Support rendering background for selected zone and tab 2014-03-08 20:58:43 +00:00
drdev
128d6304b5 Flesh out info labels 2014-03-08 17:22:33 +00:00
abbcdfin
3ed3dca6ad Fix Stangg token image 2014-03-08 16:06:52 +00:00
drdev
d7c227e128 Support loading actual card images 2014-03-08 14:59:21 +00:00
swordshine
b9f703c80e - Added Lim-Dul's Hex and Erosion 2014-03-08 08:41:05 +00:00
swordshine
48f7b96224 - Added Forbidden Ritual 2014-03-08 06:07:53 +00:00
drdev
c1e24d6043 Make card images show up 2014-03-08 05:43:39 +00:00
drdev
4b61238c20 Support connecting to AppData
Support loading card images
2014-03-08 05:36:37 +00:00
drdev
517e245c02 Fix phase order 2014-03-08 03:50:12 +00:00
drdev
3d1d4b8acc Separate and flip field 2014-03-08 02:58:37 +00:00
drdev
01910deb96 Make progress on match layout 2014-03-08 02:49:35 +00:00
Sol
6617e14c9b - Fixed NPE in DeckController 2014-03-08 02:32:49 +00:00
swordshine
c33a0295cc - Added Trade Secrets 2014-03-08 01:19:05 +00:00
drdev
00698b1351 Create zone display and make card panels actually contain a reference to a Card 2014-03-07 23:11:06 +00:00
drdev
0119e329c1 Add basic field layout 2014-03-07 22:41:27 +00:00
drdev
be209d1cb4 Make Phases horizontal 2014-03-07 21:59:51 +00:00
abbcdfin
48db3e7a36 Fix OSX build process 2014-03-07 16:37:08 +00:00
jendave
934aaa9956 Update guava to latest version 2014-03-07 16:28:16 +00:00
Chris
a8b3a9e824 Added new card names to changes.txt. 2014-03-07 13:54:42 +00:00
jendave
054a939be5 Update versions 2014-03-07 09:51:15 +00:00
swordshine
d8edc8319c - Added Teferi's Realm 2014-03-07 09:48:10 +00:00
swordshine
7772f758d1 - updated scripts for Extraplanar Lens 2014-03-07 07:22:16 +00:00
drdev
0180059e78 Fix match background aspect ratio 2014-03-07 03:03:50 +00:00
drdev
7476e386c2 Improve match layout and background 2014-03-07 02:54:44 +00:00
drdev
096ea8c62d Fix a couple more rounding issues 2014-03-07 00:22:45 +00:00
drdev
6a10cce6ca Fix border color 2014-03-07 00:05:59 +00:00
drdev
d03c9d0e44 Improve floating point rendering 2014-03-06 23:30:57 +00:00
drdev
baefd5982f Remove margin under screen header 2014-03-06 22:00:56 +00:00
drdev
21e85be3c2 Remove back icon clip 2014-03-06 21:49:58 +00:00
drdev
26bdb62676 Clean up screen header to make it look nicer 2014-03-06 21:25:36 +00:00
drdev
14accbd162 Fix crash when adding ValueRangeFilters like Toughness 2014-03-06 17:25:38 +00:00
drdev
63fe555a11 Add logic to ensure release called if longPress handled 2014-03-06 16:56:23 +00:00
drdev
50c3eabbf3 Improve quick tap responsiveness 2014-03-06 16:41:36 +00:00
drdev
5365a0df74 Make pressed and released effects happen even when quick tapping 2014-03-06 16:21:48 +00:00
Chris
c084672add Added new card names to changes.txt. 2014-03-06 15:37:11 +00:00
drdev
61aa3e5603 Improve gesture handling to not make press effect happen immediately and make release effect apply when starting to pan or pinch 2014-03-06 15:32:58 +00:00
drdev
24c6ff43ae Flesh out settings 2014-03-06 14:19:24 +00:00
swordshine
1669cf8323 - Fixed Prismatic Lace 2014-03-06 09:48:11 +00:00
swordshine
819c9b38f6 - Added Parallel Thoughts 2014-03-06 06:41:41 +00:00
drdev
d5b050985a Fix so toggling boolean setting saves preferences 2014-03-06 06:22:29 +00:00
drdev
a65507a453 Show radio button icons on CustomSelect screen 2014-03-06 06:10:31 +00:00
drdev
3a4cb788c7 Support changing and remembering theme
Make forge-m-base a Maven project
2014-03-06 05:23:17 +00:00
drdev
6219d036cc Support opening CustomSelectScreen 2014-03-06 04:10:59 +00:00
swordshine
2d2d566c1f - Improved AI logic for Homeward Path 2014-03-06 03:54:03 +00:00
drdev
523addfdde Support configuring some settings 2014-03-06 03:49:09 +00:00
Sol
8e7dd1a4ac - Switch propaganda fix to EmptySa which fills in activating player. 2014-03-06 03:17:42 +00:00
swordshine
f5a8b2706d - Updated scripts 2014-03-06 02:09:08 +00:00
swordshine
6c67cef9ed - tweak Devour 2014-03-06 01:50:15 +00:00
swordshine
6576136f39 - tweak Amplify 2014-03-06 01:17:52 +00:00
swordshine
a72d8e0882 - Fixed etbcounter transform Garruk Relentless 2014-03-06 00:22:08 +00:00
drdev
44da03a8f9 Create FModel for loading preferences and other information 2014-03-05 22:55:06 +00:00
drdev
d13e4dbdc5 Flesh out FList and support nested containers 2014-03-05 21:58:43 +00:00
swordshine
cd45fd824d - Added Diaochan, Artful Beauty 2014-03-05 05:08:04 +00:00
Sol
34c2d37b46 - Preventing a crash by passing a dummy SpellAbility into Propaganda effects 2014-03-05 03:53:07 +00:00
drdev
e2b0bb9c19 Start working on supporting overlays 2014-03-05 03:45:29 +00:00
drdev
198ae6bbfb Fix FComboBox border color
Allow menu button to temporary move to Settings screen
2014-03-05 00:42:06 +00:00
drdev
a7296a35c6 Flesh out Setting screen structure 2014-03-05 00:21:20 +00:00
drdev
cedda9622f Make combo box render 2014-03-04 23:24:18 +00:00
Sloth
b4ccd24e75 - Fixed deck generation ignoring singleton mode when adding basic lands. 2014-03-04 19:59:46 +00:00
Chris
1479e578ea Added new card names to changes.txt. 2014-03-04 14:21:05 +00:00
drdev
b7cb692b29 Make Theme selector visible 2014-03-04 13:57:10 +00:00
drdev
c1989f8fdf Add Theme selector to SettingsScreen 2014-03-04 13:56:30 +00:00
swordshine
986dd76696 - Added Mangara's Tome 2014-03-04 13:41:24 +00:00
Sloth
ff48b93222 - Updated a few quest deck with new cards. 2014-03-04 13:31:34 +00:00
Sloth
128bde09d6 - Improved AI using Vivid lands and similar cards. 2014-03-04 13:00:09 +00:00
Sloth
7310305312 - Fixed AI mana payment not using properly ordered lists (and thus didn't use the intended priorities). 2014-03-04 09:13:40 +00:00
swordshine
d53cc62788 - Added Choice of Damnations 2014-03-04 04:52:31 +00:00
swordshine
6323462350 - Fixed Pemmin's Aura 2014-03-04 01:37:42 +00:00
drdev
0efef5a925 Add FComboBox 2014-03-03 23:50:12 +00:00
drdev
a40bf890f6 Fix FButton rendering at small widths 2014-03-03 21:41:29 +00:00
swordshine
971e4475d9 - Added Confusion in the Ranks 2014-03-03 05:52:40 +00:00
drdev
61bb0cd8b6 Flesh out VPhases 2014-03-03 04:12:45 +00:00
drdev
ddae64716b Flesh out VPrompt 2014-03-03 02:52:39 +00:00
drdev
06192e71b8 Refactor how skin images are loaded
Further enhance match layout
2014-03-03 00:27:53 +00:00
drdev
4dec8f1329 Create basic match screen layout 2014-03-02 22:51:53 +00:00
drdev
04ad085e82 Replace tabs with spaces 2014-03-02 22:47:22 +00:00
drdev
859bc49f0d Ensure editions linked to cards properly 2014-03-02 21:22:06 +00:00
Chris
124174a564 Added new card names to changes.txt. 2014-03-02 15:44:06 +00:00
teferi
076783aac4 reverting module refactoring changes 2014-03-02 14:19:50 +00:00
teferi
f3aa6a56a6 upgrading android maven plugin for eclipse integration 2014-03-02 11:48:08 +00:00
teferi
2065010633 updating eclipse project files 2014-03-01 22:59:47 +00:00
teferi
e0ddddb365 moving res content to new forge resources module 2014-03-01 22:55:04 +00:00
teferi
664bbdb030 moving res content to new forge resources module 2014-03-01 22:54:46 +00:00
teferi
684f433878 moving res diretory to new forge resources module 2014-03-01 22:52:58 +00:00
teferi
fe2acaef1b moving res content to new forge resources module 2014-03-01 22:50:09 +00:00
drdev
722be1b5b3 Prevent stack overflow when cannot find skins 2014-03-01 13:32:43 +00:00
teferi
e0ddfd50b3 enhancing the configuration of mobile modules 2014-02-28 16:53:21 +00:00
Agetian
4dee0ff93d - Fixed the Remove Artifacts deck generation mode working in reverse. 2014-02-28 14:26:01 +00:00
teferi
e83c171aaa changing classpath delimiter from ; to : 2014-02-28 14:18:55 +00:00
Agetian
2475856f10 - Semicolon separator for classpath does not work on *nix systems - use the colon instead. 2014-02-28 14:06:54 +00:00
teferi
5de0bacd5f - added bunde module to the maven build
- bundle module now builds the distributable tar.gz file
- fixed gui test cases which needed files from moved res directory
2014-02-28 10:04:20 +00:00
teferi
3ae604d414 extracting res folder from gui module and moving it to the bundles module 2014-02-28 09:18:40 +00:00
teferi
3fb97dfe15 - Adding mobile modules to the maven BuildConfig.java
- moving mobile source and resource files to adhere to the maven conventions
- clean up of the poms
- regenerated the eclipse project files with mvn eclipse:eclipse to put them inline with the modifications of the poms
- adding structure of the bundle module
2014-02-28 09:11:29 +00:00
teferi
91163c6ccf - Adding dependencyManagement
- Adding enforcer plugin
2014-02-28 08:35:40 +00:00
swordshine
fc6584086e - Added Shieldmage Advocate 2014-02-28 04:30:40 +00:00
drdev
bef8f2cc69 Make starting a match work 2014-02-28 02:12:47 +00:00
drdev
1ce397c463 Allow starting match with random decks 2014-02-28 00:55:02 +00:00
drdev
c403326bef Tweak splash flow 2014-02-28 00:51:13 +00:00
Chris
7b79c8e191 Added new card names to changes.txt. 2014-02-27 14:05:01 +00:00
Sloth
0acc06e6d4 - Fixed Evoke not being recognized as a Permanent spell by the AI. 2014-02-27 13:29:52 +00:00
swordshine
b8791152be - Added Lethal Vapors 2014-02-27 12:45:17 +00:00
drdev
72fd1819e3 Support loading card database using background thread 2014-02-27 06:39:35 +00:00
drdev
9a22f8d8c3 Support rendering progress bar message 2014-02-27 06:01:57 +00:00
drdev
62a90c2d66 Position and render progress bar 2014-02-27 05:30:31 +00:00
drdev
bf36e8bd2a Display disclaimer on splash screen 2014-02-27 05:08:17 +00:00
Sloth
e6706d21b9 - Updated some scripts. 2014-02-26 17:14:33 +00:00
Chris
a161b3901e Added new card names to changes.txt. 2014-02-26 14:26:48 +00:00
swordshine
0f51e5944c - Missing file 2014-02-26 11:28:30 +00:00
swordshine
a20686d9cd - Converted Well-Laid Plans to script 2014-02-26 11:28:03 +00:00
swordshine
94a916be8c - Added Lost in Thought and Volrath's Curse 2014-02-26 10:10:27 +00:00
swordshine
7d6e22be67 - Fixed last commit 2014-02-26 07:51:46 +00:00
swordshine
14a9126933 - Better script for Daybreak Coronet 2014-02-26 07:35:33 +00:00
Sloth
5bc21dd200 - Fixed type of Rolling Thunder. 2014-02-26 06:33:40 +00:00
Sloth
aae7d09d02 - Fixed prompt of Street Spasm. 2014-02-26 06:24:12 +00:00
swordshine
83363d7491 - Better script for Price of Glory 2014-02-26 06:22:24 +00:00
swordshine
fbbab5110c - Added Price of Glory 2014-02-26 04:14:10 +00:00
swordshine
47e70694bf - Edition: Duel Decks Jace vs. Vraska 2014-02-26 02:34:40 +00:00
Sol
3228346ee1 - Small tweaks to the pet balance changes of Bird and Wolf, improved descriptions in the bazaar 2014-02-26 02:23:40 +00:00
Chris
9848cfc17d minor edit 2014-02-25 22:59:07 +00:00
Chris
9f56438c86 Added a fluff piece to the changes.txt file. 2014-02-25 16:30:43 +00:00
Chris
5e7e96ad62 Added a fluff piece to the changes.txt file. 2014-02-25 16:22:58 +00:00
Sloth
b88728dcd8 - Better fix for canPlayFromEffectAI. 2014-02-25 14:52:46 +00:00
drdev
bb837d1b3d Add SplashScreen 2014-02-25 14:44:32 +00:00
Chris
03a8915c83 Added new card names to changes.txt. 2014-02-25 14:11:12 +00:00
moomarc
4edbdc052c - Updated the quest pets with Sol's tweaks
- linked to new images (new file name so that we don't have to direct all users to find their token folders to delete the existing images)
2014-02-25 13:08:02 +00:00
Maxmtg
52cac29ca7 Deck import set recongition re-enabled 2014-02-25 09:26:07 +00:00
Sloth
c7758ca855 - Fixed canPlayFromEffectAI (i don't why a canPlay check was put there, but it's definitely not the right place, because it prevents stuff like suspend from working). 2014-02-25 09:15:06 +00:00
Sloth
7f3d5c4234 - Removed Voidslime from two quest decks. 2014-02-25 08:33:03 +00:00
swordshine
c8f5113aa8 - Added Veiled Crocodile 2014-02-25 07:53:21 +00:00
swordshine
dcc798eac9 - Updated scripts for cards with "Intervening If" state triggers
- Fixed Dark Depths
2014-02-25 07:36:03 +00:00
swordshine
31e5b0d4c0 - Experimental: fixed state triggers so they will trigger during the middle of the resolution of a spell or ability. (e.g. Cloudshift an Enchantment creature would fire Tethered Griffin's trigger) 2014-02-25 05:46:33 +00:00
moomarc
48f53491c6 - Added Arabian Nights theme. First user contrib to make the cut. Credit to 1224Deko 2014-02-24 16:26:19 +00:00
swordshine
358caeb54e - Fixed Astral Slide 2014-02-24 08:08:52 +00:00
swordshine
5167948b44 - Fixed NPE 2014-02-24 07:47:48 +00:00
Agetian
859e721566 - Experimental: display mana-related ability choices in the game log instead of in a message box. Non-mana ability choices will still be displayed in a message box as before. Currently using GameLogEntryType.LAND type of the entry for mana ability choices. 2014-02-24 07:25:22 +00:00
swordshine
d81003d4db - Fixed filterListByType (This should fix Night Dealings) 2014-02-24 04:43:25 +00:00
drdev
013467796b Make mobile game run without crashing 2014-02-24 04:11:52 +00:00
swordshine
3e162658ba - World Rule is now checked in SBA 2014-02-24 03:55:15 +00:00
drdev
ffc4ee0275 Fix compile errors 2014-02-24 03:34:41 +00:00
drdev
59d1f5c967 Replace tabs with spaces 2014-02-24 03:15:46 +00:00
Sol
ddf3351313 - Fixed Orcish Bloodpainter damage value 2014-02-24 02:38:23 +00:00
drdev
5eefcd35d4 Start working on setting up Constructed match 2014-02-24 02:26:07 +00:00
drdev
ed359d9926 Flesh out means of defining match launch parameters 2014-02-23 23:48:28 +00:00
drdev
18d04acbc9 Refactor to create base LaunchScreen class 2014-02-23 22:54:36 +00:00
drdev
fa65bb10a6 Add StartButton to other screens
Add references to core projects
2014-02-23 22:27:18 +00:00
drdev
2b8ec09fca Fix so clicking in empty area of Player panel focuses that player 2014-02-23 22:07:18 +00:00
drdev
bf3157511f Avoid use of Vector2 for FImage size 2014-02-23 19:25:00 +00:00
drdev
9b45f39399 Remove excess vertical padding from CardDetailPanel 2014-02-23 19:13:37 +00:00
drdev
87f23e783a Add a tiny bit more padding between p/t and horizontal line 2014-02-23 19:09:16 +00:00
drdev
2d6baafe97 Improve layout of CardDetailPanel 2014-02-23 19:01:35 +00:00
Maxmtg
4ff887959d fix incorrect mana bills for human (eg: ai plays Mana Leak, with Goblin Electromancer in play) 2014-02-23 14:12:53 +00:00
Sloth
d72e5d0f5d - Fixed Tornado. 2014-02-23 12:51:11 +00:00
Sloth
99417f7dc3 - Added the quest opponent Erebos 3 by Nordos. 2014-02-23 08:05:58 +00:00
drdev
7d5d593437 Add background behind header label 2014-02-23 07:51:12 +00:00
drdev
41d4db29d2 Increase font size of header caption 2014-02-23 07:32:08 +00:00
drdev
fc2fe0b3dc Add StartButton 2014-02-23 07:27:46 +00:00
drdev
a3a7ecaf6f Make sligtly better attempt at Back icon 2014-02-23 07:01:38 +00:00
drdev
205eb398f8 Make attempt at Back icon 2014-02-23 06:42:16 +00:00
drdev
1fe9c7dfc3 Fix display issue with drawing rectangles 2014-02-23 05:18:24 +00:00
drdev
6202c103c6 Remove unnecessary methods 2014-02-23 05:09:39 +00:00
drdev
5b12277d59 Ignore Thumbs.db in skin folders 2014-02-23 04:04:29 +00:00
drdev
c47376358c Add back and menu button to non-home screens 2014-02-23 04:04:00 +00:00
drdev
b48ace0cee Flesh out FLabel for mobile more 2014-02-22 21:07:44 +00:00
drdev
739462e4fa Prevent mouse getting stuck after double-clicking last item in List View to remove it 2014-02-22 19:44:31 +00:00
drdev
4cced802bc Prevent crash in ItemListView.getItemAtIndex 2014-02-22 19:26:05 +00:00
drdev
799bc25110 Prevent horizontal arrow button not going away when switching views in ItemManager 2014-02-22 19:15:39 +00:00
drdev
6aff03bae2 Add more screens
Add FLabel
Support FButton command on tap
Support visible/enabled at FDisplayObject level
2014-02-22 15:50:26 +00:00
Sol
cb50a185b6 - Remove extraneous text from Frozen Solid 2014-02-22 14:09:04 +00:00
Sol
03c32a6292 - Adding buttons the Troubleshooting section to improve users finding their profiles/content locations 2014-02-22 04:57:35 +00:00
Sol
fbddce946b - Card Detail panel needs to use CARDNAME for additional costs like it used to 2014-02-22 03:23:40 +00:00
swordshine
03df1df7dc - Commander decks generate 99 cards. 2014-02-22 01:08:51 +00:00
drdev
e0902eab8a Support relaying touch events to display objects 2014-02-22 00:51:45 +00:00
Chris
f8460f56d0 Cleared out the changes.txt file, now ready for new material. 2014-02-21 18:03:03 +00:00
Chris
d9a8f6581d [maven-release-plugin] prepare for next development iteration 2014-02-21 14:19:08 +00:00
Chris
6d9e785aec [maven-release-plugin] prepare release forge-1.5.13 2014-02-21 14:18:55 +00:00
Chris
e33be38fa6 Preparing the changes.txt file for the next beta build and release. 2014-02-21 13:48:15 +00:00
Sloth
734b6f748e - Fixed Souls of the Faultless. 2014-02-21 13:39:37 +00:00
Sloth
104e6dc306 - Fixed BecomesBlockedAi. 2014-02-21 13:35:34 +00:00
drdev
a336cd7b0e Start input handling 2014-02-20 22:17:39 +00:00
drdev
f62f83bdda Avoid enabling Scissors preemptively 2014-02-20 20:50:14 +00:00
drdev
08ec2cc9d9 Refactor Graphics to support clipping and avoid drawing things outside the bounds of its parent 2014-02-20 20:47:27 +00:00
moomarc
4425029892 - missed a commit 2014-02-20 17:04:39 +00:00
moomarc
3b571cb7ec - Moved Commander to Constructed match setup.
- Variants menu removed
2014-02-20 17:04:13 +00:00
drdev
8edd870602 Refactor out FContainer from FDisplayObject 2014-02-20 16:02:57 +00:00
Chris
f81c3f40b8 Added new card names to changes.txt. 2014-02-20 13:29:10 +00:00
drdev
0cd306d23b Fix support for alpha colors 2014-02-20 07:21:53 +00:00
drdev
cafff3f379 Add logo to home screen 2014-02-20 06:49:15 +00:00
drdev
04d336f674 Support rendering text 2014-02-20 06:31:40 +00:00
swordshine
4f8babf927 - Added Ogre Geargrabber 2014-02-20 05:33:38 +00:00
drdev
c2bbd84204 Make proper background texture be rendered 2014-02-20 04:33:10 +00:00
drdev
f87f3489d1 Make rendering work for mobile game 2014-02-20 04:29:10 +00:00
drdev
77329e8fe5 Refactor FSkin for mobile game 2014-02-20 02:09:35 +00:00
drdev
c947da28c2 More mobile game refactoring 2014-02-19 23:37:59 +00:00
drdev
de51f43301 Refactor mobile Forge game 2014-02-19 22:41:15 +00:00
Sloth
bec8706fcf - Added the hard quest opponent Surtr 3. 2014-02-19 14:43:22 +00:00
Chris
7b6026e17d Added new card names to changes.txt. 2014-02-19 12:38:37 +00:00
asepetci
1324b0754b Updated draft rankings 2014-02-19 06:49:21 +00:00
swordshine
7da1d97769 - Added Leonin Arbiter 2014-02-19 02:28:14 +00:00
Maxmtg
1b5ba15321 ai mana costs will be adjusted by game state 2014-02-18 23:31:33 +00:00
Maxmtg
b299711be7 This restores mana payment prompts (lost yesterday) 2014-02-18 20:28:03 +00:00
Agetian
164490ffc9 - Get rid of the TextUtil import, use the splitting convention used everywhere else in CardFactoryUtil. 2014-02-18 14:11:02 +00:00
Agetian
eadba12739 - Comment fixes. 2014-02-18 13:57:40 +00:00
Agetian
e52e154774 - Added a way to count specific colors of mana spent on X (Count$XColorPaid followed by a list of colors in one-letter abbreviation format e.g. Count$XColorPaid WUG).
- Added Soul Burn.
2014-02-18 13:55:15 +00:00
Chris
878c037554 Added new card names to changes.txt. 2014-02-18 12:52:43 +00:00
moomarc
03cdddce6e - Fixed a bug with team allocation for variant matches 2014-02-18 12:30:13 +00:00
swordshine
f23f17be4f - Fixed Chorus of the Conclave 2014-02-18 11:51:19 +00:00
Maxmtg
fa423233ab only remove javadoc and whitespace 2014-02-18 09:11:23 +00:00
Maxmtg
c9c15d0157 remove custom maps, use guava multimaps 2014-02-18 08:33:40 +00:00
drdev
1b2e23b309 Start working on mobile home screen 2014-02-18 06:29:48 +00:00
drdev
acaa61319f Support loading skins without crashing 2014-02-18 04:18:41 +00:00
drdev
c476415bfc Create symbolic links to allow asset files to be shared amongst gui projects 2014-02-18 03:51:03 +00:00
Sol
5e3786fe1c - Fix for Players not being assigned to any team causing issues from Quest mode 2014-02-18 03:04:40 +00:00
swordshine
07915701c3 - Added Jeweled Amulet 2014-02-18 02:45:28 +00:00
Maxmtg
b69228e28b I believe this would break ai's mana payment 2014-02-18 01:12:37 +00:00
Maxmtg
42fcd856d0 remove getManaPaid() from SpellAbility because there is already a method getPayingMana()
Remove input/InputPayManaExecuteCommands.java, using Common input instead
2014-02-18 00:35:45 +00:00
Maxmtg
22be9fffb6 moved some specific code to ai 2014-02-17 22:19:45 +00:00
moomarc
204f65faac - Archenemy moved to Constructed match setup
- Basic team setup implemented
2014-02-17 16:12:21 +00:00
moomarc
7e2b336ecc - Fixed previous commit 2014-02-17 16:10:14 +00:00
moomarc
df86422e1b - Attempt to implement a basic team victory 2014-02-17 15:53:41 +00:00
moomarc
89c2130ff6 - Attempt to stop AI players in multiplayer games from always only attacking the human until dead. They will now gang up on an opponent with less than 8 life but otherwise attack a random opponent. Feel free to improve the ai. 2014-02-17 15:47:04 +00:00
Sloth
9d90ca99cb - Improved DestroyAllAi. 2014-02-17 15:18:03 +00:00
Chris
f8224a0f7e Added new card names to changes.txt. 2014-02-17 14:58:15 +00:00
moomarc
eef2e004b3 - Improved AI for Idle Thoughts 2014-02-17 14:39:39 +00:00
moomarc
4fda7abaff - Removed unneeded import 2014-02-17 12:01:30 +00:00
asepetci
72aefc9152 Read rankings from cache instead of reading file every time. 2014-02-17 11:03:45 +00:00
Maxmtg
2feac87574 add all triggered abilities to stack when priority is gained, and after devmode cheat 'add to play' 2014-02-17 08:18:48 +00:00
drdev
adcceb74ee Fix so Unique Cards Only option saved between sessions 2014-02-17 07:53:35 +00:00
drdev
9d0db8580e Support saving filters being shown/hidden between sessions 2014-02-17 07:35:47 +00:00
drdev
7106098c91 Support saving column widths and positions between sessions 2014-02-17 07:23:20 +00:00
drdev
51acbeeab2 Fix typo 2014-02-17 07:07:54 +00:00
drdev
77f7031f44 Support saving many item manager options between sessions 2014-02-17 07:02:21 +00:00
drdev
447f07ef7f Refactor how ItemView configuration is setup 2014-02-17 05:08:05 +00:00
swordshine
83a1b4f35e - Prevent NPE when the spell is countered. 2014-02-17 04:33:58 +00:00
swordshine
8cbab3a5a7 - Updated some scripts 2014-02-17 04:16:10 +00:00
Sol
8fdadd61d0 - Added Perplexing Chimera (Exchange portion of ControlSpell) 2014-02-17 03:31:38 +00:00
Sol
1c8b589b1f - Improve description of Poultice Silver 2014-02-17 03:02:39 +00:00
Maxmtg
3d360d216b kill duplicate 2014-02-16 23:21:35 +00:00
Maxmtg
2194592016 This should track the mana paid for each spell 2014-02-16 23:18:21 +00:00
Sloth
7bccaa769a - Fixed playSpellAbilityForFree not being mandatory for the AI. 2014-02-16 20:25:09 +00:00
Sol
1982f73e3d - Added an Effect to gain Control of Spells.
- Added Commandeer
2014-02-16 17:15:44 +00:00
Sloth
4525633ad8 - Added the medium quest opponent Nekusar the Mindrazer 2. 2014-02-16 14:46:55 +00:00
Agetian
6c75215113 - Restore the operation of "remove" and "remove all" buttons in DualListBox so that it's possible to remove added elements one by one or all at once without having to add all the elements first. 2014-02-16 09:08:00 +00:00
Agetian
d841ed5858 - Fix loading skins that have cropped sprite_icons.png with no physical data for missing elements (e.g. the new targeting arrows). Will now return a fully transparent color instead of bailing out with a crash. 2014-02-16 04:12:48 +00:00
drdev
255d508437 Update tooltip for Ranking column 2014-02-15 20:15:31 +00:00
drdev
ee2da8d8cd Remove deprecated Preferences pane from Deck Editor
Reorganize Deck Editor default layout
2014-02-15 20:01:30 +00:00
drdev
c4e4bc1871 Add Unique Cards Only checkbox to options panel on Constructed Catalog 2014-02-15 19:54:27 +00:00
drdev
45ce34ff0b Support showing/hiding columns via checkboxes in options panel
Truncate ranking after 4 decimal places
2014-02-15 19:33:50 +00:00
drdev
f7256824bb Make arrow buttons account for insets 2014-02-15 18:09:27 +00:00
drdev
06f33d21ee Support horizontal scroll button for option panel 2014-02-15 18:00:22 +00:00
drdev
60ae9a110b Prevent both view buttons being toggled off 2014-02-15 17:29:13 +00:00
Agetian
dbabf696ce - Better place for a comment. 2014-02-15 17:12:17 +00:00
Agetian
bcac77bd0d - Non-combat and combat targeting arrows are now themed (use CLR_NORMAL_TARGETING_ARROW and CLR_EFFECT_TARGETING_ARROW).
- Default theme is updated to include a demonstration of where and how to specify the targeting arrow colors.
- Themes which do not have the targeting arrow colors specified will use the default red color with 60% opacity for the combat arrow and CLR_ACTIVE with 60% opacity (as before) for the non-combat arrow.
- Combat targeting arrow opacity is now defined by the theme, not hard-coded.
2014-02-15 17:08:30 +00:00
Agetian
030f6c3939 - Improved the visual appearance of targeting arrows.
- Targeting overlay now displays arrows for creatures attacking planeswalkers.
- Combat arrows (blocking creatures, attacking planeswalkers) are now displayed in red while non-combat arrows are displayed in the more neutral theme-based color.
- Optimized the display of targeting arrows in "always on" mode (should be somewhat faster when many arrows are displayed at once).
- Some refactoring and minor fixes in targeting overlay code.
2014-02-15 15:23:14 +00:00
moomarc
9fbf9903ef - fixed My Undead Horde Awakens 2014-02-15 12:26:30 +00:00
swordshine
0b67f989b9 - Converted keyword "If damage would be dealt to CARDNAME, prevent that damage. Remove a +1/+1 counter from CARDNAME." to script 2014-02-15 04:27:17 +00:00
Agetian
68e8b47838 - Fix the BasicLand definition for Born of the Gods booster packs (uses Theros lands now). 2014-02-14 15:37:18 +00:00
asepetci
52965b233f updated rankings.txt 2014-02-14 15:07:14 +00:00
swordshine
a239710a6b - Update Draft Rankings 2014-02-14 09:09:42 +00:00
drdev
4f86ee6025 Remove bin folders from SVN 2014-02-13 22:40:07 +00:00
Agetian
102468d2e3 - Fix a typo. 2014-02-13 16:53:18 +00:00
Sloth
ee8f8def8e - Prevent NPE in lifeInSeriousDanger. 2014-02-13 15:52:07 +00:00
Chris
4bc8a89544 Added new card names to changes.txt. 2014-02-13 14:59:38 +00:00
swordshine
e66a776f9f - Updated scripts for Sphere of the Suns 2014-02-13 08:38:09 +00:00
drdev
0961590f20 Remove unneeded UIManager call 2014-02-13 06:50:37 +00:00
drdev
8bf4345ac3 Work towards being apply to load skins for Android app 2014-02-13 06:48:53 +00:00
swordshine
e7f0776098 - Fixed a typo 2014-02-13 05:17:48 +00:00
swordshine
35d8ea0949 - Added Daxos of Meletis and Psychic Intrusion (only updated mana color conversion for human players) 2014-02-13 05:13:14 +00:00
drdev
59979056b9 Add start of mobile Forge gui 2014-02-13 04:54:38 +00:00
Sol
dbbb3741d7 - Removing awkward Skeleton Shard cost descriptions 2014-02-13 03:08:02 +00:00
Sloth
7ace65b8c9 - Added SVar:RemAIDeck:True to Peregrine Mask. 2014-02-12 21:29:09 +00:00
Sloth
dcccae1f7c - Fixed AI using Idle Thoughts. 2014-02-12 21:28:28 +00:00
Maxmtg
fa3a140470 fix crashes in deck import when 'use latest edition' is unchecked. 2014-02-12 18:23:42 +00:00
Sloth
d9b657acf4 - Fixed AI suspending Aeon Chronicler for 0. 2014-02-12 15:28:35 +00:00
moomarc
b9046d8326 - Implemented alternate token art parameter in TokenEffect
- updated Eldrazi spawn token generators to reflect correct brood lineage according to https://www.wizards.com/magic/magazine/Article.aspx?x=mtg/daily/arcana/472
- updated token urls with THS tokens
- updated Theros scripts with token image params
2014-02-12 10:12:27 +00:00
swordshine
5b70f38a9c - Fixed TokenTapped 2014-02-12 10:05:21 +00:00
drdev
f94fcfc997 Lock resize cursors when resizing dock panes 2014-02-12 06:50:16 +00:00
Sloth
73e835df10 - Fixed Demonic Tutor and friends revealing the fetched card. 2014-02-12 06:30:39 +00:00
drdev
3dc4594173 Fix so I-Beam cursor displayed when over text fields 2014-02-12 06:29:49 +00:00
drdev
1606bfa2c5 Show resize cursor when hover border between columns and while resizing column 2014-02-12 06:17:17 +00:00
drdev
b39e0f4052 Allow manual resizing of fixed width columns 2014-02-12 05:40:26 +00:00
drdev
f61ac6b361 Column tweaks 2014-02-12 04:41:00 +00:00
drdev
b447b4ab6b Avoid showing unnecessary Folder column in certain DeckManagers 2014-02-12 04:25:20 +00:00
drdev
968a035672 Support marking decks favorites similar to cards 2014-02-12 04:03:49 +00:00
drdev
d976bed702 Support restoring the current deck in the Constructed Deck Editor after closing and reopening Forge 2014-02-11 19:26:29 +00:00
Maxmtg
720a44b4fd change zone ai won't crash with oob 2014-02-11 09:37:55 +00:00
swordshine
fb2287b8c2 - Fixed RearrangeTopOfLibraryEffect 2014-02-11 05:03:26 +00:00
Maxmtg
6468dcc712 bugfix: for cases when no foil is present 2014-02-11 04:56:01 +00:00
Maxmtg
c5923c31e9 DGM booster generation fixes 2014-02-11 04:50:12 +00:00
Sol
7ab28b5226 - Improving two card details text 2014-02-11 04:48:41 +00:00
swordshine
f862a01a78 - Fixed ThisTurnEntered and LastTurnEnded so controller change effects will not count 2014-02-11 04:41:38 +00:00
swordshine
875d019b1c - Fixed 2 cards 2014-02-11 03:58:24 +00:00
Sol
a4271de319 - Remove a phased out token from the battlefield, instead of exiling it, so Attached permanents get permanently phased out 2014-02-11 02:12:13 +00:00
Sol
4d00ab3ecf - Fix crash related to the legendary rule 2014-02-11 01:15:16 +00:00
Sloth
bebe569d10 - Fixed Steamflogger Boss. 2014-02-10 20:03:30 +00:00
moomarc
1c147936d7 - Added links to the Theros booster pack images
- Removed some old Planechase and Vanguard variant stuff
2014-02-10 15:06:13 +00:00
Chris
7e9220d414 Added new card names to changes.txt. 2014-02-10 14:28:24 +00:00
Agetian
01867e5352 - Made FoilAlwaysInCommonSlot the default choice (since all current sets use this option anyway).
- Refactored the edition definitions, now slots newer than TSP do not include the FoilAlwaysInCommonSlot line, while the older sets with foils have a FoilAlwaysInCommonSlot=False line.
- Some definition fixes related to foil generation.
2014-02-10 10:18:56 +00:00
Agetian
09b638075c - Another MMA foil update. 2014-02-10 08:44:52 +00:00
Agetian
79a61f2e12 - Fix for the previous fix. 2014-02-10 08:38:40 +00:00
Agetian
ed39723ab6 - Fix Modern Masters definition to work correctly with foils. 2014-02-10 08:38:03 +00:00
Agetian
b22ce18572 - Fix imports. 2014-02-10 08:34:09 +00:00
Agetian
9b55d3c36b - Update the Modern Masters definition. 2014-02-10 08:33:36 +00:00
Agetian
02bb5942b3 - Get rid of a debug println. 2014-02-10 08:33:24 +00:00
Agetian
a72655fc79 - Read the foil chance in booster value from edition files as a US locale double. 2014-02-10 08:32:49 +00:00
Agetian
30fda0e7a8 - Simplify foil chance calculations, use double to represent chance. 2014-02-10 08:17:34 +00:00
Maxmtg
9957c12ff8 split Command interface - separate class for ui, and another one for game. 2014-02-10 08:11:32 +00:00
Maxmtg
bfee22e968 disbanded 'constant' class from game 2014-02-10 08:04:02 +00:00
Agetian
485aa06339 - Revert the previous representation of foil chances in booster (doesn't work the way I thought it would).
- Changed the default chance of a foil in booster to 0.2143 (21.43%) which seems to match the official 1 foil per 70 cards more closely.
2014-02-10 07:38:13 +00:00
Agetian
bd5471cb30 - A comment is not necessary here (moved elsewhere). 2014-02-10 06:56:40 +00:00
Agetian
39c83b4870 - A more intuitive way to represent foil chance in booster in edition files (1:6 instead of 1667, 1:1 instead of 10000).
- Updated Modern Masters definition file to use the new format.
2014-02-10 06:56:00 +00:00
swordshine
d32858b4c4 - Added False Dawn 2014-02-10 05:21:14 +00:00
Sol
de0348592b - Add an extra Restriction Matrix to handle Celestial Dawn for Mana Conversion
- Added Celestial Dawn
2014-02-10 03:22:19 +00:00
Maxmtg
804a8801e5 Moved ai to dedicated module, fix api dictionary 2014-02-09 21:12:26 +00:00
Maxmtg
dd34a3aa9b remove AI class from ApiType 2014-02-09 21:01:34 +00:00
Maxmtg
0f37de9627 removed another ai hook 2014-02-09 20:25:47 +00:00
Maxmtg
14a0e6e3ac by adding a bit ugly method to player controller, I've removed last isHuman check and the last reference from api executor to AI 2014-02-09 20:22:15 +00:00
Maxmtg
2f2d24eb3e move some ai-classes to right package 2014-02-09 20:15:58 +00:00
Maxmtg
06484f81f6 Separate AI decision making from SpellAbility classes 2014-02-09 20:05:05 +00:00
drdev
b3f019420f Fix so current quest deck remembered correctly 2014-02-09 19:47:33 +00:00
Agetian
2487f7ee93 - Modern Masters now correctly has a foil in every booster pack. 2014-02-09 19:38:54 +00:00
drdev
e9c4f0913d Fix so quest decks can be deleted properly 2014-02-09 19:18:57 +00:00
drdev
81c5912add Remove unused imports 2014-02-09 19:07:10 +00:00
Hellfish
767524fb57 *More overzealous rename refactoring done away with 2014-02-09 17:44:00 +00:00
Hellfish
40f7d164bf *Fix overzealous rename refactoring 2014-02-09 17:38:39 +00:00
Hellfish
1ff23dcc56 *Apparently the reintroduced TriggerReplacementBase was never added. It is now! 2014-02-09 17:33:14 +00:00
Agetian
a4e9aa6243 - Added the star icon to old-style (pre-8E) foils for authenticity. 2014-02-09 16:41:19 +00:00
Hellfish
50c40311a7 *Reintroduced TriggerReplacementBase as a specialized subclass of CardTraitBase 2014-02-09 16:03:27 +00:00
Chris
d331c87ab5 Added new card names to changes.txt. 2014-02-09 15:24:50 +00:00
Hellfish
c4e1552b8b *StaticAbility shares some functionality with Trigger and ReplacementEffect, extend their base instead of duplicating code 2014-02-09 14:42:39 +00:00
Hellfish
94783575cc *Prettied up TriggerReplacementBase 2014-02-09 14:14:08 +00:00
Hellfish
a54a0ba985 *Moved common functionality of Trigger and ReplacementEffect into base class. 2014-02-09 13:56:04 +00:00
swordshine
e9da0ec519 - Fixed Fact or Fiction 2014-02-09 11:19:54 +00:00
swordshine
8a9a13c5d7 - "enters the battlefield tapped with counters" now is a single replacement effect. 2014-02-09 10:43:27 +00:00
swordshine
85d967e5a5 - Fixed Eureka so these cards actually start with the activator when resolving 2014-02-09 10:39:48 +00:00
swordshine
453bf76d63 - Added Fearsome Temper 2014-02-09 10:36:23 +00:00
swordshine
72bb290215 - Added Contamination 2014-02-09 10:30:21 +00:00
swordshine
6230b6f28b - Converted "CARDNAME enters the battlefield tapped unless you control a" keyword to an ETBtapped replacement effect. 2014-02-09 10:28:35 +00:00
swordshine
0f5228259a - Fixed Mistbind Clique 2014-02-09 10:18:46 +00:00
Sloth
4b5bd3d619 - Added Vortex Elemental. 2014-02-09 09:10:38 +00:00
Maxmtg
1ad1714388 fix hybrids payment {2/C} 2014-02-09 07:22:08 +00:00
drdev
f10fd27869 Fix so view has focus when opening FDeckViewer 2014-02-09 06:05:56 +00:00
drdev
1f883c993b Fix so switching group by options retains all groups being collapsed
Add option to group by rarity
2014-02-09 05:30:14 +00:00
drdev
319b470acd Prevent crash when attempting to being build Draft deck immediately after ending drafting process and saving the draft 2014-02-09 05:10:51 +00:00
Agetian
e09ec6c165 - Better variable name. 2014-02-09 04:45:40 +00:00
Agetian
1fa0a2c81c - Fixed a bug in booster generator that caused the foil from a wrong print sheet to be generated for sets that did not have a foil always in common slot. 2014-02-09 04:41:54 +00:00
Sol
a8e54c5052 - Added Warping Wurm by squee1968 2014-02-09 03:39:53 +00:00
drdev
f17fa767c0 Sort draft pack by rarity then by color 2014-02-09 02:57:00 +00:00
Sol
c8eed79a2a - Initial checkin for Additive Mana Conversion Static Ability (Restrictive Conversions currently not 100% correct)
- Added Mycosynth Lattice
- Fixed Sunglasses of Urza
2014-02-09 02:37:09 +00:00
Sol
537f95c79d - Fixed infinite loop caused by Max's trigger fixes when no triggers are on the stack 2014-02-09 02:10:19 +00:00
Maxmtg
c923a7d976 fix comile erre 2014-02-08 22:49:56 +00:00
Maxmtg
b0939aeed8 bug fix 2014-02-08 21:10:23 +00:00
Maxmtg
a7d359fa10 loop until nothing added to stack, AP is turn owner 2014-02-08 20:52:02 +00:00
drdev
862d8ed857 Fix so foils display properly in CardManager Image Views 2014-02-08 20:41:07 +00:00
drdev
83cebd7e82 Fix label 2014-02-08 20:26:30 +00:00
Maxmtg
1eeab52cdf all player will add their triggers to stack when ANY player has priority 2014-02-08 20:24:35 +00:00
Agetian
686807b0d2 - A closer approximation of foil chance in booster (16.67% for 1:6 ratio instead of just 16%). 2014-02-08 20:03:01 +00:00
Agetian
f0464395ab - A little correction. 2014-02-08 19:55:25 +00:00
Agetian
87de44dd04 - Added information about extended foil support to CHANGES.txt. 2014-02-08 19:55:06 +00:00
Agetian
5fe65ad74b - Added a preference to support enabling/disabling foil overlay display in GUI.
- Tied the card panel foil display to the user preference setting.
2014-02-08 19:35:36 +00:00
drdev
58600fbfad Lock input while refreshing images 2014-02-08 19:34:37 +00:00
drdev
c92be334ae Maximize space for viewing pack cards by eliminating Choose Card button and hiding view options by default 2014-02-08 18:51:55 +00:00
drdev
8276b5c51a Support apply foil effect to card images in CardManager Image View 2014-02-08 18:29:04 +00:00
Agetian
d7224d7515 - Fixed a bug that caused the game to crash when generating boosters with no specified code (fixes full cardpool draft).
.
2014-02-08 18:24:04 +00:00
drdev
96ff2dc09e Support hiding filters by default on Draft screen 2014-02-08 18:23:21 +00:00
Agetian
a40da18132 - Added Born of the Gods quest precons. 2014-02-08 17:34:49 +00:00
drdev
8cb889da68 Prevent horizontal line appearing when hiding filters and not showing button panel 2014-02-08 17:28:21 +00:00
drdev
08d2d7f4e8 Prevent Add Player button getting stuck 2014-02-08 17:22:39 +00:00
Maxmtg
e9c273e40f logic optimized 2014-02-08 17:13:35 +00:00
Maxmtg
9500b3d951 acquire booster edition once 2014-02-08 17:07:15 +00:00
drdev
2b4e935373 Align buttons 2014-02-08 17:01:23 +00:00
Agetian
4f9fd821ec - Added foil generation in booster packs (the UI support is currently incomplete, foils will not be distinguished in deck editors or displayed in pile view or booster card list for now; also, there is currently no option to disable the foil visual effect in GUI). 2014-02-08 16:16:23 +00:00
Agetian
b221b7eaab - Added a method to add a color replacement to ManaPool.
- Fixed a mistype in method name.
2014-02-08 16:04:54 +00:00
Chris
4b8ed1df67 Added new card names to changes.txt. 2014-02-08 15:19:30 +00:00
Chris
9399097069 Cleared out the changes.txt file, now ready for new material. 2014-02-08 15:17:27 +00:00
Maxmtg
337f5b7320 clean up code style 2014-02-08 15:01:46 +00:00
Agetian
80c70d321e - Append the foil suffix to the card name instead of to the end of the line (looks better in the deck file and fixes foil card recognition). 2014-02-08 13:16:36 +00:00
Maxmtg
676fee32c6 renamed add/subtract methods, fixed bug with colorless payment 2014-02-08 12:56:54 +00:00
Maxmtg
715ee1f9ab color conversion routine for mana implemented 2014-02-08 12:21:55 +00:00
Maxmtg
c5a791f361 more paths require manapool 2014-02-08 11:33:17 +00:00
Maxmtg
1ec656f2ed ManaCostBeingPaid no longer be built from string, its "pay" methods require reference to manaPool (which is to hold color replacement rules) 2014-02-08 11:26:27 +00:00
Sloth
97b579a68d - Fixed Lightning Volley. 2014-02-08 07:47:31 +00:00
drdev
59f75710dc Add Expand/Collapse all groups button to Image View 2014-02-08 04:47:45 +00:00
drdev
c7e74b2ddc Add combo box as way to change column count in addition to Ctrl+MouseWheel 2014-02-08 02:54:59 +00:00
drdev
6380b4c8fe Change image scaling method to be based on column count rather than fixed size 2014-02-08 02:21:27 +00:00
Sol
3d4f9e7297 - Committing Ertai's Familiar and Shimmering Efreet by squee1968 2014-02-07 17:29:15 +00:00
Chris
bfe48d2611 [maven-release-plugin] prepare for next development iteration 2014-02-07 17:25:48 +00:00
Chris
3c08718b4b [maven-release-plugin] prepare release forge-1.5.12 2014-02-07 17:25:37 +00:00
Chris
2f033f795f Preparing the changes.txt file for the next beta build and release. 2014-02-07 15:10:33 +00:00
drdev
acd2ca2f23 Add GroupBy and PileBy combo boxes to Image View 2014-02-07 07:42:56 +00:00
drdev
de2731c21f Group sealed pool by color by default 2014-02-07 06:36:26 +00:00
drdev
5e0a8a6331 Add view options panel to ItemManager 2014-02-07 06:26:28 +00:00
drdev
b34ca7b951 Support canceling when selecting block or custom draft format when setting up a new draft or sealed deck
Prevent crash if you select a block that has no sets
2014-02-07 05:20:08 +00:00
drdev
1422748447 Prevent double-click failing after a previous double-click on a control opened a different screen 2014-02-07 04:25:31 +00:00
drdev
186f7f70e4 Fix so hover doesn't get stuck after right-clicking card in deck viewer 2014-02-07 04:11:56 +00:00
drdev
4b1eb98e5b Make Image View the default in all decklist ItemManagers 2014-02-07 04:05:45 +00:00
drdev
f7e185be3b Fix flaw with previous fix 2014-02-07 03:55:10 +00:00
Agetian
ea6da0b7dc - Make the zebra skin color on Marble Blue skin easier on the eyes. 2014-02-07 03:51:25 +00:00
drdev
ae23652c0c Avoid odd display when first opening image view 2014-02-07 03:51:17 +00:00
drdev
54b86b4db2 Update CHANGES.txt 2014-02-07 03:32:25 +00:00
drdev
f45779d2c3 Don't enforce 4-of card limit in deck editor if not enforcing deck legality 2014-02-07 03:28:13 +00:00
drdev
480ebbb121 Include information about ItemManager ImageView in CHANGES.txt 2014-02-07 01:00:12 +00:00
Chris
427e8c7059 Added new card names to changes.txt. 2014-02-06 15:01:20 +00:00
RumbleBBU
86cf1b63f4 Fixed quest starting pool color bias selection. 2014-02-06 08:25:41 +00:00
drdev
27ee03494b Improve restored scroll position after adjusting image view zoom 2014-02-06 05:36:46 +00:00
Maxmtg
2f5799f453 routed all checks like 'can pay for this shard with mana of certain color' through either player's manapool, or a method in ManaCostBeingPaid. Will add a color conversion matrix at these 2 points later. This change is a prerequisite to implement cards like Daxos of Meletis 2014-02-06 04:55:30 +00:00
drdev
7c419d875d Fix so image size goes from 50 to 300 2014-02-06 04:52:17 +00:00
Maxmtg
d7d87b5c5d CardDb is now able to report the unique missing cards (it's not a good idea to keep it all in ctor, should refactor later) 2014-02-06 04:00:51 +00:00
Sol
a11e7bbcb8 - Introduce PhaseIn and PhaseOut triggers
- Added Teferi's Imp (as an example of both)
2014-02-06 03:01:21 +00:00
drdev
028e4bc196 Support image view scaling using Ctrl+MouseWheel 2014-02-06 02:28:54 +00:00
Sloth
2252b9908b - Updated mtg-data.txt. 2014-02-05 17:05:21 +00:00
Sloth
02353704ca - Fixed Seize the Soul and friends. 2014-02-05 16:35:14 +00:00
Sloth
2bde0ac099 - Fixed lands with "May be played by your opponent" being playable by the owner. 2014-02-05 16:11:59 +00:00
Chris
2543aabbd4 Added new card names to changes.txt. 2014-02-05 13:25:59 +00:00
Maxmtg
d01c22b5f9 Change zone - only the choose card left inside if condition 2014-02-05 08:15:56 +00:00
swordshine
08896bdb8e - Converted "When CARDNAME is dealt damage, destroy it." keyword to script 2014-02-05 06:28:17 +00:00
swordshine
46d7491c78 - Update scripts 2014-02-05 06:26:05 +00:00
swordshine
9437ea5d90 - Converted Fastbond and Naya to script
- Missing file for Felhide Spiritbinder
2014-02-05 06:23:45 +00:00
swordshine
184943da83 - Fixed some scripts 2014-02-05 06:21:41 +00:00
swordshine
66e53ad1ed - Added Felhide Spiritbinder, Hunter's Prowess, Lightning Volley 2014-02-05 06:17:49 +00:00
Maxmtg
6595893e48 Add BNG cycle of creatues with "inspired - pay {2}{C} to put some tokens onto battlefield"
Fix: Oracle text for Searing Blood
2014-02-05 06:14:52 +00:00
Maxmtg
14ac5860f8 removed from EXT banlist cards whose editions left the format 2014-02-05 05:40:25 +00:00
drdev
4554d94f32 Prevent crash when Control clicking a selected card 2014-02-05 03:26:01 +00:00
drdev
737b2eb0f7 Prevent FMouseAdapters getting screwed up if popup appears between mouse down and mouse up 2014-02-05 02:03:07 +00:00
drdev
cb318eb8b9 Ensure scrolled to top after loading deck in list view 2014-02-05 01:25:52 +00:00
drdev
557035e340 Focus list when header clicked
Improve behavior of removing items in Image View
2014-02-05 01:21:48 +00:00
drdev
86bd570e2c Lock hovered item while context menu or zoomer open 2014-02-05 00:41:58 +00:00
drdev
d406114118 Add middle (and left+right) click zoom support to Image View 2014-02-05 00:15:24 +00:00
drdev
e4dd0faf5e Code cleanup 2014-02-04 23:02:04 +00:00
drdev
83aa60a77c Code cleanup 2014-02-04 22:59:12 +00:00
Sloth
acfe00d6db - Fixed a bug in ChooseSourceAi. 2014-02-04 19:55:45 +00:00
Maxmtg
d4a2ae07df code formatting 2014-02-04 18:13:56 +00:00
Maxmtg
926bdc1d5a Fix wrong filtering in 2 piles effect 2014-02-04 18:13:45 +00:00
drdev
ffee3af0ac Use same border for hovered and selected items 2014-02-04 18:06:33 +00:00
Maxmtg
42e6dffda2 Fixed problem with antes being drawn before players are assigned 2014-02-04 18:02:06 +00:00
drdev
c9db375d7c Fix multiple selection for image view 2014-02-04 17:53:30 +00:00
drdev
06de741370 Prevent auto-selecting card when first opening deck, changing filters, or expanding/collapsing groups 2014-02-04 17:45:23 +00:00
drdev
a2287aff5b Improve appearance of group headers
Allow deselecting cards in image view
2014-02-04 17:25:28 +00:00
drdev
444aad2034 Wrap piles 2014-02-04 16:10:27 +00:00
Chris
0de852043e Added new card names to changes.txt. 2014-02-04 14:49:52 +00:00
Sloth
9df1102514 - Added a space to message. 2014-02-04 14:24:06 +00:00
Sloth
8eaa535d6b - The AI will no longer kill itself with Mogis, God of Slaughter. 2014-02-04 13:59:44 +00:00
Sloth
b5e7de67a2 - The AI will no longer kill itself with Vendetta. 2014-02-04 13:47:55 +00:00
swordshine
f4db8078b8 - Converted Chains of Mephistopheles to script (it's a normal replacement effect, the original hardcoded script is not correct) 2014-02-04 08:13:50 +00:00
swordshine
21db65e9ab - Update state-based actions (704_5r now fire remove counter triggers, Brother Yamazaki now work correctly with Humility) 2014-02-04 08:09:25 +00:00
swordshine
1d0b60427d - Fixed ETBtapped effect
- Converted Transmute to script
2014-02-04 08:06:01 +00:00
swordshine
1760b10940 - Update scripts 2014-02-04 08:03:20 +00:00
swordshine
ce54805981 - Update banlist 2014-02-04 07:54:52 +00:00
swordshine
6df75248d8 - Added Gild and Satyr Firedancer 2014-02-04 07:52:47 +00:00
drdev
21331d4189 Support sorting cards into piles 2014-02-04 06:36:52 +00:00
drdev
c1e72c380b Prevent unnecessary refresh when setting up Image View groupBy/pileBy 2014-02-04 04:35:42 +00:00
drdev
b38346e00c Prevent changing collapsed state of empty group 2014-02-04 04:29:16 +00:00
drdev
9e5cbbb9d1 Prevent prompting to leave draft when exiting after already leaving a draft 2014-02-04 04:24:59 +00:00
drdev
f767ca34ce Fix so programatically selecting an item in collapsed group auto-expands group 2014-02-04 04:07:16 +00:00
drdev
d4bc720dd0 Fix so selection on Image View not lost on resize 2014-02-04 03:56:04 +00:00
drdev
1d1950d3cb Fix so hovering cards in FDeckViewer shows Details/Picture in dialog as expected 2014-02-04 03:50:00 +00:00
drdev
038418ca0d Fix selection after expand/collapse group 2014-02-04 03:29:34 +00:00
drdev
4aa2dd4471 Prevent auto-expanding groups when filters change
Fix how multi-type cards are grouped
2014-02-04 03:04:41 +00:00
drdev
075a01e3ae Fix display glitch 2014-02-04 02:14:55 +00:00
drdev
35ea4c2a50 Add grouping support for Deck editors 2014-02-04 01:56:46 +00:00
Sloth
bc851d0b51 - Fixed spells cast by AF Play effects (like Isochron Scepter) not triggering cast spell triggers (like storm). 2014-02-03 20:08:25 +00:00
Sloth
c11d353540 - Fixed Searing Blood. 2014-02-03 19:59:50 +00:00
Sloth
32e6da4a78 - Fixed Herald of Torment. 2014-02-03 19:40:26 +00:00
Chris
a96f9be77a Added new card names to changes.txt. 2014-02-03 13:52:35 +00:00
Maxmtg
04a38b79ac Old-format decks will load without exceptions 2014-02-03 08:16:44 +00:00
Maxmtg
a1886d51f8 mana effect - will give all colors to choose from if manaAb.expressChoice was empty 2014-02-03 06:41:14 +00:00
Agetian
9cd2bc595d - Fixed ManaEffect with AnyMana crashing, e.g. for Chromatic Star (temporarily fixed it by reverting the relevant part to the previous version, feel free to revert and commit a more optimal fix) 2014-02-03 06:25:51 +00:00
Maxmtg
e592d3bc56 add god-favoured general (script by moomarc) 2014-02-03 05:33:58 +00:00
Sol
1da213b157 - Improved Card Detail description of Buyback and Entwine 2014-02-03 04:43:37 +00:00
Sol
3f349d0eb3 - Improved Card Detail description of Suspend 2014-02-03 04:33:43 +00:00
Sol
84cac99a59 - Improved Card Detail description of Echo 2014-02-03 04:11:12 +00:00
Sol
de1b198f4c - Adding Mana symbols to Unnerving Assault 2014-02-03 03:22:25 +00:00
Sol
5954e7053c - Adding Mana symbol to Vigor Mortis 2014-02-03 02:46:02 +00:00
Maxmtg
1b4b9ad32b change zone... still didn't dare to change it =) 2014-02-02 18:11:32 +00:00
Agetian
394e96d051 - A little clarification in CHANGES.txt. 2014-02-02 15:42:16 +00:00
Chris
2c6151996e Added a fluff piece to the changes.txt file. 2014-02-02 15:22:36 +00:00
Maxmtg
5c195f3cea moved forge.net.protocol to .net project 2014-02-02 13:31:55 +00:00
Maxmtg
1af6d101e8 fix mana atoms (bug emerged with 24602) 2014-02-02 12:32:46 +00:00
Maxmtg
b6b220496b do not add target folder into svn 2014-02-02 11:17:49 +00:00
Maxmtg
ff92c4cf31 add forge.net project (to hold network protocol, FServer and similar things) 2014-02-02 11:16:39 +00:00
Maxmtg
12ed04a7cc non-supported cards will have a default image 2014-02-02 10:56:44 +00:00
Maxmtg
6575000c28 better loading of unsupported cards 2014-02-02 10:26:22 +00:00
Agetian
43f4e45827 - Some more error message mistype / spelling fixes. 2014-02-02 10:22:49 +00:00
Agetian
4b6e58ddf0 - A little mistype fix. 2014-02-02 10:19:59 +00:00
Maxmtg
0abdf7a3b5 CardDb - unsupported cards detection
CardPool - fix bug in decks save
2014-02-02 10:03:41 +00:00
Maxmtg
53e0a2ad37 createUnsuportedCard -> cardDb 2014-02-02 09:39:22 +00:00
Agetian
7e22527164 - Send unsupported card names to the console so that the user is aware of which cards failed to load when the decks were parsed. 2014-02-02 09:22:49 +00:00
Maxmtg
7e6928d700 Split Deck- storage and serializer parts into their own classes 2014-02-02 09:11:48 +00:00
Agetian
4fa37ac4b9 - Delete the unwanted file that got pulled into the last commit. 2014-02-02 08:51:34 +00:00
Maxmtg
bbe5e3c556 small tweaks 2014-02-02 08:51:03 +00:00
Agetian
4c7f16baf4 - Most random card pools (quest shop, quest starting pool, sealed deck, booster draft) will now generate only one kind of Zendikar lands (full art or standard art) at a time instead of mixed art of both kinds. 2014-02-02 08:44:46 +00:00
Maxmtg
cec3d26493 re-arranged deck serialization code to make it more "symmetric": the what is serialized somewhere tends to be de-serialized in the same class 2014-02-02 08:39:12 +00:00
Maxmtg
86edf9fd66 nothing important 2014-02-02 01:56:26 +00:00
Maxmtg
0adcfe55aa made deck color filters null-tolerant 2014-02-02 01:53:45 +00:00
Maxmtg
5a22e6a15d generated decks will not attempt to calculate their color 2014-02-02 01:49:00 +00:00
Maxmtg
4d833b6f38 getColor method moved to DeckProxy 2014-02-02 01:42:54 +00:00
Maxmtg
d05ecdf840 propper filtering of deck proxies 2014-02-02 01:40:32 +00:00
Maxmtg
1f66ec432d shifted MagicColors 1 bit to the right 2014-02-02 01:08:53 +00:00
drdev
2fcc5943fa Refactor Sections to Groups and create enum for grouping items 2014-02-02 00:53:03 +00:00
Maxmtg
08e909ca00 remove another isHuman check 2014-02-02 00:28:24 +00:00
Maxmtg
4c48e3e089 Reveal empty list won't crash the game 2014-02-02 00:05:41 +00:00
Maxmtg
d9d32f7508 fix hangs when playing spell from devmode that triggers something
remove unneeded code
2014-02-01 23:53:08 +00:00
Maxmtg
691c52fff9 Forge will no longer crash when there are decks with unsupported cards. These cards will appear in decks and games player starts as a dummy without cost, types, abilities, but with explanation in card's text 2014-02-01 21:43:42 +00:00
drdev
c3d7a9f075 Refactor so Image View shares sort order of List View 2014-02-01 21:16:12 +00:00
Maxmtg
da3b2c1dc1 "take priority" changed: now on priority SBA is checked, triggers are ordered, then player is asked for spell they want to play, then spell is played. Until player refuses to choose a spell, that means "I pass" 2014-02-01 20:43:20 +00:00
drdev
2ea69dde48 Show picture and details on hover for image view 2014-02-01 19:31:55 +00:00
Chris
7c66069ee3 Cleared out the changes.txt file, now ready for new material. 2014-02-01 14:36:16 +00:00
Sol
fd9ee6f4e1 - Fix Clean remembered line for Arbiter of the Ideal 2014-02-01 13:59:53 +00:00
Sloth
6314550377 - AI can now target with Tyrant of Discord. 2014-02-01 09:22:15 +00:00
Agetian
738fc7f52d - Fixed the Suspended Sentence precon description. 2014-02-01 07:02:12 +00:00
drdev
4c129ffee4 Add hover effect to ImageView 2014-02-01 04:47:14 +00:00
Sol
c1750989b7 - Fixing Asphyxiate cost 2014-02-01 01:53:21 +00:00
drdev
2b685348ab Add image view to item managers 2014-02-01 01:16:43 +00:00
Maxmtg
070fd7695a phase won't end if players are allowed to have priority and there are sim-stack entries to be added 2014-01-31 23:59:54 +00:00
Maxmtg
7cf1a52405 orderSimultaneousStackEntries only when player gains priority 2014-01-31 21:51:50 +00:00
Maxmtg
096f41172d remove some playertype checks 2014-01-31 19:57:59 +00:00
Chris
59665029d2 [maven-release-plugin] prepare for next development iteration 2014-01-31 16:18:08 +00:00
Chris
3249e844f9 [maven-release-plugin] prepare release forge-1.5.11 2014-01-31 16:17:57 +00:00
Chris
187c90c7df Preparing the changes.txt file for the next beta build and release. 2014-01-31 15:40:38 +00:00
Chris
d779034da8 Added new card names to changes.txt. 2014-01-31 15:36:38 +00:00
moomarc
429d8dbf30 - Added Searing Blood 2014-01-31 07:46:08 +00:00
Maxmtg
c5d35c9596 added a method: magic color form char 2014-01-31 05:55:30 +00:00
Maxmtg
23265d2623 moved a method from ai to effect class (because the code being moved does not take decisions) 2014-01-31 05:12:45 +00:00
drdev
4810518d74 Code cleanup 2014-01-31 00:22:14 +00:00
Sloth
1e389fdef8 - Added oracle texts to BNG cards. 2014-01-30 21:57:20 +00:00
Sloth
f31550732e - Added Forsaken Drifters, Servant of Tymaret and Warchanter of Mogis. 2014-01-30 21:45:54 +00:00
drdev
29876aeb28 Code cleanup 2014-01-30 20:50:23 +00:00
Sloth
a90c34aac4 - Updated some SVars. 2014-01-30 19:34:17 +00:00
moomarc
78456d6333 - Removed duplicate script for Sapphire Drake 2014-01-30 17:47:11 +00:00
moomarc
44edc80abc - BNG: Added Pain Seer 2014-01-30 17:45:55 +00:00
Sloth
3f6e6f54a1 - Updated some SVars. 2014-01-30 16:38:46 +00:00
moomarc
1e576cfde6 - BNG: Added Black Oak of Odunos 2014-01-30 16:15:59 +00:00
moomarc
07c4ab24e7 - BNG: Added Retraction Helix 2014-01-30 16:02:34 +00:00
Sloth
915a6a42c2 - Added Sphinx's Disciple and Stratus Walk. 2014-01-30 13:27:34 +00:00
Chris
5216b35688 Added new card names to changes.txt. 2014-01-30 13:25:04 +00:00
Maxmtg
3c53eec798 fix CostRemoveCounter for X counters 2014-01-30 07:10:13 +00:00
moomarc
db080d8b10 - BTG: Added Acolyte's Reward 2014-01-30 06:46:58 +00:00
drdev
04d129b8d8 Cleanup look of vanguard and planar deck panels 2014-01-30 02:30:11 +00:00
drdev
059e7f7920 Fix so first player's avatar has focus when Forge first opened 2014-01-30 01:58:49 +00:00
drdev
3bbfe87868 Code cleanup 2014-01-30 01:48:57 +00:00
Sloth
8cdc76427e - Added Kraken of the Straits and Meletis Astronomer. 2014-01-29 19:58:07 +00:00
Maxmtg
11976bf964 fix year of BNG set 2014-01-29 17:20:38 +00:00
Maxmtg
a5f4f78018 won't throw when not expected 2014-01-29 17:02:32 +00:00
Maxmtg
0621f2e242 refactor isAPermanentType to be less ugly 2014-01-29 16:59:06 +00:00
Chris
5538480862 minor edit. 2014-01-29 16:10:42 +00:00
Sloth
07f126cb52 - Updated Cloudstone Curio. 2014-01-29 15:47:45 +00:00
Sloth
a5263b1375 - Updated scripts of Blind Fury, Bloodletter Quill, Goblin Warchief and Opal Palace. 2014-01-29 15:11:25 +00:00
Sloth
6a52bdf10d - Merged BNG branch into trunk. 2014-01-29 15:00:25 +00:00
moomarc
ad38be34b7 - updated Changes.txt to reflect the latest state of the new constructed match screen 2014-01-29 11:05:33 +00:00
moomarc
a7785b0d1b - disabled checkboxes for Archenemy and Commander in constructed match setup.
- disabling a variant now updates the deck selector as appropriate
2014-01-29 10:57:16 +00:00
moomarc
26743d0ca0 - uploaded missing precon images and updated download URLs 2014-01-29 10:19:13 +00:00
moomarc
fccc8f129f - formalised/fixed some precon image names/links
- added Sol's python script for checking for missing precon images
2014-01-29 08:43:57 +00:00
Maxmtg
c1a11dd89a natural ordering of cards now includes art idnex 2014-01-29 06:49:48 +00:00
Agetian
0730e2d774 - Changed typeContains so that it can correctly identify Planes apart from Planeswalkers (fixes the card zoomer incorrectly showing planeswalkers rotated 90 degrees). 2014-01-29 06:46:51 +00:00
drdev
a8bf257391 Refactor Spell Shop prompts to only appear once no matter how many items are being bought/sold together 2014-01-28 22:51:56 +00:00
Agetian
86f6a9e3f1 - Attempt to fix image cache visualizing wrong card pictures for cards with multiple art. 2014-01-28 16:24:38 +00:00
Chris
41f3b22237 Added new card names to changes.txt. 2014-01-28 15:17:03 +00:00
Maxmtg
7ad5bfb581 rollback bug 2014-01-28 09:31:20 +00:00
Maxmtg
75e5c8d0ca fix precon loading issues 2014-01-28 07:32:10 +00:00
Maxmtg
1b9437ad32 fix artindex 2014-01-28 07:11:41 +00:00
Maxmtg
d5bde7570a correct picture 2014-01-28 06:58:48 +00:00
Maxmtg
a0d13578f3 artIndex inside the very cards is 1-based as well (no more adjustments of +/-1 needed) 2014-01-28 06:56:42 +00:00
Maxmtg
ed48547f36 very minor tweaks 2014-01-28 03:50:28 +00:00
Agetian
73b97fe151 - Fix for the previous commit. 2014-01-27 18:18:43 +00:00
Agetian
f21e1c3f8a - Make generated quest card pool indices 1-based. 2014-01-27 18:15:54 +00:00
Maxmtg
aa230be806 quest save indices 2014-01-27 17:53:35 +00:00
Maxmtg
26bb8e5009 art index bugfix for decks being loaded 2014-01-27 17:37:54 +00:00
Agetian
5322d5a9c2 - Reapply the previous NPE fix. 2014-01-27 16:06:36 +00:00
Agetian
0f5eb7d5f8 - An alternate NPE fix as suggested by Max. 2014-01-27 15:47:35 +00:00
Agetian
9379f7283c - Added descriptions to new precon decks.
- Fixed a NPE when trying to show the description of a precon in spell shop that lacks the description line in its metadata.
2014-01-27 15:45:24 +00:00
Maxmtg
29025cce61 step 2 on hidden origins 2014-01-27 08:48:28 +00:00
Maxmtg
7fd201d5e3 merge ChangeZoneEffect.java hidden part to make it invariant of player types (step 1) 2014-01-27 07:52:13 +00:00
moomarc
1f947d5781 - selecting a vanguard avatar updates the button label 2014-01-27 07:52:01 +00:00
Agetian
8dea53bcda - A better fix for the custom booster draft NPEing 2014-01-27 07:06:20 +00:00
Agetian
f5d43d0986 - Fix imports. 2014-01-27 06:43:13 +00:00
Agetian
cf67fb456e - Temporarily revert the previous fix, will recommit a better one soon. 2014-01-27 06:42:35 +00:00
moomarc
308814bdca - removed a few unnecessary lines 2014-01-27 05:51:06 +00:00
Agetian
149a9bd7b2 - Fix a crash when choosing Custom Draft.
- Note that this fix gets rid of a seemingly useless/buggy piece of code in GuiChoose, I can't remember why if there was a good reason for it in the first place. Please report if I broke something else by removing it.
2014-01-27 05:39:42 +00:00
Agetian
e16998beb5 - Fixed the ability to choose to use the deck-default Vanguard avatar. 2014-01-27 05:22:19 +00:00
Maxmtg
a9e12e38ef update something on ai/human playertype change 2014-01-26 22:26:25 +00:00
Maxmtg
9c7d25f49d arranged components inside a panel 2014-01-26 22:02:57 +00:00
Maxmtg
a52a1f5820 Threw in an idea for playerPanels in constructed screen 2014-01-26 18:54:10 +00:00
Agetian
e0c3244667 - Compilation fix 2014-01-26 17:17:33 +00:00
moomarc
32bf18781a - Vanguard matches now launched via constructed match screen 2014-01-26 15:51:43 +00:00
Chris
5bd88d468e Added new card names to changes.txt. 2014-01-26 14:59:07 +00:00
Agetian
e758e07658 - Fix a typo in image name. 2014-01-26 05:06:44 +00:00
swordshine
eb0ac0dde9 - BNG: Added Whims of the Fates 2014-01-26 04:56:56 +00:00
Maxmtg
c81a4d50dd auto set assignment - report to CHANGES.txt 2014-01-25 23:20:23 +00:00
Maxmtg
ae28b04615 A couple of intro decks from GPT times 2014-01-25 23:01:40 +00:00
Maxmtg
471623cd10 3 Starters from M11 added 2014-01-25 22:51:45 +00:00
Maxmtg
4378bfdbea release art indices on M14-precons 2014-01-25 22:42:12 +00:00
Maxmtg
8ff6cbd98e better art randomization for loaded decks 2014-01-25 22:36:15 +00:00
drdev
f4ffe22d61 Refactor ItemManager to switching between different views 2014-01-25 22:33:50 +00:00
Maxmtg
4573e30e73 refactor and remove some dependencies 2014-01-25 22:31:32 +00:00
Maxmtg
832b40e235 Add theros intro decks 2014-01-25 22:10:41 +00:00
Maxmtg
aec0bad678 more problems with art indices solved 2014-01-25 21:49:53 +00:00
Maxmtg
aeedde578d exclude schemes, planes etc from xitax-conversion 2014-01-25 21:40:29 +00:00
Maxmtg
dfebb08e1e fix deck loading problem (wrong editions were shown) 2014-01-25 21:30:56 +00:00
Maxmtg
dbf77d8548 M14 intro decks added to precons 2014-01-25 20:04:16 +00:00
Maxmtg
003c252d8a added option to use only core and expansion sets in deck importer, fixed a related bug 2014-01-25 19:54:32 +00:00
Maxmtg
1986df1961 Xitax's deck convertor integrated into Forge - applies on load to decks where no card has explicitly defined set. 2014-01-25 19:10:26 +00:00
Maxmtg
11c205f0c9 fix bugs in minimal set calculation.
added that column to itemmanager
2014-01-25 16:29:56 +00:00
drdev
7d2cc8fac5 Use arrow button scroller for Variant panel 2014-01-25 16:07:04 +00:00
drdev
863e7733e6 Prevent unmaximizing unless mouse moved 5 pixels on title bar 2014-01-25 16:04:37 +00:00
Maxmtg
e657a1b07d Moved ColumnDef to separate file 2014-01-25 15:58:16 +00:00
Maxmtg
2f29cf7755 edition cached in deckproxy 2014-01-25 15:50:56 +00:00
Maxmtg
6d34dbc286 refactored cardDb, added getEdition method to DeckProxy 2014-01-25 15:43:48 +00:00
Sloth
28f7f7baaf - Fixed Myr Reservoir. 2014-01-25 15:26:58 +00:00
Chris
f3b78b1aa3 Added a fluff piece to the changes.txt file.
Added new card names to changes.txt.
2014-01-25 14:31:19 +00:00
moomarc
ce82a93afe - Fixed starting a constructed match with no variants applied 2014-01-25 12:21:28 +00:00
Maxmtg
fe9a35b706 fix crash 2014-01-25 11:19:01 +00:00
moomarc
febba22f45 - Updated booster and precon lists 2014-01-25 09:56:33 +00:00
Maxmtg
2981668172 PreconDecks' folder property will be filled with their set (temporary) 2014-01-25 09:56:14 +00:00
Maxmtg
ed7369c98f store variants in an enumset 2014-01-25 09:45:47 +00:00
Maxmtg
b6409b11c7 fix NPE when you close any dialog prompting for random name options 2014-01-25 09:37:24 +00:00
Sloth
98c51e45b4 - Fixed Night Dealings. 2014-01-25 07:39:51 +00:00
drdev
9e6b82d10a Add "Folder" filter for DeckManagers 2014-01-25 06:39:48 +00:00
drdev
ee49314502 Fix so planar and scheme decks are saved in the right place 2014-01-25 06:14:17 +00:00
Agetian
29e73367a6 - Planes and phenomena will now be shown rotated 90 degrees in card zoomer mode.
- Updated the AI hints for Onakke Catacomb.
2014-01-25 06:04:50 +00:00
drdev
80aa655164 Add "Folder" column to DeckManagers 2014-01-25 05:50:12 +00:00
drdev
f8d7d060b9 Fix so saving a deck multiple time works
Fix so adding/removing decks in All Decks pane updates deck choosers on home screen
Fix so saving a deck in Deck Editor updates All Decks pane right away
Fix so typing in deck title field marks deck as having changes to save
2014-01-25 05:12:09 +00:00
drdev
b198e8a40e Code cleanup 2014-01-25 02:48:36 +00:00
drdev
a3fb6de6b3 Fix so decks inside subfolders support being deleted 2014-01-25 01:02:51 +00:00
moomarc
5252cca5c5 - small update to changes.txt 2014-01-24 20:33:23 +00:00
moomarc
4cab5da076 - Planechase variant now launched from Constructed match setup screen.
- moved random deck checkboxes into deck panel. Only show them when a random deck type is selected. They are still global settings however.
- when player 1 name is changed in preferences, switching back to constructed setup screen will reflect the change
2014-01-24 19:06:31 +00:00
Sloth
2cdf7030f8 - Made some CantBeBlocked keywords HIDDEN. 2014-01-24 15:37:54 +00:00
Chris
e30f8d0fb6 Preparing the changes.txt file for the next beta build and release. 2014-01-24 14:12:10 +00:00
Chris
22fe17048d Added new card names to changes.txt. 2014-01-24 14:07:24 +00:00
swordshine
3d70e2e9f6 - BNG: Added Gorgon's Head, Siren Song Lyre, and Thunderous Might 2014-01-24 07:20:41 +00:00
Maxmtg
f35dc1f30d apply random foil option for quest games 2014-01-24 06:58:52 +00:00
Maxmtg
34b36a8ef2 optimized formats calculation for decks,
added some comments to deckmanagers
2014-01-24 06:55:38 +00:00
Maxmtg
7c105ca398 Deckmanager : "Edit deck" button (icon) now opens decks from nested folders correctly 2014-01-24 06:43:22 +00:00
Maxmtg
2ec4873552 match itself no longer creates a separate thread, it is now caller's responsibility. Some callers (such as tests or simulations) may run their match in the same thread. 2014-01-24 06:32:45 +00:00
Maxmtg
aa4f3de30c done with Dependencies
added a class to hold all game rules (type, gamesToWinMatch, manaburn, etc)
2014-01-24 06:19:09 +00:00
Maxmtg
e4fb939e91 free blocks option moved to PlayerControllerHuman 2014-01-24 05:44:23 +00:00
Maxmtg
68acaf77c5 cut Dependencies on log entry type and AI profiles 2014-01-24 05:21:21 +00:00
Maxmtg
308039739f Random foiling moved to per-player settings, is set up before starting a match 2014-01-24 04:35:22 +00:00
swordshine
7687637783 - BNG: Added Astral Cornucopia, Fated Return, and Pillar of War 2014-01-24 01:06:57 +00:00
drdev
7b799eb531 Restore borders that were accidentally removed from scroll panes 2014-01-23 23:15:08 +00:00
drdev
9c37156906 Remove unnecessary setting of scroll pane border to null 2014-01-23 22:30:54 +00:00
Chris
32d6eb3ed5 Added new card names to changes.txt. 2014-01-23 14:36:05 +00:00
swordshine
faa2cef0bb - BNG: Added Shrike Harpy and Scourge of Skola Vale 2014-01-23 12:52:26 +00:00
Maxmtg
7e999ea4b3 Cut the dependence on images. Game module will store image keys, unaware of real image locations 2014-01-23 09:11:51 +00:00
swordshine
69c569c82b - added missing subtype arcane to Cranial Extraction 2014-01-23 08:34:49 +00:00
Agetian
bcc5f2c526 - A little fix for the fix. 2014-01-23 07:29:06 +00:00
Agetian
35bff6a89b - Use CLR_ZEBRA for the game log window for consistency with the deck editor tables and to make some themes (e.g. Firebloom) easier on the eyes. 2014-01-23 06:24:21 +00:00
Agetian
a26d45793e - Fix the formation of card choice window title for DigEffect. 2014-01-22 19:00:20 +00:00
Chris
d6577d1d72 Added new card names to changes.txt. 2014-01-22 15:00:22 +00:00
swordshine
e8aeec7f87 - BNG: Added Nessian Demolok and Oracle of Bones 2014-01-22 10:58:32 +00:00
Maxmtg
0b75a0ee8e fix duplication of copies brought by "bftb" 2014-01-22 07:31:52 +00:00
Maxmtg
4163c56502 back from the brink now brings back the cards (but created 2 copies for unknown reason) 2014-01-22 07:14:53 +00:00
drdev
37d45ffbeb Use base ZEBRA and tweak skins that would otherwise have unreadable text 2014-01-22 06:57:09 +00:00
drdev
f03a1397f1 Use dark ZEBRA instead of THEME2 as base background color for Item Manager tables 2014-01-22 06:44:32 +00:00
drdev
410b23974e Make alternating row colors more distinct and remove horizontal grid lines 2014-01-22 05:35:10 +00:00
Maxmtg
3366843ca1 added a method to reload a proxied object from storage (call this method after the object has been changed in deck editor) 2014-01-22 05:26:26 +00:00
Maxmtg
9bcc6cbc64 save/delete methods implemented on DeckProxy 2014-01-22 05:06:56 +00:00
drdev
9636e3d2e4 Prevent player column stretching up over variants panel when players added 2014-01-22 04:59:54 +00:00
drdev
140e44a3bd Add title to avatar selector
Return focus to proper player after avatar selector closed
2014-01-22 04:50:24 +00:00
Maxmtg
9f76a78b0a visbility fix 2014-01-22 04:36:36 +00:00
Maxmtg
dd6e8d0884 rename field 2014-01-22 04:35:08 +00:00
drdev
66b1a795c1 Make Quest Duels and Quest Challenges screens use FScrollPanel with arrow buttons
Prevent focusing arrow buttons
2014-01-22 04:29:19 +00:00
Maxmtg
8b8b9f0cf5 add methods to search for nested folders and create them 2014-01-22 04:22:31 +00:00
drdev
d5647c9e98 Move arrow buttons support to FScrollPane to allow better separation of FScrollPane and FScrollPanel 2014-01-22 04:09:38 +00:00
Maxmtg
5d1d77f4df generalize DeckProxy to manage Limited mode decks efficiently 2014-01-22 03:52:06 +00:00
drdev
7a193c0618 Fix so adding cards to sideboard in Quest Deck Editor properly removes them from inventory 2014-01-22 03:43:07 +00:00
drdev
1709ed07c7 Prevent weird diamond shaped scrollbar thumbs 2014-01-22 03:34:58 +00:00
drdev
23586a027e Make FLabel colors static 2014-01-22 03:21:45 +00:00
drdev
97c74ec2b1 Make scroll arrow buttons semi-transparent and more like FLabels 2014-01-22 03:14:23 +00:00
drdev
961461aa19 Dim scrollbars unless mouse over them 2014-01-22 02:28:52 +00:00
drdev
713a9ecb3b Prevent long deck name causing horizontal scroll arrow to appear 2014-01-22 00:29:36 +00:00
drdev
8a46d38914 Fix so previously played deck restored properly again 2014-01-22 00:12:44 +00:00
drdev
423033d2ac Code cleanup 2014-01-21 23:55:17 +00:00
Maxmtg
d01925107f fix label on 'Choose deck' button 2014-01-21 18:54:02 +00:00
Maxmtg
47a719147c load decks from subfolders
display formats, sb/main sizes
2014-01-21 18:38:17 +00:00
Agetian
556bb2caa7 - Mention the new random art option in CHANGES.txt. 2014-01-21 14:39:34 +00:00
Agetian
ec3813fb13 - Fix getCbRandomArtInPools returning the wrong checkbox.
- Some more renaming.
2014-01-21 14:31:53 +00:00
Agetian
926152940e - Better name for the random art in generated card pools option. 2014-01-21 14:23:46 +00:00
Agetian
7cf186952e - Added an option "Randomize card art in generated card pools" (enabled by default). When enabled, generates cards with different art in generated limited mode pools (sealed, booster draft, quest). When disabled, generates a certain predefined amount (30 for draft/sealed, 10 for quest shop) of lands, all with the same art. However, the art index will be randomized at every generation, thus still leaving some room for art randomization.
- Tweaked case of letters in some option names for consistency.
2014-01-21 14:17:01 +00:00
Chris
b2ccb5c689 Added new card names to changes.txt. 2014-01-21 13:51:48 +00:00
Agetian
3da6e688e4 - Fixed the "remove this card if not playing for ante" inversion causing the ante cards to be removed when playing for ante and not removed when not playing for ante. 2014-01-21 11:04:08 +00:00
Maxmtg
567ffe84cd DeckManagers use DeckProxies 2014-01-21 09:32:36 +00:00
swordshine
d97495ed41 - BNG: Added Heroes' Podium 2014-01-21 08:47:10 +00:00
Maxmtg
ceab176d9f improved the codestyle for Dependencies left from gui 2014-01-21 06:59:28 +00:00
Maxmtg
050887c53c fix compile problems 2014-01-21 06:34:03 +00:00
Maxmtg
2bc61a9e68 the great move 2014-01-21 06:27:36 +00:00
Maxmtg
6b1d9356f3 move authorization to see downface of cards to classes that won't move to different module 2014-01-21 06:20:08 +00:00
Maxmtg
1dbc34fe62 move command and constant, set up bridges for dependencies 2014-01-21 06:16:10 +00:00
Maxmtg
d93b041397 moved 2 files to ensure history is saved 2014-01-21 06:11:18 +00:00
Maxmtg
ecd14e1de4 Revert module separation to make another commit that would keep files' history 2014-01-21 06:05:34 +00:00
Agetian
923bddc90d - Generate 10 lands per art in sealed deck and booster draft modes if there is more than one art available (to avoid spamming the sideboarding window with many hundreds of basic lands) or just generate 30 basic lands of each type if there is only one art for the basic land in set (should still be reasonably enough for any sane limited play). 2014-01-21 05:58:56 +00:00
Maxmtg
97297f291f Game now compiles and runs! 2014-01-20 19:01:29 +00:00
Maxmtg
84850c76a9 restore compilation ability - 1 method left 2014-01-20 18:57:00 +00:00
Maxmtg
ca8c8d35d9 commited a workaround for preferences dependency 2014-01-20 18:44:43 +00:00
Maxmtg
18e96a1028 module separation in progress. Project cannot be compiled. Will restore in under an hour 2014-01-20 18:33:47 +00:00
Maxmtg
f27b3e469a last call to gui eliminated in game code, will try to extract module next 2014-01-20 18:01:12 +00:00
Maxmtg
7b47938062 remove method from AbilityUtils that adds reference from Game to Gui 2014-01-20 17:47:00 +00:00
swordshine
d9f3bb8bdd - BNG: Added Spirit of the Labyrinth 2014-01-20 14:32:16 +00:00
swordshine
8919532b84 - Convert Dredge to a replacement effect 2014-01-20 14:13:13 +00:00
Chris
481ac50726 Added new card names to changes.txt. 2014-01-20 12:45:54 +00:00
Maxmtg
731b3c8c36 DeckProxy (work in progress) 2014-01-20 09:13:36 +00:00
Maxmtg
8393bc02e4 remove ItemPoolView class, instead a read-only pool will be an instance of same class, but backed with an unmodifiable map 2014-01-20 09:13:13 +00:00
Maxmtg
85e5b0ff13 removed list or items from CardPool that had to be kept in sync with the main map, since no other class but ItemManagerModel used it (I wanted to do that for too long already!) 2014-01-20 08:49:52 +00:00
Maxmtg
3b8d779b27 reverted another change to core (the ordering of colors for random generation is implemented in a simpler way) 2014-01-20 08:20:28 +00:00
Maxmtg
89dcef5b67 moved convoke cards selection code from ManaCostBeingPaid to dedicated input for human player 2014-01-20 07:32:12 +00:00
moomarc
6ced3d38a4 - ComboBoxWrapper will retain whether its combobox is enabled or not with a skin change 2014-01-20 07:05:47 +00:00
swordshine
7fc97562b2 - BNG: Added Fanati of Xenagos and Flame-Wreathed Phoenix 2014-01-20 06:59:51 +00:00
moomarc
80372f40b5 - Added manual avatar selection to constructed match setup. 2014-01-20 06:23:57 +00:00
Sol
d9a5a27391 - Fixed Antes Panel from updating too early, and not updating when cards are added to the Ante zone. 2014-01-20 04:29:30 +00:00
Sol
8c73aa93c8 - Adding missed bazaar index file from last checking for new Quest item 2014-01-20 04:16:09 +00:00
drdev
59997f5cf2 Skin scrollbars 2014-01-20 03:03:43 +00:00
drdev
3ab7db6061 Change ItemTable border to match filter separators 2014-01-20 00:26:58 +00:00
drdev
3d2ba5a182 Tweak alt row color so it contrast better with inactive selection color 2014-01-20 00:18:56 +00:00
drdev
d7cb5165ef Skin ItemManagers 2014-01-20 00:14:40 +00:00
Agetian
3a89700d95 - The AI will add snow-covered lands to maindeck when building limited decks (sealed, draft). 2014-01-19 19:04:22 +00:00
drdev
f0ce722aa4 Don't retain selection when clicking to change column sort
Support showing color deck options in proper order with no column header
2014-01-19 18:15:02 +00:00
Chris
95709401a3 Added new card names to changes.txt. 2014-01-19 14:54:50 +00:00
swordshine
06f030ab73 - BNG: Added Champion of Stray Souls 2014-01-19 11:36:37 +00:00
Sloth
bd0dc07c43 - Fixed the keyword "At the beginning of your upkeep, sacrifice CARDNAME unless you pay ..." broken by the brackets {}. 2014-01-19 11:16:54 +00:00
swordshine
0d354f679c - BNG: Added Arbiter of the Ideal, Everflame Eidolon, and Mindreaver 2014-01-19 04:10:20 +00:00
Sol
7ed37ec5f8 - Created a new Bazaar item "Cash Stakes" to allow cards lost in ante to be available in the card shop immediately after the match 2014-01-19 03:15:24 +00:00
swordshine
fa40deaa11 - BNG: Added Tromokratis 2014-01-19 01:33:24 +00:00
Sloth
117d25b686 - Prevention for infinite loops in payManaCost. 2014-01-18 20:41:30 +00:00
Sloth
7491eb0076 - Fixed AI using Sphere of the Suns. 2014-01-18 20:28:50 +00:00
drdev
1acb9f8ab1 Fix so restored deck in view when application first opened
Prevent selection going out of view when table height changes
2014-01-18 20:04:23 +00:00
drdev
f87b262194 Fix so selection retained when changing sort
Fix so previously played deck restored on Constructed screen
2014-01-18 19:26:01 +00:00
Sloth
6c82cabe3a - Updated the quest deck Abe Sapien 3. 2014-01-18 18:25:34 +00:00
drdev
7e7969988a Rework player zone message building for ability effects 2014-01-18 17:06:18 +00:00
moomarc
4b51c24b66 - removed a console println 2014-01-18 15:28:40 +00:00
Sol
5e0ad38ffc - Cards lost to Ante in Quest mode will now appear in the Spell Shop for repurchase 2014-01-18 14:53:31 +00:00
Chris
56557101f3 Added new card names to changes.txt. 2014-01-18 13:36:12 +00:00
drdev
1d0cf99e48 Add View Deck button to make FDeckViewer more discoverable 2014-01-18 07:14:30 +00:00
drdev
2f5b534de6 Make quantity column narrower in FDeckViewer 2014-01-18 06:57:34 +00:00
drdev
00ae4d4824 Add card detail and picture panels to FDeckViewer 2014-01-18 06:42:25 +00:00
swordshine
af2a87a207 - BNG: Added Archetype of Courage, Archetype of Endurance, and Archetype of Imagination 2014-01-18 06:15:53 +00:00
drdev
72fe5ad996 Add FDeckViewer to display deck list when double-clicking
Improve support for opening modal dialog on top of another modal dialog
2014-01-18 05:50:11 +00:00
drdev
d00da28a3c Prevent cursor changing to Move every time you click a tab 2014-01-18 04:06:42 +00:00
drdev
81363bc537 Revert my revert of Max's revert (now that I see what I did wrong, sorry Max) 2014-01-18 03:49:45 +00:00
drdev
1e98cd4939 Fix so combo box constraints retained when switching skins 2014-01-18 03:23:36 +00:00
drdev
814a8976fb Show tooltip for truncated caption 2014-01-18 02:55:09 +00:00
drdev
86cea92ca1 Truncate item manager caption if not enough room for it 2014-01-18 02:53:32 +00:00
drdev
f9178dcff2 Fix so Constructed layout is at least usable at minimum resolution
Fix so Archenemy combo box supports skin changes
2014-01-18 02:33:36 +00:00
swordshine
fcc4b92efe - Fix last commit 2014-01-18 02:19:54 +00:00
swordshine
44f79a5db2 - BNG: Added Brimaz, King of Oreskos and Oreskos Sun Guide 2014-01-18 02:15:56 +00:00
drdev
034f235196 Show color and other columns for quest opponent decks 2014-01-18 01:26:59 +00:00
swordshine
a1e16543b2 - BNG: Added Temple of Enlightenment, Temple of Malice, and Temple of Plenty 2014-01-18 01:24:23 +00:00
drdev
8578e2a538 Fix case of random button 2014-01-18 01:21:37 +00:00
drdev
092d3dac40 Fix padding around new random name button 2014-01-18 01:19:15 +00:00
drdev
e9ddf8400b Revert Max's revert 2014-01-18 00:31:45 +00:00
Maxmtg
22b78255bb Storages must not be changed for UI needs 2014-01-17 17:23:50 +00:00
Agetian
2985b48432 - Updated Alara block precons with authentic basic land art [by Diogenes]. 2014-01-17 16:45:46 +00:00
Agetian
b249028b8e - Code simplification related to effective art index calculation. Deprecated art index 0 will now be treated as random art (please update your decks if they use art index 0). 2014-01-17 16:39:21 +00:00
Agetian
4cb2077e1a - The art indexes in .dck files now start at 1, not at 0, and thus match the image file name conventions (e.g. index 1 for a Forest matches Forest1.full.jpg). Note that if you had decks created with different art in mind prior to this beta, the art in your decks will be slightly off (index 0 will be treated as index 1 for the sake of limited backwards compatibility). Please update your decks if necessary. 2014-01-17 15:37:19 +00:00
Agetian
88b6223820 - Fix imports. 2014-01-17 15:05:11 +00:00
Agetian
0b4ef6b1e3 - Experimental: generate 50 basic lands for each art type in limited modes (Sealed Deck and Booster Draft, in particular). While this is not theoretically "unlimited" as the rules for limited modes provide, it guarantees at least 150-200 basic lands of each type for every set with three or four pictures, and at least 50 basic lands of each type even if there's only one art; this probably should be more than necessary for any sane limited play needs). Feedback welcome. 2014-01-17 15:04:12 +00:00
Agetian
8921ce16e6 - Basic NPE prevention in showCard, please review (not sure if there's a better way to prevent this NPE that would be more desirable). 2014-01-17 14:37:35 +00:00
Chris
f4606da30f Added new card names to changes.txt. 2014-01-17 14:14:50 +00:00
moomarc
41a5727a93 * Added a button to game setup to fetch random names 2014-01-17 13:14:14 +00:00
Maxmtg
19cec963d2 moved a gui reference out from costs 2014-01-17 08:32:39 +00:00
swordshine
156bc84c73 - Update more scripts 2014-01-17 07:52:22 +00:00
swordshine
eb98eaf5af - Update more scripts 2014-01-17 07:30:27 +00:00
swordshine
fb6d86af8a - Update scripts 2014-01-17 07:18:54 +00:00
drdev
39aa6bfda1 Add a little more padding between columns 2014-01-17 05:58:46 +00:00
drdev
ba59dfb01c Allow clicking anywhere inside player panel to select it
Distinguish selected player better using semi-transparent overlay for other panels
2014-01-17 05:55:30 +00:00
drdev
dd044c30e6 Prevent scroll arrow button sticking around when switching to other pages on home screen 2014-01-17 05:01:46 +00:00
drdev
f1fcc2c26b Increase gap below variants panel 2014-01-17 04:52:58 +00:00
drdev
c0e9d82ff6 Improve Constructed screen layout 2014-01-17 04:40:35 +00:00
Agetian
89598ab48c - Fixed apostrophes in Vintage format banned list definition. 2014-01-17 02:53:32 +00:00
drdev
586de9321a Remove copy decklist message 2014-01-17 01:16:05 +00:00
drdev
ae7244a10f Fix so toggle button filters appear properly when removed then re-added 2014-01-17 00:54:21 +00:00
drdev
d95fc7352f Cleanup unused references 2014-01-16 23:42:27 +00:00
moomarc
e4b7c92c6a - New constructed match setup improvements:
* Skinned player close button
2014-01-16 18:47:58 +00:00
drdev
a52a88e0cb Fix so DeckManagers list decks in nested folders
Update FDeckChooser to use DeckManager
2014-01-16 15:57:43 +00:00
moomarc
2ec3c08e72 - New constructed match setup improvements:
* changing the avatar in match setup or avatar preferences will now update each other to reflect the change to the preferences
2014-01-16 15:41:54 +00:00
Chris
b57e0a9848 Added new card names to changes.txt. 2014-01-16 13:49:09 +00:00
Chris
eabcc78815 Added new card names to changes.txt. 2014-01-16 13:46:49 +00:00
moomarc
1b7a2730f0 - New constructed match setup improvements:
* When a player is removed, the closest active player gains focus.
2014-01-16 11:17:18 +00:00
moomarc
caac7dc2ed - New player name generator applied 2014-01-16 10:17:38 +00:00
Maxmtg
d8eb3a5c7a DeckChooser will notify of their selection change 2014-01-16 06:40:22 +00:00
Agetian
5973d0d944 - Added some more information about the WIP functionality targeted for the upcoming beta. 2014-01-16 05:16:36 +00:00
Agetian
a512a7ab33 - Added some information about the WIP functionality targeted for the upcoming beta. 2014-01-16 05:11:10 +00:00
Agetian
e44cada50e - [Fixed] only save the information about the card art index to .dck file if the card has more than one possible art in set. 2014-01-16 04:45:17 +00:00
Sloth
49e734b66d - Added code support for Ragemonger. 2014-01-15 22:31:18 +00:00
Agetian
5c4efbcd04 - Minor code style tweak. 2014-01-15 16:01:57 +00:00
Agetian
f131aafa44 - Optimized the generation of basic lands with random art for the quest mode card pool and quest shop.
- Better name for a function to split a value into a predefined number of random groups.
2014-01-15 15:59:57 +00:00
Chris
f4263e943d Added new card names to changes.txt. 2014-01-15 14:07:07 +00:00
moomarc
45cd72f7dc - New constructed match setup improvements:
* avatar randomization now ensures duplicates aren't chosen
  * player names and avatars are now used for the match
2014-01-15 12:07:45 +00:00
Agetian
634289407b - Optimization of adding cards with random art index in CardPool. 2014-01-15 09:34:03 +00:00
moomarc
01ff93375a - New constructed match setup fixes:
* starting a game without preferences set no longer causes issues with avatars or name.
  * avatars are assigned avatars randomly (except for p1 and p2 who uses their preferences)
  * right clicking an avatar assigns a new random avatar
2014-01-15 08:10:55 +00:00
Agetian
c64ef5deed - Fix a crash in the multiple art processing code related to cards not assigned to any edition. 2014-01-15 07:50:27 +00:00
drdev
a5a0c510b5 More code cleanup 2014-01-15 05:48:53 +00:00
drdev
d7f8231717 More code cleanup 2014-01-15 05:20:00 +00:00
drdev
f0f7cfc839 Move remaining storage classes out of GUI 2014-01-15 05:14:05 +00:00
drdev
03870821c5 Code cleanup 2014-01-15 05:07:59 +00:00
Agetian
726084bc06 - Removed a check for variant card art index (all variant cards currently have only one art). 2014-01-15 05:02:50 +00:00
swordshine
cbbc341472 - Remove creature subtypes when gods are not creatures 2014-01-15 04:54:36 +00:00
drdev
664b707330 Fix so multicolor decks shown if only multicolor button checked 2014-01-15 02:21:26 +00:00
drdev
a47bba59d4 Fix so right-click updates table selection even if no context menu is shown 2014-01-15 02:10:36 +00:00
drdev
e84544afe4 Fix deck format default sort 2014-01-15 01:49:07 +00:00
drdev
cd505adc3d Fix padding around deck list buttons 2014-01-15 01:46:11 +00:00
drdev
5b1dd964ae Fix warnings 2014-01-15 01:33:07 +00:00
Sol
86ef4d0820 - Adding support for Gain Ownership cards, utilizing some of the same methods Ante is already using
- Added Darkpact
2014-01-15 01:06:14 +00:00
moomarc
966e593617 - Initial implementation of new constructed game setup 2014-01-14 16:04:10 +00:00
Agetian
eb4a355dc7 - Only write out the card art index to the deck if the art count for the card is greater than 1. 2014-01-14 15:42:47 +00:00
Agetian
d65b645a64 - Added a function to CardDb to get the number of different art available for a given card in a given set (to be used soon). 2014-01-14 15:27:33 +00:00
Chris
f899c6e58c Added new card names to changes.txt. 2014-01-14 14:30:40 +00:00
Agetian
a554599fd7 - Updated the Duel Decks: HvM edition file to correctly recognize 8 Mountains with different art (thanks Diogenes!) 2014-01-14 13:53:47 +00:00
swordshine
6046860e15 - BNG: Added Hero of Iroas
- Tweak Bestow
2014-01-14 12:15:24 +00:00
Maxmtg
1dda7d72a9 restore fields( in case GameFormat is serialized) 2014-01-14 07:35:07 +00:00
Maxmtg
3e2f3ab1c5 small bug 2014-01-14 07:22:39 +00:00
Maxmtg
286d7d043c Restored functionality : deckeditor shows all valid formats for decks in its list. 2014-01-14 07:21:49 +00:00
Maxmtg
563c089b9d now GameFormat supports "Restricted" cards (ex: power 9 in Vintage) 2014-01-14 07:13:48 +00:00
Agetian
ca103655bd - Optimize splitCardName by getting rid of continuous regular expression parsing. 2014-01-14 06:56:06 +00:00
Agetian
666fb6b35c - Cards with no art index specified will now have random art in every match (e.g. the line "20 Forest|7ED" provides twenty 7th Edition Forest cards each with randomized art).
- Some code reogranization related to card art randomization.
2014-01-14 06:02:06 +00:00
swordshine
d234975cde - BNG: Added Nessian Wilds Ravager and Pharagax Giant 2014-01-14 04:40:40 +00:00
drdev
13a6310ac0 Increase height of table rows slightly 2014-01-14 03:55:54 +00:00
drdev
62bfb66e11 Tweak spell shop columns 2014-01-14 03:39:48 +00:00
drdev
b776929fe8 Ignore sideboard when determining deck color (mostly for sake of limited) 2014-01-14 03:16:05 +00:00
drdev
273b7286cf Tweak cost column width 2014-01-14 02:27:45 +00:00
drdev
5bd450e0c9 Fix deck sort logic 2014-01-14 02:19:51 +00:00
drdev
777dff3c4b Adjust column widths 2014-01-14 02:06:15 +00:00
drdev
e3ddb00eee Left align table headers and ColorSetRenderer
Fix default sort for Format column
2014-01-14 01:54:45 +00:00
Maxmtg
870ffe3437 better color sorting, colorless decks icon is properly centered 2014-01-13 19:30:07 +00:00
Maxmtg
b8ea837204 align colors on center 2014-01-13 19:21:39 +00:00
Maxmtg
4a611fcf58 fix problems with deck format detection 2014-01-13 19:01:46 +00:00
Maxmtg
91be7b5a32 ColorSetRenderer for deck list 2014-01-13 18:46:40 +00:00
Maxmtg
42cf0def0f rollback changes to Deck, ManaCost, StorageBase, CardPool 2014-01-13 18:21:29 +00:00
Agetian
10fd05478d - Sealed Deck and Booster Draft limited modes now correctly handle and support cards with different art. 2014-01-13 14:46:12 +00:00
Chris
9fbc7a17c3 Added new card names to changes.txt. 2014-01-13 14:29:06 +00:00
Agetian
3cd105bac0 - Restore the functionality to show all cards from all sets and with different card art in the Constructed deck editor. This is temporarily the default and only behavior because it's the only way to properly support cards from multiple sets and with multiple card art indexes at the same time (given the note below).
- NOTE: The "Show unique cards only" functionality of the Constructed deck editor is currently broken (it was commented out by someone, possibly to be reworked later?)
2014-01-13 10:48:38 +00:00
swordshine
559c96412a - BNG: Added Ephara, God of the Polis 2014-01-13 09:56:21 +00:00
Agetian
ee5187c7e7 - Snow-covered lands have only one art (at least thus far). 2014-01-13 09:47:12 +00:00
Agetian
0cb7573494 - Generate basic land cards with random art in quest mode starting pool and quest mode card shop. 2014-01-13 09:46:35 +00:00
Agetian
0f514be363 - Added a simple Python tool to batch-scan a number of deck files for compatibility with Forge AI (use -h to get help). Right now it requires an unpacked 'cardsfolder' and a 'decks' folder in the same folder as the tool in order to operate.
- The -p option will only list decks that are playable by the AI, the -u option will only list decks that are unplayable by the AI (along with the lists of unplayable cards in each deck), the -d option will physically remove all deck files that are not compatible with the AI.
2014-01-13 09:10:34 +00:00
Agetian
ca07a8103a - Use the single-line 'for' style similar to other code places.
- Fix unused imports.
2014-01-13 08:55:47 +00:00
Agetian
4837bb5740 - Support distinction between cards with different card art indexes in the deck editors (the card index is now saved to .dck file and loaded from there if available).
- Remove a Singleton call from Match that was necessary to randomize card art (will be unsupported later and will not be necessary anyway once the true support is fully implemented).
- (WIP) Automatically randomize card art for cards that do not have the art index specified; for now only works for basic lands that were generated randomly (e.g. in random Constructed decks). Limited mode (sealed decks, draft decks, quest mode generated pool, quest mode spell shop) support for generating cards with different card art will hopefully follow soon.
2014-01-13 08:54:04 +00:00
drdev
fc7cc33111 Allow filtering and sorting decks based on name, color, and format
Refactor table column logic to be easier to implement new columns
Provide set sizes for certain columns so other columns can auto-size nicer
2014-01-13 08:35:47 +00:00
Maxmtg
ce341302a3 renamed createIngamePlayer method to minimize confusion 2014-01-13 06:23:32 +00:00
Maxmtg
4cb27c40ac (doubtful) replace xcantbe0 flag with restriction 2014-01-13 06:20:58 +00:00
swordshine
84e3fc1be9 - Fixed ChangeZoneAllEffect (r23967 broke many cards. Sloth, please review this fix) 2014-01-13 02:41:33 +00:00
Maxmtg
2522450930 Kill all gui 2014-01-12 18:32:49 +00:00
Maxmtg
e3e761ddc0 -1 gui call 2014-01-12 18:27:37 +00:00
Maxmtg
c95ee53137 remove gui calls from RepeatEachEffect.java 2014-01-12 18:22:26 +00:00
Maxmtg
7f9ef96178 wipe gui calls from effects 2014-01-12 18:16:03 +00:00
Maxmtg
95cbb2870c event phased had to be game event, not purely UI one 2014-01-12 17:34:40 +00:00
Maxmtg
17891a62fa remove global object reference from ZoneType 2014-01-12 17:20:45 +00:00
Maxmtg
f1ff893962 Human payment for costs now uses visitor pattern... as a result the concrete Cost classes no longer depend on UI 2014-01-12 16:15:41 +00:00
Chris
ce6d092b16 Cleared out the changes.txt file, now ready for new material. 2014-01-12 15:31:45 +00:00
Maxmtg
f6577217ff remove 'put' method from ItemPool , use 'add' instead 2014-01-12 12:22:12 +00:00
Maxmtg
283af44c48 removed deckbox 2014-01-12 12:16:51 +00:00
Maxmtg
1ea839f5d4 All costs except mana - AI uses decision, HumanPlay generates decision 2014-01-12 11:53:58 +00:00
drdev
4a3e07bbae Fix titles on dig effect prompts
Make reveal dialogs have more consistent titles
2014-01-11 18:26:43 +00:00
Chris
9ba8866b19 The year is now 2014. 2014-01-11 16:10:22 +00:00
Chris
5dbe15e7e0 [maven-release-plugin] prepare for next development iteration 2014-01-11 15:11:47 +00:00
Chris
cbf38aed9c [maven-release-plugin] prepare release forge-1.5.10 2014-01-11 15:11:36 +00:00
Chris
a8eb34d201 Added a fluff piece to the changes.txt file.
Preparing the changes.txt file for the next beta build and release.
2014-01-11 14:54:09 +00:00
drdev
496b12913d Prevent random crash that sometimes occurs when moving mouse over deck tables 2014-01-11 04:15:04 +00:00
drdev
be47a4bad3 Fix crash when clicking a card that can't be played 2014-01-11 01:56:14 +00:00
Sol
9d28e88a24 - Adding mana symbol to trigger description 2014-01-10 23:01:04 +00:00
Chris
d937a397a7 [maven-release-plugin] prepare for next development iteration 2014-01-10 14:01:32 +00:00
Chris
c9daed2056 [maven-release-plugin] prepare release forge-1.5.9 2014-01-10 14:01:20 +00:00
Chris
804c36e8b7 Preparing the changes.txt file for the next beta build and release. 2014-01-10 13:47:11 +00:00
drdev
7274d46865 Increase maximum list box auto size width 2014-01-10 04:36:12 +00:00
drdev
feaec2eb6d Auto size ListChooser dialogs to fit items if possible 2014-01-10 04:30:23 +00:00
drdev
753c0731a3 Fix performance of list boxes
Skin border for list on ListChooser dialogs
2014-01-10 03:01:52 +00:00
drdev
9a6b1822a9 Ensure application icon updated when skin changed 2014-01-10 01:17:04 +00:00
Sloth
db5e8316ec - Added AI logic to Ward Sliver. 2014-01-09 22:54:04 +00:00
drdev
513b9db9b5 Update CHANGES.txt 2014-01-09 19:33:26 +00:00
drdev
04248f0166 Refactor skinning logic to avoid caching components, allowing memory to be cleared and improving performance 2014-01-09 19:05:51 +00:00
Chris
c60c041012 Added new card names to changes.txt. 2014-01-09 15:02:49 +00:00
swordshine
f10ec1751f - Converted Old Man of the Sea
- Added Rootwater Matriarch
2014-01-09 13:46:14 +00:00
drdev
561d4deb32 Move graphics functions to static FSkin class 2014-01-09 03:19:30 +00:00
Sloth
3e552ac655 - Fixed Gilt-Leaf Archdruid. 2014-01-08 15:49:04 +00:00
Chris
12d8b289e5 Added new card names to changes.txt. 2014-01-08 14:54:57 +00:00
swordshine
bcf2abdbbc - Comment out unused complex counting methods 2014-01-08 14:28:56 +00:00
swordshine
8747c163ee - Updated scripts 2014-01-08 14:12:07 +00:00
swordshine
458bd8f964 - Updated scripts 2014-01-08 14:02:12 +00:00
swordshine
19a34ba730 - Updated scripts 2014-01-08 13:59:22 +00:00
swordshine
16294fe54a - Combine GreatestPowerYouControl and GreatestPowerYouDontControl 2014-01-08 13:55:22 +00:00
swordshine
76cdfa9759 - Converted Count$LowestLibrary to playXCount 2014-01-08 12:52:09 +00:00
swordshine
fc508b3a27 - Converted LowestLifeTotal 2014-01-08 12:32:02 +00:00
swordshine
a4c2fa3797 - Converted Psychic Transfer for multiplayer 2014-01-08 12:26:14 +00:00
swordshine
d1575996b4 - Converted Liu Bei, Lord of Shu to script 2014-01-08 11:38:50 +00:00
swordshine
75293299ed - Update scripts for AllM12Empires (should fix some corner cases) 2014-01-08 11:22:27 +00:00
swordshine
e50f31fb5f - Update scripts for Visions of Beyond 2014-01-08 11:05:26 +00:00
drdev
e47cdebf14 Prompt to save changes of previous deck before loading another deck 2014-01-08 04:17:26 +00:00
drdev
85eaf866d9 Avoid unnecessary reloading of deck if closing deck 2014-01-08 04:04:23 +00:00
swordshine
800a9b6854 - Added Storage Matrix 2014-01-08 03:54:03 +00:00
drdev
94eb94508c Reload deck if you choose not to save when leaving screen 2014-01-08 03:49:22 +00:00
drdev
02a49149fa Revert previous change 2014-01-08 03:11:47 +00:00
drdev
80308ab621 Prevent prompting to save deck when switching away from editor 2014-01-08 02:35:39 +00:00
drdev
cb055269d3 Prompt before leaving draft 2014-01-08 02:06:17 +00:00
drdev
1c6ccbb20a Make end turn button automatically pass priority if possible, and otherwise not end turn 2014-01-08 01:33:02 +00:00
drdev
764310e08b Fix issues with Dock button hovering 2014-01-08 00:42:54 +00:00
swordshine
673fd2dae3 - Fixed Sphinx of Jwar Isle 2014-01-07 05:35:58 +00:00
drdev
5fe57fcb11 Improve Sealed Deck button usability and support canceling prompt for number of booster packs 2014-01-07 04:08:31 +00:00
drdev
0a9617b0c4 Improve captions on Deck Editors 2014-01-07 03:29:46 +00:00
drdev
6b06a6f274 Prevent being able to add more cards to deck in quest deck editor than you own
Show inventory when in sideboard mode in quest deck editor
2014-01-07 01:59:53 +00:00
Chris
e5c3d4595c Added new card names to changes.txt. 2014-01-06 15:11:55 +00:00
swordshine
ab0a18cc64 - Added Static Orb 2014-01-06 11:46:41 +00:00
drdev
b534c4bbcd Make Deck Editor add/remove items smarter
Support adding X copies of card at a time using new GuiChoose.getInteger API
2014-01-06 08:51:30 +00:00
Agetian
0ee95fae76 - Randomize Card Art is no longer an option and is the default functionality instead (since there is no true support for distinguishing cards with different art in Forge, the game will randomize the card art that appears on cards with multiple available pictures, most notably basic lands, in each match). 2014-01-06 05:33:26 +00:00
Sol
dcb8c54e4c - Updaating Crypt Sliver description 2014-01-05 23:19:47 +00:00
drdev
802aed63df Refactor context menu building logic for editor tables 2014-01-05 22:26:01 +00:00
Sol
ba7cd330e6 - Updating trigger description for Mana Symbol 2014-01-05 22:23:48 +00:00
drdev
adeec5d6a9 Refactor incremental search (FindAsYouType) into ItemView class 2014-01-05 19:59:07 +00:00
drdev
8b0e20aa9e Create DeckManager 2014-01-05 19:21:15 +00:00
Agetian
a22a3dc849 - Fixed the description of Drain Life's spell ability (now it includes the first part of Oracle text which says to spend only black mana on X). 2014-01-05 19:05:35 +00:00
drdev
f220aef52a Make dialog backdrop appear over top of navigation bar 2014-01-05 17:15:20 +00:00
drdev
0175cc1a26 Prevent Alt key opening Forge menu while dialog open 2014-01-05 17:01:11 +00:00
drdev
59b6e092c9 Use new backdrop panel behind FDialog that's more transparent than overlay panel 2014-01-05 16:46:21 +00:00
drdev
ceb7b13a8e Refactor ComponentSkin.skins to compSkins in FSkin 2014-01-05 15:50:13 +00:00
Agetian
f68f8ba157 - Fix a bug that caused the deck subtitle not to be updated when the quest mode deck editor was turned to sideboard mode.
- Fix a bug that allowed the Import button to be used in quest mode deck editor.
2014-01-05 11:33:26 +00:00
drdev
19a58c309e Update CHANGES.txt 2014-01-05 08:34:57 +00:00
drdev
62479e1de6 Use reveal list dialog when revealing cards 2014-01-05 08:29:41 +00:00
drdev
04dde1c18d Fix crash when closing Spell Shop 2014-01-05 08:23:22 +00:00
Agetian
c7450034f5 - Restored the assign random card edition in randomly generated decks functionality. 2014-01-05 08:08:58 +00:00
drdev
9140dab9f1 Ensure animation card panels are disposed 2014-01-05 08:08:46 +00:00
drdev
8f4d3792c6 Dispose CardPanels as they are removed from CardPanelContainer 2014-01-05 08:00:30 +00:00
drdev
9d73236812 Support disposing of component skins when that component's dialog or screen is closed 2014-01-05 07:33:17 +00:00
swordshine
fbc0404f94 - Fixed CostRemoveCounter 2014-01-05 07:20:46 +00:00
Agetian
a2050ed3e6 - Removing an erroneously committed empty method. 2014-01-05 06:06:23 +00:00
drdev
0d2c13bf80 Clear images from cache when switching screens to reduce memory usage
Dispose of card panels when each game ends to reduce memory usage
2014-01-05 06:05:10 +00:00
Agetian
39061439dc - Restored the "Use Random Card Art" functionality. Implementation may be suboptimal with the latest changes in mind, feel free to reimplement in a better way if you know how (do NOT randomly remove though!). 2014-01-05 06:03:30 +00:00
drdev
d9e5d93265 Add standard API for setting default focus on FDialog 2014-01-05 03:30:24 +00:00
Agetian
b3bec906ef - Fix the bug that causes the sideboard not to work correctly when the sideboard is initially empty. 2014-01-04 18:38:50 +00:00
drdev
6d969373b9 Improve list reveal dialogs to allow Escape key and clicking close button
Improve title for "AI can't play cards well" dialog
2014-01-04 17:42:37 +00:00
drdev
c8ac6b9f2d Prevent ListChooser getting caught in infinite loop of reprompting 2014-01-04 16:27:24 +00:00
drdev
45d7b43aa6 Prevent filter widgets being hidden when opening Workshop 2014-01-04 05:44:33 +00:00
drdev
e954b40d3c Skin ListChooser 2014-01-04 05:27:28 +00:00
drdev
07f94f9d42 Ensure filters shown when Ctrl+F used to focus search field 2014-01-04 03:16:20 +00:00
drdev
18809bc918 Prevent updating item manager view if filters didn't change
Focus item manager when Deck Editor opened and when filters hidden/shown
2014-01-04 03:07:14 +00:00
drdev
85d32d49e2 Update CHANGES.txt 2014-01-04 02:55:55 +00:00
drdev
64459b414e Support hiding filters 2014-01-04 02:52:05 +00:00
drdev
f0ffeefe24 Move filter items to "Add" submenu and add "Reset Filters" option to main Filters menu 2014-01-03 03:47:19 +00:00
drdev
df022d5df7 Fix size of Commander Deck Editor button 2014-01-03 02:52:31 +00:00
drdev
a2b75c2072 Prevent showing File menu in Spell Shop 2014-01-03 02:46:53 +00:00
drdev
e7a9492200 Prevent crash when switching away from then back to Spell Shop 2014-01-03 02:25:42 +00:00
Agetian
3133dbf8b4 - A better fix for the attacker icon not appearing (getting rid of GUI calls in game.Combat and moving them over to gui.InputAttack) 2014-01-02 06:51:30 +00:00
Agetian
8fd2ffc93e - Getting rid of UI event duplication for declaration of blockers. 2014-01-02 06:42:58 +00:00
Agetian
39675d465d - Fixed the attacker icon not appearing automatically when a card with "attacks each turn if able" is declared.
- Added the UI event calls to Combat.addAttacker and Combat.addBlocker (this fixes the bug mentioned above). Not sure if this may lead to a duplication of events when declaring attackers/blockers manually, please review.
2014-01-02 06:40:28 +00:00
drdev
6e969ddaaa Update CHANGES.txt 2014-01-01 23:50:15 +00:00
drdev
a9f4009e43 Prevent marking deck as modified when changing sections
Update item manager caption when changing section
Show full catalog when in sideboard section
Avoid hiding title and save buttons when changing sections
2014-01-01 23:43:14 +00:00
drdev
b28b5e1ec9 Add File menu and keyboard shortcuts to Deck Editor 2013-12-31 21:44:45 +00:00
drdev
f4b9dd2f34 Update buttons on concede, restart, and exit prompts 2013-12-31 20:00:51 +00:00
drdev
40c651cd04 Apply anti-aliasing to FDialog border on Windows where it doesn't cause issues 2013-12-31 19:50:02 +00:00
drdev
b6d6da88e8 Skin more message/option/input dialogs
Prevent prompting twice when switching away from modified card in Workshop
2013-12-31 19:30:26 +00:00
drdev
7f95e5f583 Add prompts to confirm buying and selling items in Spell Shop 2013-12-31 17:16:40 +00:00
Maxmtg
e179aa404c setLife uses no gui 2013-12-31 05:53:06 +00:00
Maxmtg
4235a6906e remove isHuman from dig effect 2013-12-31 05:42:47 +00:00
Maxmtg
618cd6415d visited the quest ante code 2013-12-31 05:19:59 +00:00
Maxmtg
9d458ce8c5 still needed an originalDeck in RegisteredPlayer (to restart a match) 2013-12-31 05:08:02 +00:00
Sol
311306e986 - Fixing Mana symbol for Ogre Savant 2013-12-31 03:57:12 +00:00
Sol
a1688a7404 - Some cleanup with ante fixes. Quest mode midgame ante behavior restored in a more generalized fashion 2013-12-31 03:26:33 +00:00
Maxmtg
da421bc5f8 removed some duplicated code 2013-12-30 21:36:24 +00:00
Maxmtg
db8a71cca2 changed how ante works 2013-12-30 21:17:14 +00:00
swordshine
c8352e4968 - Remove phasedOut cards from combat 2013-12-30 14:30:34 +00:00
Chris
1d8aec2c3b Added new card names to changes.txt. 2013-12-30 13:56:56 +00:00
swordshine
459c2cfae4 - Missing Oracle 2013-12-30 01:41:38 +00:00
swordshine
32c52578e2 - Added Bludgeon Brawl 2013-12-30 00:56:08 +00:00
swordshine
eccadbf6fc - Added Nullstone Gargoyle 2013-12-30 00:39:50 +00:00
swordshine
8d99d2032d - Fixed Avacyn, Angel of Hope 2013-12-30 00:38:55 +00:00
Maxmtg
121db288c1 into single thread 2013-12-29 17:16:24 +00:00
Agetian
b8b3fff684 - Changed the representation of booleans in AI profile config files to match the preference file conventions.
- Sorted the options in AI profile config files in alphabetical order.
2013-12-29 08:17:32 +00:00
Agetian
33a08f67ec - Changed the way AI cheating works. The old option "Smooth AI Land" is now replaced with a global toggle "Enable AI Cheating" which allows the AI personalities (profiles) that have various cheat options set in them to utilize those cheat options to gain card advantage over the human.
- Currently there is only one cheat option (CHEAT_WITH_MANA_ON_SHUFFLE) which works like the old Smooth AI Land option by allowing the AI to cheat-shuffle appropriate lands into appropriate places in the library to minimize mana lock.
- Both default AI personalities (Default.ai and Reckless.ai) currently have CHEAT_WITH_MANA_ON_SHUFFLE set to True, which emulates the old Smooth AI Land functionality: if the "Enable AI Cheating" option is enabled, both profiles will cheat-shuffle. If disabled, neither profile will cheat-shuffle.
- Overall, it is now possible to set AI cheating on a per-profile basis and it's also possible to globally disable AI cheating even for personalities that normally do cheat.
- When adding new AI cheating options, don't forget to check for the value of the global toggle which is FPref.UI_ENABLE_AI_CHEATS.
2013-12-29 07:42:07 +00:00
Agetian
dffc1b2a42 - NetBeans settings loss related to expanding tabs is killing me :\ 2013-12-29 06:19:01 +00:00
Agetian
55aa4350b9 - Fixed the Phasing icon not appearing immediately when the card phases in/out.
- Added support for an additional sound effect that is played when a card phases in/out (phasing.wav is played if available).
- Added the "CHEAT_WITH_MANA_ON_SHUFFLE" option to the stock AI profiles (not used yet, to be implemented soon).
- Organized the AI profile config files a little bit by sorting the options.
2013-12-29 06:13:42 +00:00
drdev
40bfde20fa Cleanup Quest and Deck lister display
Fix Quest renaming
2013-12-28 22:28:59 +00:00
drdev
8ceda2b07b Use skinned dialog for new quest dialogs 2013-12-28 20:57:34 +00:00
drdev
a592a44647 Support input FOptionPane 2013-12-28 20:23:41 +00:00
Chris
2a9b59f935 Added new card names to changes.txt. 2013-12-28 14:50:01 +00:00
swordshine
5ed0549dc4 - Fixed devModePlaneswalkTo 2013-12-28 10:29:02 +00:00
swordshine
158da7f60f - Fixed Phyrexian Dreadnought 2013-12-28 06:56:34 +00:00
swordshine
58e529097f - Added Debt of Loyalty, Matopi Golem, Skeleton Scavengers, and Soldevi Sentry 2013-12-28 05:08:39 +00:00
Maxmtg
2de5beb6d1 something is no longer wrong with 2 piles separation in fact or fiction 2013-12-28 00:17:50 +00:00
Chris
cb5df407fd Cleared out the changes.txt file, now ready for new material. 2013-12-27 22:02:48 +00:00
Chris
8fd0e873c7 [maven-release-plugin] prepare for next development iteration 2013-12-27 17:42:27 +00:00
Chris
fe9ff2f4f9 [maven-release-plugin] prepare release forge-1.5.8 2013-12-27 17:42:15 +00:00
Chris
bf05d850fb Preparing the changes.txt file for the next beta build and release. 2013-12-27 17:29:36 +00:00
Chris
266cbd5dde Added new card names to changes.txt. 2013-12-27 17:26:08 +00:00
swordshine
e222c0f7a9 - Added Pools of Becoming 2013-12-27 12:59:31 +00:00
swordshine
12e80be6d1 - Fix NewGame trigger not working 2013-12-27 12:31:21 +00:00
swordshine
5efb2c2e40 - Fixed DigEffect 2013-12-27 11:34:05 +00:00
swordshine
2e574caac6 - Another fix to avoid overriding 2013-12-27 10:32:07 +00:00
swordshine
74b7a40763 -Fixed Selesnya Loft Gardens 2013-12-27 10:30:32 +00:00
Maxmtg
1ede72b64a ai cost decisions now use visitors 2013-12-27 09:26:39 +00:00
Maxmtg
c45fe42129 prerequisites to pay costs using visitor pattern (to remove AI decision-making and gui-specific inputs from the concrete cost classes) 2013-12-27 08:42:44 +00:00
drdev
ddaffcf7a5 Prevent glitchy dialog on Linux
Transition more message/confirm dialogs to skinned look
2013-12-27 05:59:29 +00:00
swordshine
0d28620ee3 - Fixed a typo in Journey of Discovery 2013-12-27 00:28:23 +00:00
Chris
bbab149d3c Added new card names to changes.txt. 2013-12-26 14:36:00 +00:00
Maxmtg
d4e193f39a ensure that limited games won't pop the AI cannot play cards window 2013-12-26 07:25:16 +00:00
swordshine
bd4dd064be - BNG: Added Kiora, the Crashing Wave 2013-12-26 05:47:19 +00:00
Agetian
2efb70e3b5 - Stupid NetBeans space/tab settings were broken again, fixing. 2013-12-26 05:33:47 +00:00
Agetian
92668c3a2a - Adding an AI profile property for cheat shuffling (to be used soon). 2013-12-26 05:31:31 +00:00
Agetian
3915c3ac2c - Fix the dialog window popping up about unplayable cards in the AI deck in Sealed Deck, Booster Draft, and Quest modes. 2013-12-26 05:22:46 +00:00
Chris
51e521fbb3 Added new card names to changes.txt. 2013-12-25 15:03:12 +00:00
Maxmtg
a81a666b81 move haunt Ai to a separate file
remove isComputer method
2013-12-25 08:21:25 +00:00
swordshine
69a9f0fe43 - Added Plunge into Darkness 2013-12-25 08:14:19 +00:00
Maxmtg
9262ad4d82 make newGame method private, non-static 2013-12-25 08:07:33 +00:00
Maxmtg
b6270a71bb dissolve gameNew, move ai cheating to that very class, improve ante messages
remove lose by milling option
2013-12-25 08:03:20 +00:00
Maxmtg
e31d2ae0d1 fix proliferate not working on creatures 2013-12-25 05:49:00 +00:00
Maxmtg
77510ac6e3 arrange inputs hierarchy 2013-12-25 05:42:49 +00:00
swordshine
0f1e88bb25 - Converted Amplify to replacement effects 2013-12-25 04:50:26 +00:00
swordshine
c5a42f03e6 - Update more scripts 2013-12-25 04:07:37 +00:00
swordshine
de1124c19e - Update 3 scripts 2013-12-25 00:33:58 +00:00
drdev
60ba4bfec6 Add back FDialog custom paint code 2013-12-24 19:06:10 +00:00
drdev
6372242b0b Temporarily comment out FDialog custom paint code 2013-12-24 19:05:17 +00:00
drdev
9a8c4a1c8c Make Left/Right/Home/End keys shift focus as expected between buttons in FOptionPanes 2013-12-24 18:50:09 +00:00
drdev
891db98700 Close FDialogs when Escape key pressed 2013-12-24 18:38:11 +00:00
drdev
f7d1b73a6c Move setShape call from paint to resize listener rather to hopefully fix Linux issue
Make FDialog border non-rounded if setShape isn't supported (Mac)
2013-12-24 18:11:09 +00:00
swordshine
7a906fdc03 - Update more scripts 2013-12-24 13:21:40 +00:00
swordshine
e7046c9bf5 - Update more scripts 2013-12-24 10:54:44 +00:00
swordshine
8d87b0256b - Update more scripts 2013-12-24 10:30:26 +00:00
Maxmtg
802aa167a9 Added input to select both players and cards for tokens created by Hero of Bladehold 2013-12-24 09:23:14 +00:00
swordshine
b83bd41716 - Update more scripts 2013-12-24 07:06:01 +00:00
swordshine
7c8cb3053a - Update more scripts 2013-12-24 06:24:29 +00:00
swordshine
7c9fb9f6b4 - Update some scripts 2013-12-24 05:21:11 +00:00
swordshine
68989d3e31 - Cleanup 2013-12-24 02:08:18 +00:00
swordshine
51a0745348 - Refactored Entwine ability 2013-12-24 02:06:22 +00:00
drdev
3505a2bcd5 Add FOptionPane
Make FDialog title use skinned font
2013-12-23 23:05:17 +00:00
drdev
0581a5e42b Fix Mac FDialog crash properly 2013-12-23 21:16:40 +00:00
drdev
7ea839334c Fix setShape issue without try/catch block 2013-12-23 17:06:39 +00:00
drdev
be7cce4300 Prevent FDialog crashing on Mac. 2013-12-23 16:46:03 +00:00
drdev
c78251a90e Improve appearance of FDialogs
Make CardListViewer use FDialog and display on screen
2013-12-23 10:45:31 +00:00
Maxmtg
c3c8fd7186 improve random choice of N cards
remove gui calls from choosePile effect
2013-12-23 09:05:50 +00:00
drdev
3d97768f71 Code cleanup 2013-12-23 04:52:08 +00:00
swordshine
f2c93cb5dd - Fixed Maelstrom Nexus and similar cards 2013-12-23 04:37:59 +00:00
drdev
689ef0cf8a Make selection after adding/removing cards from deck behave as expected and improve performance of adding multiple cards at once
Support Ctrl+F in Current Deck pane
Prevent losing multi-selection when using Left/Right arrow keys to switch focus between Catalog and Deck
2013-12-23 03:03:33 +00:00
swordshine
77de4abfd1 - Fixed Battalion Triggers check requirements when resolving 2013-12-23 02:58:10 +00:00
Maxmtg
dc16b75c94 minimize need to player type checks 2013-12-22 23:13:07 +00:00
Maxmtg
3a0fdb4d4f remove gui calls from untap 2013-12-22 22:50:01 +00:00
Maxmtg
32b0f8333d remove calls to gui from game code 2013-12-22 22:36:36 +00:00
drdev
446dfd2257 Add +/- buttons to Deck Editor Quantity column 2013-12-22 20:43:11 +00:00
drdev
faa9947974 Fix so tooltips don't always appear for all columns of table 2013-12-22 19:09:33 +00:00
drdev
c75971e8c5 Get favorites feature working again 2013-12-22 18:20:36 +00:00
Maxmtg
2c850cbe53 clash - gui call replaced by gameAction.notifyOfValue
proliferate - single executor for human and AI, chooseProliferation method added to PlayerController
2013-12-22 18:04:00 +00:00
Chris
a060f5f322 Added new card names to changes.txt. 2013-12-22 15:00:26 +00:00
Maxmtg
5367811a33 moved card prefrences to gui 2013-12-22 13:08:28 +00:00
Maxmtg
7d41ae1331 revert unwanted "preferences" from game-core.
remove gui calls
2013-12-22 13:06:27 +00:00
swordshine
f55abfa576 - Added Tariff 2013-12-22 13:03:31 +00:00
drdev
79b8340b80 Fix bug with sort priorities getting messed up 2013-12-22 10:21:53 +00:00
drdev
e0b7034f97 Fix so favorites appear on top by default when column first clicked 2013-12-22 10:03:57 +00:00
drdev
b79876c959 Support hiding Favorite column from Editor Preferences pane 2013-12-22 09:39:00 +00:00
drdev
e159c25f6d Improve appearance of star icons 2013-12-22 09:07:47 +00:00
drdev
d16eedd1b3 Update CHANGES.txt to mention Deck Editor usability improvements 2013-12-22 08:41:08 +00:00
drdev
a062d61c8d Support marking cards as favorites in catalog 2013-12-22 08:39:20 +00:00
drdev
471e5b5399 Support mana icons 13, 14, 17, 18, 19
Reorganize a couple mana symbols in skin
2013-12-21 22:29:27 +00:00
drdev
577f94a67f Fix firebloom and simpsons mana icons 2013-12-21 22:01:29 +00:00
drdev
f7e05491da Prevent 16/17 mana cost icons being cut off 2013-12-21 21:56:09 +00:00
drdev
2771b4fe1f Fix mana cost rendering in table
Start favorites column
2013-12-21 19:43:52 +00:00
Sol
b5830fac6e - Command Tower taps for Controller Commander's CI, not the owners. 2013-12-21 17:34:25 +00:00
drdev
d8511c92c0 Fix so Pack and Multicolor filter buttons work correctly when only they are toggled off 2013-12-21 17:33:30 +00:00
Sloth
1ea41edd6a - Added the hard quest opponent Abe Sapien 3. 2013-12-21 07:28:38 +00:00
swordshine
4f79f92940 - Converted Sphinx of Jwar Isle to script 2013-12-21 03:16:16 +00:00
swordshine
e13865a966 - Converted "You may discard CARDNAME any time you could cast an instant." to script 2013-12-21 01:08:36 +00:00
Maxmtg
05e1161632 this should prevent some NPE 2013-12-20 20:40:33 +00:00
Sloth
feae947742 - Fixed Tsabo's Decree. 2013-12-20 16:13:44 +00:00
Sloth
9ef69149ee - Fixed preventRunAwayActivations to work with temporary abilities.
- AI updates and code cleanup.
2013-12-20 15:45:27 +00:00
Chris
04ca668807 dded new card names to changes.txt. 2013-12-20 14:46:42 +00:00
Sloth
489af75669 - Updated the quest deck Optimus Prime 3. 2013-12-20 14:44:19 +00:00
swordshine
c8e1aff861 - Update mana replacements in ComputerUtilMana 2013-12-20 08:49:00 +00:00
Maxmtg
373bcd0351 commit 24000 FTW! (remove gui calls from untap) 2013-12-20 08:40:08 +00:00
swordshine
c08e984e35 - Added Hall of Gemstone 2013-12-20 08:06:33 +00:00
drdev
5dee59e8e5 Make Pack stat label appear in color and cmc filters too so each toggle button filter has the same button count and works the same way when left clicking other filters. 2013-12-20 04:57:04 +00:00
drdev
350dbeb12f Add back Pack filter button to Spell Shop 2013-12-20 03:35:32 +00:00
swordshine
fdc2eb66aa - Added Scrambleverse 2013-12-20 00:33:16 +00:00
Maxmtg
ef332e4568 move HumanPlay, PlayerControllerHuman to forge.gui.player package 2013-12-20 00:22:20 +00:00
Maxmtg
93c7d28714 moved limited play to a different package (since they don't belong to game module) 2013-12-19 23:17:04 +00:00
Maxmtg
5d8225f041 eliminate gui calls 2013-12-19 23:15:32 +00:00
Maxmtg
b501c76f7c some more gui calls gone 2013-12-19 23:03:28 +00:00
Maxmtg
97526110d0 removing direct references from game to gui 2013-12-19 22:20:28 +00:00
drdev
f8a4c5db92 Fix Statistics tooltips 2013-12-19 06:22:00 +00:00
drdev
2093d23e24 Add Card CMC toggle button filters
Enhance Filters menu to support adding Color and Type filters
2013-12-19 06:14:49 +00:00
drdev
7e32b752a0 Refactor ItemTable into ItemListView and ItemView base class
Add combo box for selecting view
2013-12-19 04:29:59 +00:00
Sloth
4b02708bb0 - Updated the Sherlock Holmes quest decks. 2013-12-18 15:47:50 +00:00
Chris
9684d69bd1 Added new card names to changes.txt. 2013-12-18 15:07:57 +00:00
swordshine
f6d07944d8 - Converted TokenDoubler to script 2013-12-18 11:38:07 +00:00
swordshine
46796041c7 - Added Primal Vigor 2013-12-18 10:33:44 +00:00
swordshine
196a782f8c - Update 3 scripts 2013-12-18 05:25:41 +00:00
swordshine
4839d05b70 - Update two scripts 2013-12-18 04:27:09 +00:00
drdev
d8b6140692 Refactor previous fix 2013-12-17 22:14:17 +00:00
Sloth
040e51f124 - Fixed two scripts missing a nonToken restriction. 2013-12-17 22:11:07 +00:00
drdev
a24161db2b Support search for non-card items in SpellShop 2013-12-17 21:42:21 +00:00
drdev
117501c511 Fix SpellShop item manager to not crash and support filtering 2013-12-17 21:21:35 +00:00
moomarc
1c122b99e9 - Fixed Rotted Ones Lay Siege 2013-12-17 10:24:15 +00:00
drdev
6970c1e7cf Fix ratio in Current Deck item manager
Add captions before ratios in item managers
Fix padding around header in Current Deck pane
2013-12-16 19:28:33 +00:00
drdev
d56cecdba4 Integrate filters into ItemManager 2013-12-16 09:10:40 +00:00
Sloth
8ebf514dab - Fixed possible NPE in ChooseSourceAi. 2013-12-15 22:36:14 +00:00
Sol
1376f0dde2 - Fixing mana symbols for a few devotion cards 2013-12-15 16:50:42 +00:00
Sloth
dbacf597da - Updated some quest decks. 2013-12-15 11:17:58 +00:00
Sloth
87eaf96fa1 - Fixed Reparations triggering on creatures not on the battlefield. 2013-12-14 21:21:09 +00:00
Sloth
13db59aac8 - Fixed possible source for NPE's in RemoveFromCombatEffect. 2013-12-14 20:56:21 +00:00
Sol
9a46768de6 - Starke is already removed from combat by the GainControl code, and whatever he's destroying should be removed by the destruction code. 2013-12-14 19:02:50 +00:00
Chris
3c5010cebf Cleared out the changes.txt file, now ready for new material. 2013-12-14 15:35:37 +00:00
Sloth
d25b197c09 - Fixed Legion's Initiative. 2013-12-14 07:52:54 +00:00
Chris
b892cfa029 [maven-release-plugin] prepare for next development iteration 2013-12-13 15:54:18 +00:00
Chris
23a012364b [maven-release-plugin] prepare release forge-1.5.7 2013-12-13 15:54:07 +00:00
Chris
ed0f3600f5 Preparing the changes.txt file for the next beta build and release. 2013-12-13 15:39:28 +00:00
drdev
dd4e250432 Fix compilation problem 2013-12-13 08:05:42 +00:00
drdev
2ffb71e053 Code cleanup 2013-12-13 08:04:36 +00:00
Maxmtg
be25cf699c removed input play or draw (for being a special case of InputConfirm)
added optional param to chooseCreatureType
2013-12-13 07:51:27 +00:00
drdev
1cc15fe50c Update CHANGES.txt 2013-12-13 07:40:21 +00:00
drdev
a04e5c1da2 Skin FDialog 2013-12-13 07:29:55 +00:00
Maxmtg
5b18ba9058 Cost.chooseXValue moved to member of CostPart 2013-12-13 07:10:23 +00:00
Maxmtg
753f4d989b renamed InputYesOrNo, removed static methods from it, added a method to confirmPayment to PlayerController 2013-12-13 07:01:30 +00:00
Maxmtg
8960fa20c3 added showAndWait method to InputSyncronizedBase - it holds the long chain of calls to reach Control's input queue. 2013-12-13 06:25:55 +00:00
drdev
38344027ca Show cost payment prompts during ability resolve using Prompt pane instead of a dialog 2013-12-13 06:17:03 +00:00
drdev
90ff1abab8 Code cleanup 2013-12-13 05:48:35 +00:00
drdev
7fe3799ea6 Code cleanup 2013-12-13 05:19:09 +00:00
drdev
5ed6fba085 Code cleanup 2013-12-13 05:04:27 +00:00
drdev
6c3573d854 Use Prompt pane instead of dialogs for cost-related questions 2013-12-13 04:48:31 +00:00
drdev
d00aeffbda Add static "ask" API to InputYesOrNo 2013-12-13 03:07:15 +00:00
drdev
e247b8e368 Update CHANGES.txt 2013-12-13 02:40:36 +00:00
drdev
3d54fd3b7b Prompt Yes or No for optional triggered abilities using Prompt pane rather than dialog 2013-12-13 02:37:09 +00:00
drdev
b19b5daf48 Refactor confirmTrigger into controller class 2013-12-13 02:02:54 +00:00
drdev
f48952aa94 Added notes to CHANGES.txt 2013-12-13 01:06:37 +00:00
drdev
e8d4433bb3 Tweak follow up logic after auto payment 2013-12-13 00:59:45 +00:00
drdev
84b0e17572 Fix so you're still prompted for a color when paying cards that care what colors are spent to cast them 2013-12-12 14:53:17 +00:00
drdev
e4ba6f56dd Fix so GUI thread not locked while waiting for Auto payment 2013-12-12 12:57:08 +00:00
drdev
bdfd2e9adf Avoid prompting for color when using "Add one mana of any color" effect to pay for a colorless cost 2013-12-12 12:43:50 +00:00
drdev
849655cb2f Fix so Auto payment occurs in Game thread 2013-12-12 11:49:50 +00:00
swordshine
1c391a7c7e - Fixed Varolz 2013-12-12 11:36:41 +00:00
Sloth
cf1990ddf7 - Fixed Ragged Veins. 2013-12-11 15:04:35 +00:00
drdev
fad3ea497d Code cleanup 2013-12-11 04:05:17 +00:00
drdev
f586525a61 Ensure index in hand zone updated when card drag dropped into new position 2013-12-10 16:27:11 +00:00
Chris
832a290778 Added new card names to changes.txt. 2013-12-10 13:26:11 +00:00
swordshine
ecbba9f1c0 - Added Sheltering Ancient 2013-12-10 13:10:32 +00:00
drdev
afeb4eb815 Fix so canceled spells return to same place in your hand as they were cast from 2013-12-10 02:50:24 +00:00
drdev
d0b5e78f7a Code cleanup 2013-12-10 01:13:34 +00:00
drdev
1837234650 Revert change that prevented a spell moving on the stack until after prerequisites were met 2013-12-10 00:24:21 +00:00
drdev
c65031ea31 Avoid removing source card from lists 2013-12-10 00:17:46 +00:00
Chris
14a7176325 Added a new piece to the Known Issues section. 2013-12-09 19:23:32 +00:00
swordshine
a0c3a1eb05 - Clones are able to copy LevelUp abilities 2013-12-09 04:03:02 +00:00
drdev
f7af3865b7 Allow canceling discarding cards to pay cost 2013-12-09 00:03:18 +00:00
drdev
51a0c08042 Prevent card exiled to pay its own additional cost 2013-12-08 23:47:53 +00:00
drdev
abc2118a77 Code cleanup 2013-12-08 23:18:40 +00:00
drdev
776ac3ee2b Prevent card discarded to pay its own additional cost 2013-12-08 23:12:07 +00:00
drdev
63eaec8348 Code cleanup 2013-12-08 22:50:59 +00:00
drdev
ddb8464c1c Code cleanup 2013-12-08 22:22:44 +00:00
drdev
29ef7a7d3b Code cleanup 2013-12-08 22:14:19 +00:00
drdev
49aa0cc459 Code cleanup 2013-12-08 22:10:03 +00:00
drdev
cdf1b44cb0 Check static abilities when adding card to zone from nowhere (such as using Dev tools) 2013-12-08 18:47:31 +00:00
drdev
61fe9f2282 Code cleanup 2013-12-08 17:49:49 +00:00
Maxmtg
0b9d254e12 fix NPE caused by null predicate 2013-12-07 23:12:37 +00:00
Maxmtg
77b241eb68 remove another toString method from manacost, update references to use better ways 2013-12-07 22:18:52 +00:00
Sloth
b98ae5844c - Fixed type of Stern Judge. 2013-12-07 21:28:45 +00:00
drdev
507ce6f220 Ensure OK button gets initial focus in DualListBox if remainingSources matches source list count 2013-12-07 20:08:03 +00:00
drdev
4d2a27f7e8 Prevent adding cards in DualListBox using spacebar if add button disabled
Prevent selecting cards to discard with Abandon Hope if 0 cards should have been allowed
2013-12-07 19:54:57 +00:00
drdev
a90841a6b6 Fix conditions under which Auto button enabled on DualListBox 2013-12-07 19:39:33 +00:00
drdev
e9bb6e42f6 Prevent adding cards in DualListBox once specific target reached 2013-12-07 19:30:42 +00:00
drdev
ed4b11d9ef Prevent focusing OK button if DualListBox has no specified count needed 2013-12-07 19:10:16 +00:00
drdev
c115f01edf Fix so OK button in DualListBox gets focus when it becomes enabled 2013-12-07 18:52:10 +00:00
drdev
8fd6bbef3b Code cleanup 2013-12-07 18:29:49 +00:00
drdev
8fa68731d1 Fix so mana refunded when using Auto to pay non-X cost then canceling at X prompt 2013-12-07 18:25:29 +00:00
drdev
b6b586a865 Make {X} appear before generic on card overlays 2013-12-07 17:38:52 +00:00
Chris
457ba444f1 Added new card names to changes.txt. 2013-12-07 14:36:10 +00:00
Sloth
31a367c434 - Added Praetor creature type. 2013-12-07 09:43:13 +00:00
swordshine
e83eb92948 - Added Fight or Flight 2013-12-07 01:50:02 +00:00
Sloth
5ee779846d - Fixed 2 more LKI problems. 2013-12-06 17:11:54 +00:00
Sloth
7a3ecf8e38 - Fixed LKI problems with Mercy Killing and similar cards. 2013-12-06 17:06:12 +00:00
Chris
9e2c96a18e Minor change to the changes.txt file. 2013-12-06 15:23:43 +00:00
Sloth
6550fa28ca - Fixed a bug in DamagePreventAi. 2013-12-06 14:47:30 +00:00
drdev
de9ce7ebb9 Mention recent game play usability improvements in CHANGES.txt 2013-12-06 07:26:54 +00:00
drdev
caae78b6ee Add basic Undo support for untapping mana sources that were tapped when not paying an active mana cost 2013-12-06 07:16:04 +00:00
Maxmtg
495701c46c tap-untap effect is indifferent to playertype 2013-12-06 06:46:24 +00:00
Maxmtg
ed99ce1694 remove gui calls from add/remove counters effects 2013-12-06 06:26:49 +00:00
Maxmtg
51a37e896d move counters no longer uses gui 2013-12-06 06:10:51 +00:00
Maxmtg
b431315e88 removed some gui calls 2013-12-06 05:49:11 +00:00
drdev
ea59f120da Prevent cards disappearing from your hand while paying for them or picking targets 2013-12-06 05:11:36 +00:00
drdev
9bd30e8d5d Code cleanup 2013-12-06 04:37:39 +00:00
drdev
39d1ef7e13 Add Escape as shortcut for Cancel in Prompt even if OK button has focus 2013-12-06 04:24:49 +00:00
drdev
83a1b70efe Ensure game ends if you concede while in the middle of playing a spell/ability 2013-12-05 02:26:06 +00:00
drdev
01b4f803a8 Code cleanup 2013-12-05 02:25:19 +00:00
drdev
5c31890066 Code cleanup 2013-12-05 02:02:34 +00:00
drdev
be7f4e5192 Code cleanup 2013-12-05 01:37:35 +00:00
drdev
4124c45875 Code cleanup 2013-12-05 01:18:28 +00:00
drdev
06e785c75a Code cleanup 2013-12-05 01:10:32 +00:00
drdev
2f384c079c Code cleanup 2013-12-05 00:56:57 +00:00
drdev
e4adada542 Code cleanup 2013-12-05 00:50:42 +00:00
drdev
efa86891cc Code cleanup 2013-12-05 00:38:04 +00:00
drdev
bcc20bb774 Return focus to OK button when returning to match screen 2013-12-05 00:31:41 +00:00
drdev
937a095209 Make runAsAi private 2013-12-05 00:14:06 +00:00
Maxmtg
1661228168 fix npe in PlayerControllerHuman 2013-12-04 21:28:11 +00:00
Chris
b17b9eb4e1 Added new card names to changes.txt. 2013-12-04 13:31:37 +00:00
Maxmtg
2ffa1510ed Player belongs to game, it cannot have references to any concrete PlayerController 2013-12-04 07:46:30 +00:00
swordshine
d1ef107b48 - Added Chorus of the Conclave 2013-12-04 07:05:50 +00:00
drdev
aa48e9cacc Fix so Ok button in DualListBox dialog receives focus as soon as it's been enabled so spacebar will activate it 2013-12-04 03:44:32 +00:00
drdev
3c0bfa7843 Remove extra blank line before "Pay Mana Cost" with optional payment prompt 2013-12-04 02:58:54 +00:00
drdev
803b6331f4 Fix so abilities using InputPayManaExecuteCommands work with Auto button 2013-12-04 02:49:26 +00:00
drdev
fe8af8705d Fix crash when determining if mana costs can be paid for SpellAbilities with no source card 2013-12-04 01:51:44 +00:00
drdev
624365cda3 Prevent AI taking over if exception thrown while AI controller temporarily set 2013-12-04 01:33:42 +00:00
Maxmtg
4fb59b6071 give spelldescriptions to card that offer 'generic' choices 2013-12-03 09:04:09 +00:00
Maxmtg
d15948e44b remove refs to gui and playertype in ChooseGenericEffect 2013-12-03 08:48:19 +00:00
Maxmtg
bf629ff518 choose color now uses player controller to decide.
removed calls to gui from ability executing classes
adjust visibility of CardFace methods
2013-12-03 08:27:44 +00:00
Maxmtg
ee9ee7f207 moved evaluator away from core 2013-12-03 06:56:13 +00:00
Maxmtg
311d4091ff remove runAsAi from playercontroller (it's meant to be indifferent to playercontrollers, and PlayerControllers descendants don't know of thier siblings' existance) 2013-12-03 06:34:29 +00:00
Sol
4e79f508c0 - Fixed issue with formatted mana being used for level up cost 2013-12-03 04:19:31 +00:00
swordshine
90828e6eab - Fixed a bug related to Commander games 2013-12-03 00:58:35 +00:00
Chris
7d3afc35cc Added a fluff piece to the changes.txt file.
Added new card names to changes.txt.
2013-12-02 14:58:46 +00:00
swordshine
6f4c046732 - Added Mana braces for three cards 2013-12-02 13:05:56 +00:00
swordshine
503a8da70f - Added Caller of the Hunt 2013-12-02 12:24:43 +00:00
drdev
1cf9a005d9 Fix places that assumed old format of ManaCost.toString() to either call new getCostString() function or assume {G} formatting
This fixes bugs with Rout ("may cast as instance if you pay 2 more" cards)
This also fixes bugs with Rune Snag ("unless player pays X" cards)
2013-12-02 08:52:30 +00:00
drdev
fe04d56568 Code cleanup 2013-12-02 07:31:12 +00:00
drdev
93b6ac15dd Ensure enters the battlefield triggered abilities are visible on stack 2013-12-02 07:06:50 +00:00
drdev
500632515c Mention Auto button and other game usability improvements in CHANGES.txt 2013-12-02 06:15:26 +00:00
drdev
598d2da9d6 Prevent mana not deducting from pool when manually paying mana costs 2013-12-02 05:56:18 +00:00
drdev
05f7a9b30a Prevent being prompted to decide how to pay mana when clicking Auto by temporarily using AI controller 2013-12-02 05:33:44 +00:00
drdev
0b6be04428 Add "Auto" button for automatically paying a mana cost
Code cleanup
2013-12-02 03:07:19 +00:00
Sol
dcb9553807 - Added Mana braces for Level up Ability and Insidious Bookworms 2013-12-02 01:03:38 +00:00
Chris
c9c9be68b1 Added new card names to changes.txt. 2013-12-01 13:50:11 +00:00
swordshine
53e6671143 - Added Call to Arms 2013-12-01 05:34:21 +00:00
drdev
3d063d8188 Code cleanup and refactoring 2013-12-01 03:50:47 +00:00
drdev
8d3633fe63 Code cleanup 2013-12-01 03:27:17 +00:00
drdev
ee7d64c533 Code cleanup 2013-12-01 03:24:22 +00:00
drdev
5009ebe0ab Code cleanup 2013-12-01 03:21:51 +00:00
drdev
9b2f3f3108 Tweak fix for not prompting if can't attack 2013-12-01 03:14:19 +00:00
drdev
9ca9dc797e Don't prompt to declare blockers if no creatures can block 2013-11-30 22:01:04 +00:00
drdev
2ffc18cc89 Skip combat phases if player has no creatures that can attack 2013-11-30 20:57:30 +00:00
drdev
cfeeda3c93 Cleanup whitespace 2013-11-30 18:50:17 +00:00
drdev
a2277bc2d4 Cleanup whitespace 2013-11-30 18:40:40 +00:00
drdev
694e4e7988 Fix misspelling 2013-11-30 18:39:28 +00:00
drdev
1c0e786489 Code cleanup 2013-11-30 18:31:18 +00:00
drdev
7420e94876 Rename CMessage to CPrompt to better match tab caption 2013-11-30 18:19:22 +00:00
drdev
73c921bb95 Increase contrast between Inactive color and background texture in Journeyman theme 2013-11-30 18:00:13 +00:00
Chris
7a22f4f74a - Added a fluff piece to the changes.txt file.
- Cleared out the changes.txt file, now ready for new material.
2013-11-30 15:15:56 +00:00
drdev
cdb76d344e Fix display of 0 loyalty planeswalker abilities 2013-11-30 07:26:10 +00:00
drdev
6cbded92cb if colorless filtered out ensure phyrexian cards don't appear unless at least one of their colors is selected 2013-11-30 07:04:21 +00:00
drdev
bc032a074c Optimize logic for no cost cards 2013-11-30 06:46:20 +00:00
drdev
89a4afdc08 Prevent cards with no mana cost showing up if they're color is filtered 2013-11-30 06:28:36 +00:00
drdev
be6266d633 Improve filter logic to support showing playable hybrid and phyrexian cards even if filtering out colors present in the card's mana cost that aren't needed to cast it 2013-11-30 05:45:30 +00:00
drdev
705264ba9a Ensure multicolor filter selected after right-clicking a color filter 2013-11-30 00:56:05 +00:00
drdev
a0b181e6fe Don't filter out multicolor cards after right-clicking a color filter 2013-11-30 00:51:09 +00:00
drdev
df50a0a38d Support showing only colorless or multicolor cards 2013-11-30 00:27:47 +00:00
Chris
abd182e17f [maven-release-plugin] prepare for next development iteration 2013-11-29 15:06:44 +00:00
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
20550 changed files with 386773 additions and 266753 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"/>

32516
.gitattributes vendored

File diff suppressed because it is too large Load Diff

223
.gitignore vendored
View File

@@ -2,20 +2,225 @@
/*.iml
/*.tmp
/.metadata
forge-ai/forge-ai.iml
forge-ai/target
forge-core/forge-core.iml
forge-core/target
forge-game/target
forge-gui-android/*.keystore
forge-gui-android/assets/fallback_skin/Thumbs.db
forge-gui-android/bin
forge-gui-android/gen
forge-gui-android/res/Thumbs.db
forge-gui-android/res/bin
forge-gui-android/res/drawable-hdpi/Thumbs.db
forge-gui-android/res/drawable-hdpi/bin
forge-gui-android/res/drawable-hdpi/gen
forge-gui-android/res/drawable-hdpi/target
forge-gui-android/res/drawable-ldpi/Thumbs.db
forge-gui-android/res/drawable-ldpi/bin
forge-gui-android/res/drawable-ldpi/gen
forge-gui-android/res/drawable-ldpi/target
forge-gui-android/res/drawable-mdpi/Thumbs.db
forge-gui-android/res/drawable-mdpi/bin
forge-gui-android/res/drawable-mdpi/gen
forge-gui-android/res/drawable-mdpi/target
forge-gui-android/res/drawable-xhdpi/Thumbs.db
forge-gui-android/res/drawable-xhdpi/bin
forge-gui-android/res/drawable-xhdpi/gen
forge-gui-android/res/drawable-xhdpi/target
forge-gui-android/res/drawable-xxhdpi/Thumbs.db
forge-gui-android/res/drawable-xxhdpi/bin
forge-gui-android/res/drawable-xxhdpi/gen
forge-gui-android/res/drawable-xxhdpi/target
forge-gui-android/res/gen
forge-gui-android/res/layout/Thumbs.db
forge-gui-android/res/layout/bin
forge-gui-android/res/layout/gen
forge-gui-android/res/layout/target
forge-gui-android/res/target
forge-gui-android/res/values/Thumbs.db
forge-gui-android/res/values/bin
forge-gui-android/res/values/gen
forge-gui-android/res/values/target
forge-gui-android/target
forge-gui-desktop/*.iml
forge-gui-desktop/target
forge-gui-ios/target
forge-gui-mobile-dev/bin
forge-gui-mobile-dev/fallback_skin/Thumbs.db
forge-gui-mobile-dev/res
forge-gui-mobile-dev/target
forge-gui-mobile-dev/testAssets
forge-gui-mobile/bin
forge-gui-mobile/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/res/skins/*.log
forge-gui/res/skins/PerSetTrackingResults
forge-gui/res/skins/Thumbs.db
forge-gui/res/skins/arabian_nights/*.log
forge-gui/res/skins/arabian_nights/PerSetTrackingResults
forge-gui/res/skins/arabian_nights/Thumbs.db
forge-gui/res/skins/arabian_nights/decks
forge-gui/res/skins/arabian_nights/layouts
forge-gui/res/skins/arabian_nights/pics*
forge-gui/res/skins/arabian_nights/pics_product
forge-gui/res/skins/comic/*.log
forge-gui/res/skins/comic/PerSetTrackingResults
forge-gui/res/skins/comic/Thumbs.db
forge-gui/res/skins/comic/decks
forge-gui/res/skins/comic/layouts
forge-gui/res/skins/comic/pics*
forge-gui/res/skins/comic/pics_product
forge-gui/res/skins/dark_ascension/*.log
forge-gui/res/skins/dark_ascension/PerSetTrackingResults
forge-gui/res/skins/dark_ascension/Thumbs.db
forge-gui/res/skins/dark_ascension/decks
forge-gui/res/skins/dark_ascension/layouts
forge-gui/res/skins/dark_ascension/pics*
forge-gui/res/skins/dark_ascension/pics_product
forge-gui/res/skins/decks
forge-gui/res/skins/default/*.log
forge-gui/res/skins/default/PerSetTrackingResults
forge-gui/res/skins/default/Thumbs.db
forge-gui/res/skins/default/decks
forge-gui/res/skins/default/layouts
forge-gui/res/skins/default/pics*
forge-gui/res/skins/default/pics_product
forge-gui/res/skins/firebloom/*.log
forge-gui/res/skins/firebloom/PerSetTrackingResults
forge-gui/res/skins/firebloom/Thumbs.db
forge-gui/res/skins/firebloom/decks
forge-gui/res/skins/firebloom/layouts
forge-gui/res/skins/firebloom/pics*
forge-gui/res/skins/firebloom/pics_product
forge-gui/res/skins/inferno/*.log
forge-gui/res/skins/inferno/PerSetTrackingResults
forge-gui/res/skins/inferno/Thumbs.db
forge-gui/res/skins/inferno/decks
forge-gui/res/skins/inferno/layouts
forge-gui/res/skins/inferno/pics*
forge-gui/res/skins/inferno/pics_product
forge-gui/res/skins/innistrad/*.log
forge-gui/res/skins/innistrad/PerSetTrackingResults
forge-gui/res/skins/innistrad/Thumbs.db
forge-gui/res/skins/innistrad/decks
forge-gui/res/skins/innistrad/layouts
forge-gui/res/skins/innistrad/pics*
forge-gui/res/skins/innistrad/pics_product
forge-gui/res/skins/journeyman/*.log
forge-gui/res/skins/journeyman/PerSetTrackingResults
forge-gui/res/skins/journeyman/Thumbs.db
forge-gui/res/skins/journeyman/decks
forge-gui/res/skins/journeyman/layouts
forge-gui/res/skins/journeyman/pics*
forge-gui/res/skins/journeyman/pics_product
forge-gui/res/skins/kamigawa/*.log
forge-gui/res/skins/kamigawa/PerSetTrackingResults
forge-gui/res/skins/kamigawa/Thumbs.db
forge-gui/res/skins/kamigawa/decks
forge-gui/res/skins/kamigawa/layouts
forge-gui/res/skins/kamigawa/pics*
forge-gui/res/skins/kamigawa/pics_product
forge-gui/res/skins/layouts
forge-gui/res/skins/marble_blue/*.log
forge-gui/res/skins/marble_blue/PerSetTrackingResults
forge-gui/res/skins/marble_blue/Thumbs.db
forge-gui/res/skins/marble_blue/decks
forge-gui/res/skins/marble_blue/layouts
forge-gui/res/skins/marble_blue/pics*
forge-gui/res/skins/marble_blue/pics_product
forge-gui/res/skins/metalcraft/*.log
forge-gui/res/skins/metalcraft/PerSetTrackingResults
forge-gui/res/skins/metalcraft/Thumbs.db
forge-gui/res/skins/metalcraft/decks
forge-gui/res/skins/metalcraft/layouts
forge-gui/res/skins/metalcraft/pics*
forge-gui/res/skins/metalcraft/pics_product
forge-gui/res/skins/mythic_rare/*.log
forge-gui/res/skins/mythic_rare/PerSetTrackingResults
forge-gui/res/skins/mythic_rare/Thumbs.db
forge-gui/res/skins/mythic_rare/decks
forge-gui/res/skins/mythic_rare/layouts
forge-gui/res/skins/mythic_rare/pics*
forge-gui/res/skins/mythic_rare/pics_product
forge-gui/res/skins/phyrexia/*.log
forge-gui/res/skins/phyrexia/PerSetTrackingResults
forge-gui/res/skins/phyrexia/Thumbs.db
forge-gui/res/skins/phyrexia/decks
forge-gui/res/skins/phyrexia/layouts
forge-gui/res/skins/phyrexia/pics*
forge-gui/res/skins/phyrexia/pics_product
forge-gui/res/skins/pics*
forge-gui/res/skins/pics_product
forge-gui/res/skins/ravnica/*.log
forge-gui/res/skins/ravnica/PerSetTrackingResults
forge-gui/res/skins/ravnica/Thumbs.db
forge-gui/res/skins/ravnica/decks
forge-gui/res/skins/ravnica/layouts
forge-gui/res/skins/ravnica/pics*
forge-gui/res/skins/ravnica/pics_product
forge-gui/res/skins/rebel/*.log
forge-gui/res/skins/rebel/PerSetTrackingResults
forge-gui/res/skins/rebel/Thumbs.db
forge-gui/res/skins/rebel/decks
forge-gui/res/skins/rebel/layouts
forge-gui/res/skins/rebel/pics*
forge-gui/res/skins/rebel/pics_product
forge-gui/res/skins/sleeping_forest/*.log
forge-gui/res/skins/sleeping_forest/PerSetTrackingResults
forge-gui/res/skins/sleeping_forest/Thumbs.db
forge-gui/res/skins/sleeping_forest/decks
forge-gui/res/skins/sleeping_forest/layouts
forge-gui/res/skins/sleeping_forest/pics*
forge-gui/res/skins/sleeping_forest/pics_product
forge-gui/res/skins/smith/*.log
forge-gui/res/skins/smith/PerSetTrackingResults
forge-gui/res/skins/smith/Thumbs.db
forge-gui/res/skins/smith/decks
forge-gui/res/skins/smith/layouts
forge-gui/res/skins/smith/pics*
forge-gui/res/skins/smith/pics_product
forge-gui/res/skins/the_dale/*.log
forge-gui/res/skins/the_dale/PerSetTrackingResults
forge-gui/res/skins/the_dale/Thumbs.db
forge-gui/res/skins/the_dale/decks
forge-gui/res/skins/the_dale/layouts
forge-gui/res/skins/the_dale/pics*
forge-gui/res/skins/the_dale/pics_product
forge-gui/res/skins/the_simpsons/*.log
forge-gui/res/skins/the_simpsons/PerSetTrackingResults
forge-gui/res/skins/the_simpsons/Thumbs.db
forge-gui/res/skins/the_simpsons/decks
forge-gui/res/skins/the_simpsons/layouts
forge-gui/res/skins/the_simpsons/pics*
forge-gui/res/skins/the_simpsons/pics_product
forge-gui/res/skins/zendikar/*.log
forge-gui/res/skins/zendikar/PerSetTrackingResults
forge-gui/res/skins/zendikar/Thumbs.db
forge-gui/res/skins/zendikar/decks
forge-gui/res/skins/zendikar/layouts
forge-gui/res/skins/zendikar/pics*
forge-gui/res/skins/zendikar/pics_product
forge-gui/target
forge-gui/tools/PerSetTrackingResults
forge-gui/tools/oracleScript.log
forge-net/src/main/php/*.php
forge-net/target
/forge.profile.properties
/jgv.txt
/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

@@ -1,39 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ForgeLocal</name>
<name>forge</name>
<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

BIN
AppIcon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

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

View File

@@ -1,700 +0,0 @@
Installation Instructions:
--------------------------
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.
Once the Forge archive has been decompressed you should then be able to launch Forge by using the included launcher. Launching Forge by double clicking on the forge jar file in the past caused a java heap space error. Forge's memory requirements have increased over time and the launchers increase the java heap space available to Forge. Currently you can launch Forge by double clicking on the forge jar file without a java heap space error but this is likely to change as we add in more sounds, icons, etc.
Updating to a newer version Instructions:
-----------------------------------------
- User data migration -
User data files, like decks, saved gauntlets, and card pictures, are now stored in new directories separate from the program data. When this version of Forge is first run, it will scan the program directory for all user data and automatically migrate the files to their new homes. There are three defined user data directores: userDir, cacheDir, and cardPicsDir, and their locations depend on the standard paths for your operating system:
Windows:
userDir=%APPDATA%/Forge/
cacheDir=%LOCALAPPDATA%/Forge/Cache/ (or %APPDATA%/Forge/Cache/ for windows versions before the local/roaming directory split)
OSX:
userDir=$HOME/Library/Application Support/Forge/
cacheDir=$HOME/Library/Caches/Forge/
Linux:
userDir=$HOME/.forge/
cacheDir=$HOME/.cache/forge/
The appdata directory is hidden by default in Win7. Open a Windows Explorer window (or double-click on My Computer] and in the address field type "%appdata%/forge/" (without the quotes). If that doesn't work, type "%appdata"/roaming/forge".
cardPicsDir is defined as <cacheDir>/pics/cards/ by default. If you wish to use a non-default directory, please see the forge.profile.preferences.example file located in the Forge installation directory root. You can use this file to, for example, share the card pics directory with another program, such as Magic Workstation.
If you are using the Mac OS X version of Forge then you will find the forge.profile.preferences.example file by right clicking or control clicking on the Forge.app icon. Select "Show Package Contents" from the contextual menu. A Finder window will open and will display a folder named Contents. Navigate to the folder:
/Contents/Resources/Java/
and you will find the file named forge.profile.preferences.example.
For reference, here is the full list of moved directories and files:
Old location New location
---------------- ----------------------
res/decks/ <userDir>/decks/
res/gauntlet/ <userDir>/gauntlet/
res/layouts/ <userDir>/preferences/
res/preferences/ <userDir>/preferences/
res/quest/data/ <userDir>/quest/saves/
res/pics/ <cacheDir>/pics/
forge.log <userDir>/forge.log
- New Import Data dialog -
The Import Pictures dialog, accessed via the Content Downloaders submenu, has received an overhaul and has been reincarnated as the Import Data dialog. You may recognize it from the automatic data migration procedure if you had any data to migrate when this version was first started. Instead of just importing pictures from a previous version of Forge, it can now import any kind of Forge data whatsoever. If you have a directory full of deck files, you can use the Import Data dialog to copy or move them to the appropriate directory. If you have just downloaded a torrent of high-quality pics for a particular set, use the Import Data dialog to get them to the proper place. The dialog give you a full listing of all file copy/move operations, so you can see what will happen before you click 'Start Import'.
An importer option was added for including pictures in set-specific card directories that don't map to any currently known card. This handles the case where people have collected complete sets of pics in anticipation of when Forge supports them.
The Mac OS application version:
-------------------------------
We have packaged the Forge BETA version as a Mac OS application. You can double click the Forge.app icon to launch the forge application on your Apple computer running Mac OS. This application will automatically increase the java heap space memory for you as it launches. This version does not require the forge.command file and it does not need to start the Terminal application as part of the start up process.
If you update your OS to Apple OSX 10.8 Mountain Lion and try to launch a new version of forge that you will likely get a dialog which states "File is damaged and cannot be opened. Please move to trash."
Mountain Lion comes with a new Gatekeeper feature and this is probably blocking your ability to launch this newer version of forge. Visit the link below and follow the instructions. They are fairly long and detailed.
http://support.apple.com/kb/HT5290?viewlocale=en_US&locale=en_US
Please note that the issue is most likely caused by Mountain Lion's Gatekeeper feature and it is extremely unlikely that the forge dev team will attempt to get a unique Developer ID from Apple and use it to digitally sign our forge app.
Picture location info:
----------------------
The instructions that were found in this section are now out of date. Current instructions can be found in the CHANGES.txt and forge.profile.properties.example files.
Launching Forge and Memory Issues:
----------------------------------
In the past, some people noticed java heap space errors and lengthy pauses. The memory requirements for Forge have increased over time. The default setting on your computer for the java heap space may not be enough to prevent the above problems.
The technically proficient can launch the forge jar with an argument from the CLI. The argument "-Xmx512m" may work for computers with 1 Gig of memory. Computers with 2 Gigs or more of memory should be able to use "-Xmx1024m" as an argument.
We have created several scripts that will launch the Forge jar with "-Xmx1024m" as an argument. People using Windows OS should double click the "forge.exe" file. People using one of the other *nix OS should double click the "forge.sh" file. People using Apple's Mac OS X should download the Mac version of Forge and then double click the "forge.app" application.
The script file must be located in the same folder as the Forge jar file and the Forge jar file name can not be changed. Otherwise, the scripts will not work.
If you have a low end machine you may find that the scripts above will prevent java heap space errors but will find that Forge still runs very slowly at times.
In this case you can try the following. You can try using low quality pictures rather than the high quality pictures. Or you can try removing all of the jpg pictures from the pics folder.
Forge failed to launch:
-----------------------
If you're trying to run Forge for the first time, but it doesn't open up, you can try the following to get some output and help yourself/us solve the problem.
1) Open up a terminal
- Under Windows, press Windows+R, type "cmd", hit enter
- Under Linux, you probably know that yourself. Use your distribution's application menu, and search for "terminal" in a group like "utilities".
- Launch the program named "Console.app" which can be found in your /Applications/Utilities/ folder. Highlight the "All Messages" option and click on the "Clear Display" button before launching Forge.
2) Go to the folder where you unpacked Forge
- Windows: Let's say your forge is in D:\Programs\Forge.
- Type "D:", Enter to change to the D: drive.
- Type "cd \Programs\Forge", Enter to change to the directory.
- NOTE: On nonenglish systems, you might have problems due to the poor localization of Windows. Go to the innermost directory you find (worst case is "\"), then "dir", Enter to show all folders in that folder. Search for the one you're probably wanting. For Example the German "Programme" could really be "Program Files" or something like that.
- NOTE: You might have to "quote" directory names with Spaces in them
- Linux: Let's say your forge is in /home/user/Forge
- Type "cd /home/user/Forge", Enter
- NOTE: You might have to "quote" or 'quote' directory names with Spaces in them
- Current versions of Forge no longer include a launcher script for Mac OS, proceed to step three.
3) Run Forge
- On Windows, just type "forge.exe", Enter
- On Linux, just type "forge.sh", Enter
- Launch the Forge application bundle by double clicking on the program named "Forge.app".
Now you will probably see some sort of Error in the console. the first few lines contain a message that might help you. If you can't fix the problem yourself, please take the complete output and report your problem on the Forum.
The Card Pictures disappear when you restart Forge:
---------------------------------------------------
if you're running Windows 7, make sure you're running the program as an admin, otherwise no changes will be made to your system (nothing is saved). In Windows 7, Forge may be happier when run from somewhere in the My Documents structure, (they call them Libraries now???) or from another partition other than C:. The user has little permission to do much on the system drive.
Java Issues:
------------
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.
Forge requires Java 6 and will not run if you have an earlier version of Java. You will need to update to Java 6.
Card Picture Issues:
--------------------
The server which contained the high quality card pictures is now off line and these high quality card pictures are no longer available as a download from within the forge application. We apologize, but the current dev team do not maintain this server and this matter is out of our control.
Some people are choosing to re-download all of the low quality card and card set pictures when they install the next version of forge. This consumes large amounts of bandwidth needlessly. Please be careful!
The instructions that were found in this section are now out of date. Current instructions can be found in the CHANGES.txt and forge.profile.properties.example files.
When you install a new version of Forge, please follow the instructions that can be found in the CHANGES.txt and forge.profile.properties.example files. This will allow you to reuse your previous picture files and other user data files. This way you will only have to download the pictures for the new cards.
This should save enough bandwidth that everyone will be able to download the new set pictures from the cardforge server. We do appreciate your efforts to save bandwidth. Thank you.
Reporting Bugs:
---------------
To report a bug with an official beta release, please follow the instructions at http://www.slightlymagic.net/wiki/Forge#I_think_I_found_a_bug_in_Forge._What_do_I_do.3F .
To report a bug (1) with an alpha test, (2) with a nightly build, (3) with something compiled from the official Forge software repository, or (4) with the leading edge (formerly "SVN Bug Reports"), please do not submit your bugs to the forum. Instead, please follow the instructions at http://www.slightlymagic.net/wiki/How_to_File_a_Bug_Report_with_Mantis.
Forge will now allow you to upload a crash report to the Forge forum at CCGH.
A new very hard tier category in Quest mode:
--------------------------------------------
You will notice a new very hard tier category for the opponent. As you change from the previous tier to the next tier (easy to medium, etc.) you will now notice that there is not an abrupt change over. There is now a mixture of decks from the previous tier and the next tier for you to chose from. When you win a match you will complete the advancement to the next tier.
The Forge Booster Draft mode:
-----------------------------
A significant re-write of the Booster Draft functionality has taken place. Draft from the Full card pool, sets/blocks or custom drafts (like cube). The AI will pick cards more intelligently, and builds decks from picked cards. Old method would pick cards for deck and then stop picking new cards.
The developer mode:
-------------------
The developer mode gives us a few new features. These new features will primarily interest the devs as it will now help to test out specific cards while testing combat code changes. You can turn on or off this mode at the Home View -> Game Settings -> Preferences -> Gameplay Options section.
When turned on the battlefield will have a tab named "Dev Mode". There are a number of useful options in this tab. You can disable loss by milling, generate mana in your mana pool, tutor for card, etc.
New foil card image available:
------------------------------
Rob and Marc have worked together to add in a new feature which will overlay a card's image with a foil like film. A few random cards will have a foil like image in constructed mode games and possibly quest mode games. There is a check box on the Home View -> Game Settings -> Preferences view that you can use to turn this feature on or off.
Informational icons overlays for cards on the battlefield:
----------------------------------------------------------
The Battlefield will now display three symbolic icons that will overlay creature cards. These icons are used to denote summoning sickness and whether a creature is attacking or blocking. Added additional icons that will be drawn over the cards in the battlefield for phasing and counters at a later date. The attack/block/phasing icons and counters will now also be shown on large cards, only casting cost will be omitted. Lands and tokens with different amounts/types of counters will no longer stack. Tokens with different summoning sickness will no longer stack. Lands that become creatures will now always be moved to the front row.
Optional choice for abilities that are on the stack:
----------------------------------------------------
When a spell or an ability appears on the stack and it says "(OPTIONAL)" you can right-click it to decide if you want to always accept or to decline it.
Multiple quest files:
---------------------
Multiple quest files are now supported. This allows you to start a new quest and give it a unique name, and it will not overwrite your previous quest game file.
The new UI now uses tabbed panes:
---------------------------------
We now have a tab system for sub-menus in the home screen. Quest mode refactored to fit this tab system. It's now considerably easier to use - less cramped, less clicks, more functionality.
The quest mode card shop:
-------------------------
You can now buy PreCon decks, Starter packs, Tournament packs and Fat packs from the quest mode card shop.
Player Avatar pictures:
-----------------------
The UI has a few new features including the option to pick an avatar from a collection of pictures. This can be accessed from the Settings -> Avatars tab.
The organizational structure of the /res/decks/ folder:
-------------------------------------------------------
The organizational structure of the /res/decks/ folder has been improved and we now have these six subdirectories:
/decks/constructed/
/decks/cube/
/decks/draft/
/decks/plane/
/decks/scheme/
/decks/sealed/
You can place your deck files from an earlier version of Forge into the /res/decks/ folder. When you next launch Forge these decks will be converted to a newer format and will be moved into the proper subdirectory.
Please not that your /decks/ directory no longer resides in you /res/ directory and has been moved to <userDir>/decks/.
User-created themes for Forge's background, fonts, colors and icons:
--------------------------------------------------------------------
When you select a new skin in the Preferences view Forge should save the change to the preference file, quit and then automatically re-launch with the new skin displayed. During testing some people have noticed that Forge is not restarting on their computer and they have to re-launch Forge themselves.
If anyone is interested in creating additional themes for inclusion in the Forge project then you should visit this topic at CCGH:
http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=8449
The Battlefield UI:
-------------------
The Battlefield UI has a new feature implemented which allows us to move and resize the panels to new places on the battlefield. This allows us to personalize the battlefield display to our own liking. You should try moving panels by clicking and dragging their tabs.
If you do not like your efforts to personalize the battlefield display you can revert the display to the default layout by clicking on the Dock button labeled "Revert layout".
The pets in quest mode:
-----------------------
Some adjustments to the pets in quest mode were made. The quest mode plant wall's Deathtouch ability was deemed to be too strong against the AI's attack code and this ability was changed to Wither in this version. This includes a new pet.
The dock tab has a new button labeled "Open Layout":
----------------------------------------------------
The dock now has a new button labeled "Open Layout" along with old button with original function "Revert Layout". Modifying the battlefield layout will result in your changes being saved to a file named "match_preferred.xml". You can copy and rename that file to share your layouts with other people.
The new Deck Editors:
---------------------
The work on the new UI is now finished and this version adds the new UI to the deck editors. We all would like to thank Doublestrike for his contributions to the new UI.
The new deck editors include:
* a better text search (can search for multiple terms, and "not" terms
* interval filters for P/T and CMC
* add/remove 4
* better statistics and draw probabilities
* Toggle-able, sort-able, resize-able, move-able columns
* and of course uses the drag cell layout.
Performance issues on low end machines:
---------------------------------------
Several people have noticed forge slowing down after playing a number of matches without quitting forge in between the matches that are played. The new UI may be involved somehow. We also hope to have this figured out and fixed in the near future. Please be patient in the meanwhile. A recent fix was implemented that should improve the slowdown problem somewhat.
A lot of time and effort have gone into fixing the memory leak problems that were recently noticed and reported to the dev team. Doublestrike and Slapshot deserve our applause and we are very thankful. People should be able to now play long multi match sessions without noticing slow downs and pauses.
Some performance changes were made to Forge and it should now operate more quickly on low end machines. Mid to high level machines are unlikely to notice as much of a performance increase. We tried to hunt down all of the bugs that resulted from these changes but there may still be a bug or two in this beta release.
A note about winning booster packs in quest mode:
-------------------------------------------------
If you win a quest mode match, you get a booster pack for every 1 or 2 (default) Wins, depending on the difficulty level. If you lose and you are playing on easy mode, you get a booster pack every 1 (default) Loss.
The new UI:
-----------
The first step was to update the battlefield window. The second step was to update the New Game window (now named Home view). We got constructed mode and then quest modes working first. We got the draft and sealed modes working again afterwards.
The work on the new UI is now for the most part finished. We should not expect major changes or major additions to the UI. Future betas may include a few minor bug fixes to the UI. And we may also include a few minor tweaks.
The new Alpha Strike button:
----------------------------
A new Alpha Strike button was added to the dock. The Dock is one of the tabs availble in the battlefield view.
Using Forge with the new Mac OS Mountain Lion:
----------------------------------------------
If you update your OS to Apple OSX 10.8 Mountain Lion and try to launch a new version of forge that you will likely get a dialog which states "File is damaged and cannot be opened. Please move to trash."
Mountain Lion comes with a new Gatekeeper feature and this is probably blocking your ability to launch this newer version of forge. Visit the link below and follow the instructions. They are fairly long and detailed.
http://support.apple.com/kb/HT5290?viewlocale=en_US&locale=en_US
Please note that the issue is most likely caused by Mountain Lion's Gatekeeper feature and it is extremely unlikely that the forge dev team will attempt to get a unique Developer ID from Apple and use it to digitally sign our forge app.
The Forge sealed deck mode:
---------------------------
Sealed Deck mode has had a complete rewrite. Full cardpool, block and custom modes are supported. Custom sealed files in the res/sealed folder are exactly the same as custom draft files, except the file extension ".sealed".
A distinction may now be made between AI decks and Human decks, with the addition of a deck Metadata "PlayerType", which right now just helps by sorting human decks into the human combo box and AI decks into the AI combo box.
The Forge sealed deck mode has undergone significant changes. You can find these in the 1.2.14 beta and later versions. Instead of a single sealed deck match, you can now choose a 1-5 round gauntlet-style tournament where you will face increasingly difficult (probably) opponent decks. You can also choose to use starter packs instead of boosters in the block mode, choose to use 3-12 boosters instead of the default 6 in the full cardpool and custom (cube) modes, and so on.
Perhaps the most notable changes to the sealed deck mode are related to "fantasy blocks" and the greatly increased flexibility you have when you are building your own blocks.
The new Gauntlet mode:
----------------------
A new Gauntlet mode has been added. This mode gives you four options: Quick Gauntlet, Build A Gauntlet, Load Gauntlet and Gauntlet Contests. You can create a group of computer decks to play against by choosing either Custom user decks, Quest Decks, Fully random color decks or Semi-random theme decks.
The new Variant mode (was named Multiplayer):
---------------------------------------------
A new multiplayer mode has also been added. You should be able to play against multiple AI opponents at this time. You should note that the current Archenemy mode does not use Schemes at this time.
A lot of things are planned for this new multiplayer mode and it will take time to finish. Please enjoy what we have at this time and be patient. :)
Since Multiplayer is so new, not all cards will be 100% compatible right away as we expand scripting to handle multiple players.
The older match layout files are incompatible with the new multiplayer mode. The original match_default.xml, match_preferred.xml and the match_preferred.xml saved to a different name files have to go and can no longer be used. You can keep your editor_preferred.xml file. But you will have to setup your match view panels using the new match_default.xml file.
The new damage dialog:
----------------------
The new damage dialog now uses the new UI.
When choosing cards, sources, etc. using a list box:
----------------------------------------------------
When choosing cards, sources, etc. using a list box, the currently selected card will now be visually highlighted on the play field (to better distinguish between e.g. three different cards with the same name on the play field). Now the visual highlighting of a card will also work when declaring the order of blockers.
Return to Ravnica Guild Sealed Deck mode:
-----------------------------------------
Added Return to Ravnica Guild Sealed Deck mode. Start a new sealed deck game, choose "Block / Set" and then scroll down until you find "Return to Ravnica Guild Sealed (block)". Select that. From the "Choose Set Combination" menu, select the first option. You will be prompted twice to pick your guild (once for the promo cards, once for the actual booster - you should choose the same guild both times). After that you're ready to go.
Targeting arrows are now available in the battlefield display:
--------------------------------------------------------------
The Targeting Overlay has been fixed and re-enabled. It now correctly shows the targeting arcs in cases when it previously showed them in the wrong direction. The match UI is properly refreshed when the targeting arcs are switched on/off. The defunct "mouseover-only" mode is currently disabled (it crashes Forge, difficult to fix).
The visuals for targeting arrows has been improved and looks better, with an adaptation of the arrow drawing code from MAGE. Thanks to the MAGE team for permission for the adaptation.
Some people have noticed slowdowns when Targeting arrows are enabled. The battlefield Dock tab includes a targeting icon. You can set the targeting arrows to Off or to Card mouseover to speed up the game.
The new sound system:
---------------------
Forge now has a sound effect system in place. Several basic sounds are linked to the code now and will be enabled when "Enable Sounds" option is checked in the preferences. It supports WAV and AU file formats.
Currently supported sound effects are:
(the ones already available in the standard installation of Forge are marked with a [*])
AddCounter [*] - add_counter.wav - triggered when a counter is added to a permanent.
Artifact[*] - artifact.wav - triggered when an artifact is played.
ArtifactCreature [*] - artifact_creature.wav - triggered when an artifact creature is played.
BlackLand [*] - black_land.wav - triggered when a land with the "B" mana ability is played.
Block [*] - block.wav - triggered when a blocker is assigned.
BlueLand [*] - blue_land.wav - triggered when a land with the "U" mana ability is played.
Creature [*] - creature.wav - triggered when a creature is played.
Damage - damage.wav - triggered when a creature is damaged.
Destroy [*] - destroy.wav - triggered when a permanent is destroyed.
Discard [*] - discard.wav - triggered when a player discards a card.
Draw [*] - draw.wav - triggered when a player draws a card.
Enchantment [*] - enchant.wav - triggered when an enchantment is played.
EndOfTurn [*] - end_of_turn.wav - triggered at the end of turn.
Equip [*] - equip.wav - triggered when an equipment is equipped.
FlipCoin [*] - flip_coin.wav - triggered when a coin is flipped.
GreenLand [*] - green_land.wav - triggered when a land with the "G" mana ability is played.
Instant [*] - instant.wav - triggered when an instant is played.
LifeLoss [*] - life_loss.wav - triggered when a player loses life.
LoseDuel[*] - lose_duel.wav - triggered when a player loses a duel.
ManaBurn - mana_burn.wav - triggered during a mana burn if the appropriate rule is enabled.
OtherLand - other_land.wav - triggered when a land with non-color mana abilities or any other land is played.
Planeswalker [*] - planeswalker.wav - triggered when a planeswalker is played.
Poison [*] - poison.wav - triggered when a player receives a poison counter.
RedLand [*] - red_land.wav - triggered when a land with the "R" mana ability is played.
Regen - regeneration.wav - triggered when a creature is regenerated.
RemoveCounter - remove_counter.wav - triggered when a counter is removed from a permanent.
Sacrifice - sacrifice.wav - triggered when a permanent is sacrificed.
Sorcery [*] - sorcery.wav - triggered when a sorcery is played.
Shuffle [*] - shuffle.wav - triggered when a player shuffles his deck.
Tap [*] - tap.wav - triggered when a permanent is tapped.
Token [*] - token.wav - triggered when a token is created.
Untap [*] - untap.wav - triggered when a permanent is untapped.
WhiteLand [*] - white_land.wav - triggered when a land with the "W" mana ability is played.
WinDuel [*] - win_duel.wav - triggered when a player wins the duel.
All sounds use the event bus model now and are not called directly.
The new Vanguard mode:
----------------------
We now have a Vanguard mode implemented. This is a work in progress. The older match layout files are incompatible with the new Vanguard mode. The original match_default.xml, match_preferred.xml and the match_preferred.xml saved to a different name files need to be deleted and can no longer be used. You can keep your editor_preferred.xml file. But you will have to setup your match view panels using the new match_default.xml file.
The new Archenemy mode:
-----------------------
Schemes have been added to the Archenemy mode. This is a work in progress and there may be a bug or two for us to find.
Quest Worlds:
-------------
This version allows you to travel between the regular quest world and the other worlds (Shandalar, Ravnica, Jamuraa, more may be added in the future) to get different duel opponents and challenges. You will have to complete your current challenges before traveling or you will lose them.
World-specific format enforcing and starting world selection are available. Something has to be done about locked (non-repeatable) challenges so they do not end up locking other challenges in different worlds.
Forge now has sideboards for the human player:
----------------------------------------------
Sideboards have been implemented for Human players. We currently have:
* Sideboard creation support in relevant deck editor modes.
* In-game sideboarding with persistence between rounds in a match and sorting of cards in the in-game sideboard editor.
* Sideboard supported as a zone, with some relevant cards already in.
* Correct validation of decks, both before the game starts and between the rounds (Limited min 40, Constructed min 60, free-form sideboard/main in Draft and Sealed, 1:1 sideboarding with 0 or 15 cards allowed in sideboard in Constructed (all variants) and Quest; OK to have less than minimum between rounds in a match in all modes if lost cards on ante).
* Correct (fingers crossed) interaction of sideboarding with other relevant aspects of Forge rule enforcement (mulligan and ante interactions were corrected, initial hand and library between rounds were both corrected, everything else looks so far so good).
We don't yet have:
* AI sideboarding.
The deck conformance/legality limitation:
-----------------------------------------
The deck conformance/legality is now a user-toggable preference and is enabled by default. You no longer need to turn on dev mode to play an illegal deck.
Using Forge on displays that are only 600 pixels tall or slightly larger:
-------------------------------------------------------------------------
The "Sanctioned Format: Constructed" view should now be compatible with displays that are only 600 pixels tall. The deck list at 600 pixels tall should now display three lines of text rather than less than a single line of text.
We are looking for help in finding additional sound files for the new sound feature:
------------------------------------------------------------------------------------
This version of forge includes a few sound files for the new sound effect system. While we have several sounds assigned to a few of the available events there are a number of events that do not yet have a assigned sound file. This should be considered a work in progress and we could use some help in finding interesting sounds that we can add to forge.
The sound files need to be in wav or au format, wav appears to be more widespread but the code can handle either format. The sound files need to be copyright-free and they should be in the public domain.
You can either record your own sounds if you have the necessary equipment or you may be able to find an appropriate sound on a website such as http://www.freesound.org/browse/
You should note that sound files can be large and we would like to avoid this if possible. A good size to shoot for would be 50 K or less. There is a freeware sound editor that may have versions for all operating systems. This app is named Audacity.
We have a forge forum topic at the Collectible Card Games Headquarters web site that is devoted to finding sounds for this new sound system. Please visit this topic and contribute a sound or two. We can use your help and assistance. :)
http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=8570
Notes about the second Quest World, Jamuraa:
--------------------------------------------
A second Quest World, Jamuraa, has been added to Forge. When playing Quest mode, it is now possible to 'Travel' between the regular Quest environment and the two Worlds, Shandalar and Jamuraa, both of which include special formats, opponents and challenges. Or you can start a new Quest in any of them.
Like Shandalar, Jamuraa is a fantasy world. Its peaceful existence has recently been wrecked by a planar conjunction that shattered the barriers between Jamuraa and the infernal planes known as Jahim, Saqar, and Jahannam. The demon planeswalkers who rule those planes, and their hellish sister, Lilith, are now extending their influence over Jamuraa and gradually destroying the whole continent. Your task is to fight their minions and ultimately challenge the four demons - but beware, their destructive might is unfathomable!
From a technical perspective, the following sets are available to the player in Jamuraa:
5th Edition, Arabian Nights, Mirage, Visions, Weatherlight.
Jamuraa contains:
- 81 opponent decks, broken down as follows: 13 'easy' decks, 17 'medium' decks, 31 'hard' decks, and 20 'very hard' decks.
- 9 challenges, including the 4 demon planeswalkers (the 3 demon rulers and Lilith) and 5 other special scenarios set in Jamuraa. All challenges are repeatable. All are fairly hard, and the 4 demon challenges are especially fiendish.
For the most part, the opponent duel and challenge decks are built with the same format restrictions as your own cardpool, and some of the easiest opponent decks were in fact based on a limited cardpool. But there will be exceptions, especially in the hard/very hard decks and challenges, which can be more like Vintage/T1 decks than pure Mirage + 5th Edition decks. There will be older cards here and there, and maybe even a random Tempest card or two (although these are extremely scarce!).
Hint: if you find the later 'Vintage' opponent decks unfair or near-impossible to beat with your 5th Edition/Mirage block cards, you can Travel to Shandalar and collect some old power cards there, and then return to Jamuraa. Just remember to complete your challenges before traveling.
Information on the quest worlds format can be found in this topic:
http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=9258
New Deck Editor features with improved Filters:
-----------------------------------------------
Some work is being done on the various deck editors -- including the quest spell shop -- and we hope to add in additional features while improving the UI. Here is a quick tutorial on the new features:
FILTERS
The Filters tab has been removed and filters are now controlled from the Card Catalog tab. Pretty much everything that used to be a checkbox is now represented by a toggle button. The statistics labels at the top for colors and card types can now be clicked to toggle display of the related cards. Clicking the Total Cards label in the upper left will alternately set all filters on and off.
Text searches are done by just typing the the text box. The results will update as you type. Use the combo box to the right of the text box to set whether the search should be for cards with or without the specified text. The three toggle buttons to the right of the combo box allow you to specify where in the card the text should (or should not) match. Complex text searches, such as for goblin creatures with haste but not with kicker costs, are possible by stacking the search filters. Put the current search filter on the stack by selecting the "Add filter" button to the left of the text box and choosing the "Current text search" option. You can also use the keyboard shortcut Ctrl+Enter (Cmd+Enter on OSX). This will keep your current text search applied, but will clear the text box and allow you to input the next search filter. To perform the example goblin search above, you would:
1) Ensure "in" is displayed in the the combo box. Enter "goblin" in the text box and deselect Name and Text so that only Type is selected.
2) Hit Ctrl+Enter (Cmd+Enter on OSX). Notice the "Contains: 'goblin" in: type" filter appears below the text box.
3) Type "haste" in the text box. Deselect Type and select Text. Hit Ctrl+Enter.
4) Change the combo box from "in" to "not in". Type "kicker" in the text box.
The shown entries match your combined search filter. Click the little 'x' in the upper right corner of each search widget to remove that filter from the filter stack.
Format filters allow you to restrict the shown cards to those that are legal in a particular format. Select the "Add filter" button, hover over the "Format" submenu, and choose one of the defined formats. The filter will appear below the text box and will be combined with whatever other filters you have on the stack. Hover the mouse over the filter widget to see details on allowed sets and banned cards. Keep in mind that cards from other, non-listed sets may still appear in the results if they are just reprints of allowed cards.
Set filters are similar to format filters except that a window will come up with a grid of checkboxes so you can select exactly which sets you would like shown. There is a checkbox at the bottom (off by default) that will allow the filter to include cards reprinted in unselected sets, just like the format filter above. If you don't check this checkbox, only cards printed in the selected sets will be shown, allowing you to focus on just that set's version of a particular card. This is very useful in quest mode when determining which cards in a set you have yet to collect.
Value range filters allow you to restrict the cards by power, toughness, and/or converted mana cost (CMC). The text boxes that appear in the filter widget are editable and update the shown cards in realtime as you modify the numbers.
Quest World filters are similar to Format filters in that they restrict the shown cards to a group of sets, respecting lists of banned cards. They are useful when constructing decks that will be valid in the various quest worlds. You can have more than one quest world filter active at the same time; useful if you are constructing a deck that will be used in multiple worlds.
SPELL SHOP
The spell shop interface has also received some usability enhancements. The first one you may notice is the addition of a new column named "Owned". This column is intended to help players decide whether buying an item is likely to be beneficial. The data in this column varies depending on what kind of item the row represents:
Cards: A number indicating how many of a particular card a player already owns
Preconstructed decks: A "YES" or "NO" indicating whether the deck exists in the player's deck list
Booster/fat packs: A percentage indicating how close a player is to completing the related set. "Complete" means at least one of every basic land and at least 4 of every other card.
If you don't want this column, it can be turned off in the editor preferences.
The new "Sell excess cards" button appears above the player's library. Clicking it will sell all cards that are not basic lands until only four copies of the cards remain. It's a one-click "cleanup" of the library and a great way to safely and quickly regain some cash.
The "Full catalog view" button appears to the left of the "Buy Card" button. Toggling this button will switch between showing the store's inventory and the full catalog. By applying a filter to show only a particular set (or group of sets), players can use this view to discover exactly which cards they do not own. Buying and selling cards is disabled while in this view.
Multibuy: By selecting any number of items and hitting space (or selecting the "Buy Card" or "Sell Card" buttons), a player can buy one of everything selected.
Find-as-you-type is now implemented for Deck Editor tables. Just start typing while the table has focus and the next card with a matching string in its name will be highlighted. If more than one card matches, hit Enter to select the next matching card. A popup panel will appear with the search string so you know what you are searching for. If no cards match the string, the string will be highlighted in red. Normally, if you hit the spacebar while a card is selected in one table, the card will be moved to the other table (catalog/deck). When the popup is displayed, space characters are interpreted as part of the search string. Find-as-you-type mode is automatically exited after 5 seconds of inactivity, or hit Escape to exit find-as-you-type mode immediately.
The Deck Editor has also gained some hotkey and context menu abilities. R-click on a card (or a group of selected cards) for a list of actions and keyboard shortcuts. In particular, you can now transfer cards 4 at a time using the keyboard and interact with the sideboard from anywhere. Also remember that you can jump to the other table with the arrow keys and jump to the text filter with ctrl/cmd+f. From the text filter, you can jump down to the tables by pressing enter.
The Game Log:
-------------
Added a 'copy to clipboard' button on WinLose screen so players can easily copy the game log.
The UI is more keyboard-friendly:
---------------------------------
Work was also done on making the UI more keyboard-friendly. For example, the OK button should now stay focused during matches, so you can advance through the stages by hitting Enter without having to go over and click the button all the time. If you find the button is losing focus, please report it as a bug.
Gatecrash Guild Sealed game mode:
---------------------------------
Gatecrash Guild Sealed game mode has been added. To use it, start a new Sealed Mode Game, select "Block / Set" and "Gatecrash Guild Sealed". Select the first (default) configuration in the "Choose Set Combination" dialog, and when asked to pick your boosters, choose the guild you want twice (once for the guild-specific booster, and then for the extra promo cards).
The following cards are not included in the guild boosters of this game mode because they are not currently implemented in Forge: Bane Alley Broker, Bioshift, Killing Glare, Simic Manipulator.
New User Preferences:
---------------------
The display of clones and copied cards is now a matter of user preference. A user to now choose whether a clone/copied card should use its native artwork or the artwork of the card being cloned. So if Infinite Reflection is played and the "Clones use original card art" preference is checked, the cards that become copies of the enchanted card will still use their own art whereas by default they would all use the card art from the enchanted card.
Flippable Cards:
----------------
Flippable cards -- cards that have an alternate card printed upside-down at the bottom -- will now flip their appearance on the battlefield when in a flipped state. They are now also flippable in the card viewer by clicking on the card image, just like double-sided "transform" cards have been. When flipped this way, the details of the flipped side can be examined in the Card Details oracle text.
High Quality Booster Pictures:
------------------------------
Forge will now download high quality booster pictures. If you are interested in these high quality booster pictures, then you should delete the pictures that are found in your <cacheDir>/pics/boosters/ directory. Then download the new pictures by using the Home View -> Game Settings -> Content Downloaders -> Download Quest Images button.
Flip, Transform and Morph cards:
--------------------------------
When you mouse over a flip, transform or Morph (controlled by you) card in battlefield, you may hold SHIFT to see other state of that card at the side panel that displays card picture and details.
Alternate sound system:
-----------------------
Implemented an alternative sound system for people who have issues with sound gradually or instantly disappearing on certain Linux systems. Can be switched on/off in the preferences without needing a restart. Uses the standard Java Sound API so it doesn't require an external dependency. It's non-caching and, as such, less efficient than the regular sound system, so only use it in case you have issues with the default system, otherwise leave the option unchecked.
Human vs Human play over the internet:
--------------------------------------
Some initial code has been added that will at some point in the future allow human vs human play over the internet. This is a work in progress and is far from being implemented at this time. Please be patient. Anyone who is curious can read the messages in the http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=9837 topic.
Random Deck generation:
-----------------------
Deck generation is now strictly conforming the colors chosen. You won't get any Boros Reckoner in a RG deck, that could be added before the change (because its manacost could be paid with red mana). Avacyn's Piligrim won't be added in a deck that has green but doesn't have white, though it does not consume, but produces white mana. As well there won't be added any creatures whose activated abilities require colors not choosen for a given deck. That is to say that now color identity is used for deck generation, that allows a better filtering of cards.
Single declare attackers step:
------------------------------
Combined declare attackers step for all Defending Players/Planeswalkers. On declare attackers step you have to click the entiry you are about to attack and then click on the creatures that should attack it. Clicking on a planeswalker or player visually highlights it, so that you will see whos attackers are assigned at the moment. By default your first opponent is pre-selected.
Booster slots:
--------------
Booster slots are now way more customizable. This change allows us to implement DGM boosters correctly. Note that custom cube .draft and .sealed files have changed their format. They require a booster description instead of Num(Rarity) N lines. Find example records in files describing SkieraCube and Juzamjedi cude coming with Forge. Singleton parameter is obsolette, since all cards within a booster slot are unique. Ignore rarity is also deprecated, for Booster options allow you to pick cards regardless of rarity with 'any' word standing for ignored rarity. (ex: 15 Any)
Quest challenge start in play cards:
------------------------------------
We have received reports that the quest challenge start in play cards are not appearing on the battlefield for people who were playing the classic mode rather than the fantasy mode. This should now be fixed.
Commander:
----------
We are taking baby steps toward Commander but there are some hurdles left before we get there. We need to implement the replacement effect that moves the commander back to your command zone; the cost-changing depending on how many times you've cast your commander; generating colorless mana if you try to generate mana outside your commanders color identity and AI for all the above.
Customize your Sealed Deck games with fantasy blocks:
-----------------------------------------------------
We have an informative topic at CCGH which explains how you can create "fantasy blocks" and the greatly increased flexibility you have when you are building your own blocks. Please see the topic http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=8164 for more information. Also note that the syntax was recently changed, see message http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=8164&view=unread#p117389 for additional information.
Custom Cube:
------------
1. You can create and save your cube as a constructed deck. Place the .dck file in the /res/cube directory.
2. To create a description file in the /res/draft folder you need to make a copy of any existing *.draft file and the adjust the deckfile and booster structure to meet your needs.
This file format is outdated. "NumCards" is no longer used. Instead there should be a line describing a booster.
Find some examples below:
Booster: 1 Rare, 11 Common, 3 Uncommon
Booster: 5 Common, 5 Uncommon, 5 Rare, 1 Mythic
Booster: 16 Any
Booster: 10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand
Blank screen when starting a match:
-----------------------------------
This problem should be fixed. At least you'll see an exception/crash report describing why the match didn't start instead of a blank screen.
Duplicate triggers problem solved:
----------------------------------
This problem has now been fixed. (Mana Vortex required 2 lands, Emrakul gave 2 extra turns, Empty the Warrens creatures two Storm triggers instead of one.)
Constructed mode AI vs AI matches:
----------------------------------
Added support for AI vs AI matches. There is a checkbox which allows you to view the AI vs AI match. This is a work in progress and is not finished. While it appears to work OK there is still a need for a few UI changes. Please be patient. These AI vs AI matches will not be a good way to test out various deck types against one another as the AI does not understand card combos and the AI is still limited at this time.
Constructed mode Human vs Human Hotseat matches:
------------------------------------------------
Hotseat matches are now possible. This mode has some known bugs to fix. At this time both players must use the same computer. Human vs Human matches via the internet is planned and should become available sometime in the future. Please be patient.
Using predetermined decks in quest mode Challenges:
---------------------------------------------------
Added the capability to play Challenges vs predetermined decks (along with a few other related options to disallow specific quest mode things). Added Sorin vs Tibalt, and Tibalt vs Sorin as examples of Challenges that force you to use a specific Deck. (They seemed to be the best duel deck compatibility for the AI).
Targeting Overlay:
------------------
Targeting arrows will now be shown for equipments equipping permanents currently under opponent's control (for those rare cases when e.g. an equipped creature gets Switcheroo'd for something else).
Our Lawyers Made Us Do This:
----------------------------
This product includes software developed by the Indiana University Extreme! Lab (http://www.extreme.indiana.edu/).

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.35</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

@@ -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.34-SNAPSHOT</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>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,953 @@
/*
* 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.ai;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import forge.game.CardTraitBase;
import forge.game.GameEntity;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CounterType;
import forge.game.combat.Combat;
import forge.game.combat.CombatUtil;
import forge.game.player.Player;
import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerType;
import forge.util.FCollectionView;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* <p>
* ComputerUtil_Block2 class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class AiBlockController {
private final Player ai;
/** Constant <code>attackers</code>. */
private List<Card> attackers = new ArrayList<Card>(); // all attackers
/** Constant <code>attackersLeft</code>. */
private List<Card> attackersLeft = new ArrayList<Card>(); // keeps track of
// all currently
// unblocked
// attackers
/** Constant <code>blockedButUnkilled</code>. */
private List<Card> blockedButUnkilled = new ArrayList<Card>(); // blocked
// attackers
// that
// currently
// wouldn't be
// destroyed
/** Constant <code>blockersLeft</code>. */
private List<Card> blockersLeft = new ArrayList<Card>(); // keeps track of all
// unassigned
// blockers
private int diff = 0;
private boolean lifeInDanger = false;
public AiBlockController(Player aiPlayer) {
this.ai = aiPlayer;
}
// finds the creatures able to block the attacker
private static List<Card> getPossibleBlockers(final Combat combat, final Card attacker, final List<Card> blockersLeft, final boolean solo) {
final List<Card> blockers = new ArrayList<Card>();
for (final Card blocker : blockersLeft) {
// if the blocker can block a creature with lure it can't block a
// creature without
if (CombatUtil.canBlock(attacker, blocker, combat)) {
if (solo && blocker.hasKeyword("CARDNAME can't attack or block alone.")) {
continue;
}
blockers.add(blocker);
}
}
return blockers;
}
// finds blockers that won't be destroyed
private List<Card> getSafeBlockers(final Combat combat, final Card attacker, final List<Card> blockersLeft) {
final List<Card> blockers = new ArrayList<Card>();
for (final Card b : blockersLeft) {
if (!ComputerUtilCombat.canDestroyBlocker(ai, b, attacker, combat, false)) {
blockers.add(b);
}
}
return blockers;
}
// finds blockers that destroy the attacker
private List<Card> getKillingBlockers(final Combat combat, final Card attacker, final List<Card> blockersLeft) {
final List<Card> blockers = new ArrayList<Card>();
for (final Card b : blockersLeft) {
if (ComputerUtilCombat.canDestroyAttacker(ai, attacker, b, combat, false)) {
blockers.add(b);
}
}
return blockers;
}
private static List<CardCollection> sortAttackerByDefender(final Combat combat) {
FCollectionView<GameEntity> defenders = combat.getDefenders();
final ArrayList<CardCollection> attackers = new ArrayList<CardCollection>(defenders.size());
for (GameEntity defender : defenders) {
attackers.add(combat.getAttackersOf(defender));
}
return attackers;
}
private List<Card> sortPotentialAttackers(final Combat combat) {
final List<CardCollection> attackerLists = sortAttackerByDefender(combat);
final CardCollection sortedAttackers = new CardCollection();
final CardCollection firstAttacker = attackerLists.get(0);
final FCollectionView<GameEntity> defenders = combat.getDefenders();
// Begin with the attackers that pose the biggest threat
ComputerUtilCard.sortByEvaluateCreature(firstAttacker);
CardLists.sortByPowerDesc(firstAttacker);
// If I don't have any planeswalkers than sorting doesn't really matter
if (defenders.size() == 1) {
return firstAttacker;
}
final boolean bLifeInDanger = ComputerUtilCombat.lifeInDanger(ai, combat);
// TODO Add creatures attacking Planeswalkers in order of which we want
// to protect
// defend planeswalkers with more loyalty before planeswalkers with less
// loyalty
// if planeswalker will be too difficult to defend don't even bother
for (List<Card> attacker : attackerLists) {
// Begin with the attackers that pose the biggest threat
CardLists.sortByPowerDesc(attacker);
for (final Card c : attacker) {
sortedAttackers.add(c);
}
}
if (bLifeInDanger) {
// add creatures attacking the Player to the front of the list
for (final Card c : firstAttacker) {
sortedAttackers.add(0, c);
}
} else {
// add creatures attacking the Player to the back of the list
for (final Card c : firstAttacker) {
sortedAttackers.add(c);
}
}
return sortedAttackers;
}
// ======================= block assignment functions
// ================================
// Good Blocks means a good trade or no trade
private void makeGoodBlocks(final Combat combat) {
List<Card> currentAttackers = new ArrayList<Card>(attackersLeft);
for (final Card attacker : attackersLeft) {
if (attacker.hasStartOfKeyword("CantBeBlockedByAmount LT")
|| attacker.hasKeyword("CARDNAME can't be blocked unless all creatures defending player controls block it.")) {
continue;
}
Card blocker = null;
final List<Card> blockers = getPossibleBlockers(combat, attacker, blockersLeft, true);
final List<Card> safeBlockers = getSafeBlockers(combat, attacker, blockers);
List<Card> killingBlockers;
if (!safeBlockers.isEmpty()) {
// 1.Blockers that can destroy the attacker but won't get
// destroyed
killingBlockers = getKillingBlockers(combat, attacker, safeBlockers);
if (!killingBlockers.isEmpty()) {
blocker = ComputerUtilCard.getWorstCreatureAI(killingBlockers);
} else if (!attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")) {
blocker = ComputerUtilCard.getWorstCreatureAI(safeBlockers);
if (attacker.hasKeyword("Trample")) {
boolean doNotBlock = false;
for (Card other : attackersLeft) {
if (other.equals(attacker) || !CombatUtil.canBlock(other, blocker)
|| ComputerUtilCombat.canDestroyBlocker(ai, blocker, other, combat, false)) {
continue;
}
int damageNext = other.getNetPower();
if (other.hasKeyword("Trample")) {
damageNext -= blocker.getLethalDamage();
}
if (damageNext > blocker.getLethalDamage()) {
doNotBlock = true;
break;
}
}
if (doNotBlock) {
continue;
}
}
blockedButUnkilled.add(attacker);
}
} // no safe blockers
else {
// 3.Blockers that can destroy the attacker and have an upside when dying
killingBlockers = getKillingBlockers(combat, attacker, blockers);
for (Card b : killingBlockers) {
if ((b.hasKeyword("Undying") && b.getCounters(CounterType.P1P1) == 0)
|| b.hasSVar("SacMe")
|| (b.hasStartOfKeyword("Vanishing") && b.getCounters(CounterType.TIME) == 1)
|| (b.hasStartOfKeyword("Fading") && b.getCounters(CounterType.FADE) == 0)
|| b.hasSVar("EndOfTurnLeavePlay")) {
blocker = b;
break;
}
}
// 4.Blockers that have a big upside when dying
for (Card b : blockers) {
if (b.hasSVar("SacMe") && Integer.parseInt(b.getSVar("SacMe")) > 3) {
blocker = b;
break;
}
}
// 5.Blockers that can destroy the attacker and are worth less
if (blocker == null && !killingBlockers.isEmpty()) {
final Card worst = ComputerUtilCard.getWorstCreatureAI(killingBlockers);
int value = ComputerUtilCard.evaluateCreature(attacker);
// check for triggers when unblocked
for (Trigger trigger : attacker.getTriggers()) {
final Map<String, String> trigParams = trigger.getMapParams();
TriggerType mode = trigger.getMode();
if (!trigger.requirementsCheck(attacker.getGame())) {
continue;
}
if (mode == TriggerType.DamageDone) {
if ((!trigParams.containsKey("ValidSource")
|| CardTraitBase.matchesValid(attacker, trigParams.get("ValidSource").split(","), attacker))
&& attacker.getNetCombatDamage() > 0
&& (!trigParams.containsKey("ValidTarget")
|| CardTraitBase.matchesValid(combat.getDefenderByAttacker(attacker), trigParams.get("ValidTarget").split(","), attacker))) {
value += 50;
}
} else if (mode == TriggerType.AttackerUnblocked) {
if (CardTraitBase.matchesValid(attacker, trigParams.get("ValidCard").split(","), attacker)) {
value += 50;
}
}
}
if ((ComputerUtilCard.evaluateCreature(worst) + diff) < value) {
blocker = worst;
}
}
}
if (blocker != null) {
currentAttackers.remove(attacker);
combat.addBlocker(attacker, blocker);
}
}
attackersLeft = (new ArrayList<Card>(currentAttackers));
// 6. Blockers that don't survive until the next turn anyway
for (final Card attacker : attackersLeft) {
if (attacker.hasStartOfKeyword("CantBeBlockedByAmount LT")
|| attacker.hasKeyword("CARDNAME can't be blocked unless all creatures defending player controls block it.")) {
continue;
}
Card blocker = null;
final List<Card> blockers = getPossibleBlockers(combat, attacker, blockersLeft, true);
for (Card b : blockers) {
if ((b.hasStartOfKeyword("Vanishing") && b.getCounters(CounterType.TIME) == 1)
|| (b.hasStartOfKeyword("Fading") && b.getCounters(CounterType.FADE) == 0)
|| b.hasSVar("EndOfTurnLeavePlay")) {
blocker = b;
break;
}
}
if (blocker != null) {
currentAttackers.remove(attacker);
combat.addBlocker(attacker, blocker);
}
}
attackersLeft = (new ArrayList<Card>(currentAttackers));
}
// Good Gang Blocks means a good trade or no trade
/**
* <p>
* makeGangBlocks.
* </p>
*
* @param combat
* a {@link forge.game.combat.Combat} object.
* @return a {@link forge.game.combat.Combat} object.
*/
static final Predicate<Card> rampagesOrNeedsManyToBlock = Predicates.or(CardPredicates.containsKeyword("Rampage"), CardPredicates.containsKeyword("CantBeBlockedByAmount GT"));
private void makeGangBlocks(final Combat combat) {
List<Card> currentAttackers = CardLists.filter(attackersLeft, Predicates.not(rampagesOrNeedsManyToBlock));
List<Card> blockers;
// Try to block an attacker without first strike with a gang of first strikers
for (final Card attacker : attackersLeft) {
if (!ComputerUtilCombat.dealsFirstStrikeDamage(attacker, false, combat)) {
blockers = getPossibleBlockers(combat, attacker, blockersLeft, false);
final List<Card> firstStrikeBlockers = new ArrayList<Card>();
final List<Card> blockGang = new ArrayList<Card>();
for (int i = 0; i < blockers.size(); i++) {
if (blockers.get(i).hasFirstStrike() || blockers.get(i).hasDoubleStrike()) {
firstStrikeBlockers.add(blockers.get(i));
}
}
if (firstStrikeBlockers.size() > 1) {
CardLists.sortByPowerDesc(firstStrikeBlockers);
for (final Card blocker : firstStrikeBlockers) {
final int damageNeeded = ComputerUtilCombat.getDamageToKill(attacker)
+ ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
// if the total damage of the blockgang was not enough
// without but is enough with this blocker finish the
// blockgang
if (ComputerUtilCombat.totalFirstStrikeDamageOfBlockers(attacker, blockGang) < damageNeeded
|| CombatUtil.needsBlockers(attacker) > blockGang.size()) {
blockGang.add(blocker);
if (ComputerUtilCombat.totalFirstStrikeDamageOfBlockers(attacker, blockGang) >= damageNeeded) {
currentAttackers.remove(attacker);
for (final Card b : blockGang) {
if (CombatUtil.canBlock(attacker, blocker, combat)) {
combat.addBlocker(attacker, b);
}
}
}
}
}
}
}
}
attackersLeft = (new ArrayList<Card>(currentAttackers));
currentAttackers = new ArrayList<Card>(attackersLeft);
// Try to block an attacker with two blockers of which only one will die
for (final Card attacker : attackersLeft) {
blockers = getPossibleBlockers(combat, attacker, blockersLeft, false);
List<Card> usableBlockers;
final List<Card> blockGang = new ArrayList<Card>();
int absorbedDamage = 0; // The amount of damage needed to kill the first blocker
int currentValue = 0; // The value of the creatures in the blockgang
// AI can't handle good triple blocks yet
if (CombatUtil.needsBlockers(attacker) > 2) {
continue;
}
// Try to add blockers that could be destroyed, but are worth less than the attacker
// Don't use blockers without First Strike or Double Strike if attacker has it
usableBlockers = CardLists.filter(blockers, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
if (ComputerUtilCombat.dealsFirstStrikeDamage(attacker, false, combat)
&& !ComputerUtilCombat.dealsFirstStrikeDamage(c, false, combat)) {
return false;
}
return lifeInDanger || (ComputerUtilCard.evaluateCreature(c) + diff) < ComputerUtilCard.evaluateCreature(attacker);
}
});
if (usableBlockers.size() < 2) {
return;
}
final Card leader = ComputerUtilCard.getBestCreatureAI(usableBlockers);
blockGang.add(leader);
usableBlockers.remove(leader);
absorbedDamage = ComputerUtilCombat.getEnoughDamageToKill(leader, attacker.getNetCombatDamage(), attacker, true);
currentValue = ComputerUtilCard.evaluateCreature(leader);
for (final Card blocker : usableBlockers) {
// Add an additional blocker if the current blockers are not
// enough and the new one would deal the remaining damage
final int currentDamage = ComputerUtilCombat.totalDamageOfBlockers(attacker, blockGang);
final int additionalDamage = ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker);
final int absorbedDamage2 = ComputerUtilCombat.getEnoughDamageToKill(blocker, attacker.getNetCombatDamage(), attacker, true);
final int addedValue = ComputerUtilCard.evaluateCreature(blocker);
final int damageNeeded = ComputerUtilCombat.getDamageToKill(attacker)
+ ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
if ((damageNeeded > currentDamage || CombatUtil.needsBlockers(attacker) > blockGang.size())
&& !(damageNeeded > currentDamage + additionalDamage)
// The attacker will be killed
&& (absorbedDamage2 + absorbedDamage > attacker.getNetCombatDamage()
// only one blocker can be killed
|| currentValue + addedValue - 50 <= ComputerUtilCard.evaluateCreature(attacker)
// or attacker is worth more
|| (lifeInDanger && ComputerUtilCombat.lifeInDanger(ai, combat)))
// or life is in danger
&& CombatUtil.canBlock(attacker, blocker, combat)) {
// this is needed for attackers that can't be blocked by
// more than 1
currentAttackers.remove(attacker);
combat.addBlocker(attacker, blocker);
if (CombatUtil.canBlock(attacker, leader, combat)) {
combat.addBlocker(attacker, leader);
}
break;
}
}
}
attackersLeft = (new ArrayList<Card>(currentAttackers));
}
// Bad Trade Blocks (should only be made if life is in danger)
/**
* <p>
* makeTradeBlocks.
* </p>
*
* @param combat
* a {@link forge.game.combat.Combat} object.
* @return a {@link forge.game.combat.Combat} object.
*/
private void makeTradeBlocks(final Combat combat) {
List<Card> currentAttackers = new ArrayList<Card>(attackersLeft);
List<Card> killingBlockers;
for (final Card attacker : attackersLeft) {
if (attacker.hasStartOfKeyword("CantBeBlockedByAmount LT")
|| attacker.hasKeyword("CARDNAME can't be blocked unless all creatures defending player controls block it.")) {
continue;
}
List<Card> possibleBlockers = getPossibleBlockers(combat, attacker, blockersLeft, true);
killingBlockers = getKillingBlockers(combat, attacker, possibleBlockers);
if (!killingBlockers.isEmpty() && ComputerUtilCombat.lifeInDanger(ai, combat)) {
final Card blocker = ComputerUtilCard.getWorstCreatureAI(killingBlockers);
combat.addBlocker(attacker, blocker);
currentAttackers.remove(attacker);
}
}
attackersLeft = (new ArrayList<Card>(currentAttackers));
}
// Chump Blocks (should only be made if life is in danger)
private void makeChumpBlocks(final Combat combat) {
List<Card> currentAttackers = new ArrayList<Card>(attackersLeft);
makeChumpBlocks(combat, currentAttackers);
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
makeMultiChumpBlocks(combat);
}
}
private void makeChumpBlocks(final Combat combat, List<Card> attackers) {
if (attackers.isEmpty() || !ComputerUtilCombat.lifeInDanger(ai, combat)) {
return;
}
Card attacker = attackers.get(0);
if (attacker.hasStartOfKeyword("CantBeBlockedByAmount LT") || attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")
|| attacker.hasKeyword("CARDNAME can't be blocked unless all creatures defending player controls block it.")) {
attackers.remove(0);
makeChumpBlocks(combat, attackers);
return;
}
List<Card> chumpBlockers = getPossibleBlockers(combat, attacker, blockersLeft, true);
if (!chumpBlockers.isEmpty()) {
final Card blocker = ComputerUtilCard.getWorstCreatureAI(chumpBlockers);
// check if it's better to block a creature with lower power and without trample
if (attacker.hasKeyword("Trample")) {
final int damageAbsorbed = blocker.getLethalDamage();
if (attacker.getNetCombatDamage() > damageAbsorbed) {
for (Card other : attackers) {
if (other.equals(attacker)) {
continue;
}
if (other.getNetCombatDamage() >= damageAbsorbed
&& !other.hasKeyword("Trample")
&& CombatUtil.canBlock(other, blocker, combat)) {
combat.addBlocker(other, blocker);
attackersLeft.remove(other);
blockedButUnkilled.add(other);
attackers.remove(other);
makeChumpBlocks(combat, attackers);
return;
}
}
}
}
combat.addBlocker(attacker, blocker);
attackersLeft.remove(attacker);
blockedButUnkilled.add(attacker);
}
attackers.remove(0);
makeChumpBlocks(combat, attackers);
}
// Block creatures with "can't be blocked except by two or more creatures"
private void makeMultiChumpBlocks(final Combat combat) {
List<Card> currentAttackers = new ArrayList<Card>(attackersLeft);
for (final Card attacker : currentAttackers) {
if (!attacker.hasStartOfKeyword("CantBeBlockedByAmount LT")
&& !attacker.hasKeyword("CARDNAME can't be blocked unless all creatures defending player controls block it.")) {
continue;
}
List<Card> possibleBlockers = getPossibleBlockers(combat, attacker, blockersLeft, true);
if (!CombatUtil.canAttackerBeBlockedWithAmount(attacker, possibleBlockers.size(), combat)) {
continue;
}
List<Card> usedBlockers = new ArrayList<Card>();
for (Card blocker : possibleBlockers) {
if (CombatUtil.canBlock(attacker, blocker, combat)) {
combat.addBlocker(attacker, blocker);
usedBlockers.add(blocker);
if (CombatUtil.canAttackerBeBlockedWithAmount(attacker, usedBlockers.size(), combat)) {
break;
}
}
}
if (CombatUtil.canAttackerBeBlockedWithAmount(attacker, usedBlockers.size(), combat)) {
attackersLeft.remove(attacker);
} else {
for (Card blocker : usedBlockers) {
combat.removeBlockAssignment(attacker, blocker);
}
}
}
}
/** Reinforce blockers blocking attackers with trample (should only be made if life is in danger) */
private void reinforceBlockersAgainstTrample(final Combat combat) {
List<Card> chumpBlockers;
List<Card> tramplingAttackers = CardLists.getKeyword(attackers, "Trample");
tramplingAttackers = CardLists.filter(tramplingAttackers, Predicates.not(rampagesOrNeedsManyToBlock));
// TODO - should check here for a "rampage-like" trigger that replaced
// the keyword:
// "Whenever CARDNAME becomes blocked, it gets +1/+1 until end of turn for each creature blocking it."
for (final Card attacker : tramplingAttackers) {
if ((attacker.hasStartOfKeyword("CantBeBlockedByAmount LT") && !combat.isBlocked(attacker))
|| attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")
|| attacker.hasKeyword("CARDNAME can't be blocked unless all creatures defending player controls block it.")) {
continue;
}
chumpBlockers = getPossibleBlockers(combat, attacker, blockersLeft, false);
chumpBlockers.removeAll(combat.getBlockers(attacker));
for (final Card blocker : chumpBlockers) {
// Add an additional blocker if the current blockers are not
// enough and the new one would suck some of the damage
if (ComputerUtilCombat.getAttack(attacker) > ComputerUtilCombat.totalShieldDamage(attacker, combat.getBlockers(attacker))
&& ComputerUtilCombat.shieldDamage(attacker, blocker) > 0
&& CombatUtil.canBlock(attacker, blocker, combat) && ComputerUtilCombat.lifeInDanger(ai, combat)) {
combat.addBlocker(attacker, blocker);
}
}
}
}
/** Support blockers not destroying the attacker with more blockers to try to kill the attacker */
private void reinforceBlockersToKill(final Combat combat) {
List<Card> safeBlockers;
List<Card> blockers;
List<Card> targetAttackers = CardLists.filter(blockedButUnkilled, Predicates.not(rampagesOrNeedsManyToBlock));
// TODO - should check here for a "rampage-like" trigger that replaced
// the keyword:
// "Whenever CARDNAME becomes blocked, it gets +1/+1 until end of turn for each creature blocking it."
for (final Card attacker : targetAttackers) {
blockers = getPossibleBlockers(combat, attacker, blockersLeft, false);
blockers.removeAll(combat.getBlockers(attacker));
// Try to use safe blockers first
safeBlockers = getSafeBlockers(combat, attacker, blockers);
for (final Card blocker : safeBlockers) {
final int damageNeeded = ComputerUtilCombat.getDamageToKill(attacker)
+ ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
// Add an additional blocker if the current blockers are not
// enough and the new one would deal additional damage
if ((damageNeeded > ComputerUtilCombat.totalDamageOfBlockers(attacker, combat.getBlockers(attacker)))
&& ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker) > 0
&& CombatUtil.canBlock(attacker, blocker, combat)) {
combat.addBlocker(attacker, blocker);
}
blockers.remove(blocker); // Don't check them again next
}
// Try to add blockers that could be destroyed, but are worth less
// than the attacker
// Don't use blockers without First Strike or Double Strike if
// attacker has it
if (ComputerUtilCombat.dealsFirstStrikeDamage(attacker, false, combat)) {
safeBlockers = CardLists.getKeyword(blockers, "First Strike");
safeBlockers.addAll(CardLists.getKeyword(blockers, "Double Strike"));
} else {
safeBlockers = new ArrayList<Card>(blockers);
}
for (final Card blocker : safeBlockers) {
final int damageNeeded = ComputerUtilCombat.getDamageToKill(attacker)
+ ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
// Add an additional blocker if the current blockers are not
// enough and the new one would deal the remaining damage
final int currentDamage = ComputerUtilCombat.totalDamageOfBlockers(attacker, combat.getBlockers(attacker));
final int additionalDamage = ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker);
if ((damageNeeded > currentDamage)
&& !(damageNeeded > (currentDamage + additionalDamage))
&& ((ComputerUtilCard.evaluateCreature(blocker) + diff) < ComputerUtilCard
.evaluateCreature(attacker)) && CombatUtil.canBlock(attacker, blocker, combat)) {
combat.addBlocker(attacker, blocker);
blockersLeft.remove(blocker);
}
}
}
}
private void clearBlockers(final Combat combat, final List<Card> possibleBlockers) {
final List<Card> oldBlockers = combat.getAllBlockers();
for (final Card blocker : oldBlockers) {
if ( blocker.getController() == ai ) // don't touch other player's blockers
combat.removeFromCombat(blocker);
}
attackersLeft = new ArrayList<Card>(attackers); // keeps track of all currently unblocked attackers
blockersLeft = new ArrayList<Card>(possibleBlockers); // keeps track of all unassigned blockers
blockedButUnkilled = new ArrayList<Card>(); // keeps track of all blocked attackers that currently wouldn't be destroyed
}
/** Assigns blockers for the provided combat instance (in favor of player passes to ctor) */
public void assignBlockersForCombat(final Combat combat) {
List<Card> possibleBlockers = ai.getCreaturesInPlay();
attackers = sortPotentialAttackers(combat);
assignBlockers(combat, possibleBlockers);
}
/**
* assignBlockersForCombat() with additional and possibly "virtual" blockers.
* @param combat combat instance
* @param blockers blockers to add in addition to creatures already in play
*/
public void assignAdditionalBlockers(final Combat combat, CardCollectionView blockers) {
List<Card> possibleBlockers = ai.getCreaturesInPlay();
for (Card c : blockers) {
if (!possibleBlockers.contains(c)) {
possibleBlockers.add(c);
}
}
attackers = sortPotentialAttackers(combat);
assignBlockers(combat, possibleBlockers);
}
/**
* assignBlockersForCombat() with specific and possibly "virtual" attackers. No other creatures, even if
* they have already been declared in the combat instance, will be considered.
* @param combat combat instance
* @param givenAttackers specific attackers to consider
*/
public void assignBlockersGivenAttackers(final Combat combat, List<Card> givenAttackers) {
List<Card> possibleBlockers = ai.getCreaturesInPlay();
attackers = givenAttackers;
assignBlockers(combat, possibleBlockers);
}
/**
* Core blocker assignment algorithm.
* @param combat combat instance
* @param possibleBlockers list of blockers to be considered
*/
private void assignBlockers(final Combat combat, List<Card> possibleBlockers) {
if (attackers.isEmpty()) {
return;
}
clearBlockers(combat, possibleBlockers);
List<Card> blockers;
List<Card> chumpBlockers;
diff = (ai.getLife() * 2) - 5; // This is the minimal gain for an unnecessary trade
// remove all attackers that can't be blocked anyway
for (final Card a : attackers) {
if (!CombatUtil.canBeBlocked(a, ai)) {
attackersLeft.remove(a);
}
}
// remove all blockers that can't block anyway
for (final Card b : possibleBlockers) {
if (!CombatUtil.canBlock(b, combat)) {
blockersLeft.remove(b);
}
}
if (attackersLeft.isEmpty()) {
return;
}
// Begin with the weakest blockers
CardLists.sortByPowerAsc(blockersLeft);
// == 1. choose best blocks first ==
makeGoodBlocks(combat);
makeGangBlocks(combat);
// When the AI holds some Fog effect, don't bother about lifeInDanger
if (!ComputerUtil.hasAFogEffect(ai)) {
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
makeTradeBlocks(combat); // choose necessary trade blocks
}
// if life is in danger
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
makeChumpBlocks(combat); // choose necessary chump blocks
}
// if life is still in danger
// Reinforce blockers blocking attackers with trample if life is still
// in danger
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
reinforceBlockersAgainstTrample(combat);
}
// Support blockers not destroying the attacker with more blockers to
// try to kill the attacker
if (!ComputerUtilCombat.lifeInDanger(ai, combat)) {
reinforceBlockersToKill(combat);
}
// == 2. If the AI life would still be in danger make a safer approach ==
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
lifeInDanger = true;
clearBlockers(combat, possibleBlockers); // reset every block assignment
makeTradeBlocks(combat); // choose necessary trade blocks
// if life is in danger
makeGoodBlocks(combat);
// choose necessary chump blocks if life is still in danger
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
makeChumpBlocks(combat);
}
// Reinforce blockers blocking attackers with trample if life is
// still in danger
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
reinforceBlockersAgainstTrample(combat);
}
makeGangBlocks(combat);
reinforceBlockersToKill(combat);
}
// == 3. If the AI life would be in serious danger make an even safer approach ==
if (lifeInDanger && ComputerUtilCombat.lifeInSeriousDanger(ai, combat)) {
clearBlockers(combat, possibleBlockers); // reset every block assignment
makeChumpBlocks(combat); // choose chump blocks
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
makeTradeBlocks(combat); // choose necessary trade
}
if (!ComputerUtilCombat.lifeInDanger(ai, combat)) {
makeGoodBlocks(combat);
}
// Reinforce blockers blocking attackers with trample if life is
// still in danger
else {
reinforceBlockersAgainstTrample(combat);
}
makeGangBlocks(combat);
// Support blockers not destroying the attacker with more blockers
// to try to kill the attacker
reinforceBlockersToKill(combat);
}
}
// assign blockers that have to block
chumpBlockers = CardLists.getKeyword(blockersLeft, "CARDNAME blocks each turn if able.");
// if an attacker with lure attacks - all that can block
for (final Card blocker : blockersLeft) {
if (CombatUtil.mustBlockAnAttacker(blocker, combat)) {
chumpBlockers.add(blocker);
}
}
if (!chumpBlockers.isEmpty()) {
CardLists.shuffle(attackers);
for (final Card attacker : attackers) {
blockers = getPossibleBlockers(combat, attacker, chumpBlockers, false);
for (final Card blocker : blockers) {
if (CombatUtil.canBlock(attacker, blocker, combat) && blockersLeft.contains(blocker)
&& (CombatUtil.mustBlockAnAttacker(blocker, combat)
|| blocker.hasKeyword("CARDNAME blocks each turn if able."))) {
combat.addBlocker(attacker, blocker);
if (blocker.getMustBlockCards() != null) {
int mustBlockAmt = blocker.getMustBlockCards().size();
final CardCollectionView blockedSoFar = combat.getAttackersBlockedBy(blocker);
boolean canBlockAnother = CombatUtil.canBlockMoreCreatures(blocker, blockedSoFar);
if (!canBlockAnother || mustBlockAmt == blockedSoFar.size()) {
blockersLeft.remove(blocker);
}
} else {
blockersLeft.remove(blocker);
}
}
}
}
}
//Check for validity of blocks in case something slipped through
for (Card attacker : attackers) {
if (!CombatUtil.canAttackerBeBlockedWithAmount(attacker, combat.getBlockers(attacker).size(), combat)) {
for (final Card blocker : combat.getBlockers(attacker)) {
if ( blocker.getController() == ai ) // don't touch other player's blockers
combat.removeFromCombat(blocker);
}
}
}
}
public static CardCollection orderBlockers(Card attacker, CardCollection blockers) {
// ordering of blockers, sort by evaluate, then try to kill the best
int damage = attacker.getNetCombatDamage();
ComputerUtilCard.sortByEvaluateCreature(blockers);
final CardCollection first = new CardCollection();
final CardCollection last = new CardCollection();
for (Card blocker : blockers) {
int lethal = ComputerUtilCombat.getEnoughDamageToKill(blocker, damage, attacker, true);
if (lethal > damage) {
last.add(blocker);
} else {
first.add(blocker);
damage -= lethal;
}
}
first.addAll(last);
// TODO: Take total damage, and attempt to maximize killing the greatest evaluation of creatures
// It's probably generally better to kill the largest creature, but sometimes its better to kill a few smaller ones
return first;
}
/**
* Orders a blocker that put onto the battlefield blocking. Depends heavily
* on the implementation of orderBlockers().
*/
public static CardCollection orderBlocker(final Card attacker, final Card blocker, final CardCollection oldBlockers) {
// add blocker to existing ordering
// sort by evaluate, then insert it appropriately
// relies on current implementation of orderBlockers()
final CardCollection allBlockers = new CardCollection(oldBlockers);
allBlockers.add(blocker);
ComputerUtilCard.sortByEvaluateCreature(allBlockers);
final int newBlockerIndex = allBlockers.indexOf(blocker);
int damage = attacker.getNetCombatDamage();
final CardCollection result = new CardCollection();
boolean newBlockerIsAdded = false;
// The new blocker comes right after this one
final Card newBlockerRightAfter = (newBlockerIndex == 0 ? null : allBlockers.get(newBlockerIndex - 1));
if (newBlockerRightAfter == null && damage >= ComputerUtilCombat.getEnoughDamageToKill(blocker, damage, attacker, true)) {
result.add(blocker);
newBlockerIsAdded = true;
}
// Don't bother to keep damage up-to-date after the new blocker is added, as we can't modify the order of the other cards anyway
for (final Card c : oldBlockers) {
final int lethal = ComputerUtilCombat.getEnoughDamageToKill(c, damage, attacker, true);
damage -= lethal;
result.add(c);
if (!newBlockerIsAdded && c == newBlockerRightAfter && damage <= ComputerUtilCombat.getEnoughDamageToKill(blocker, damage, attacker, true)) {
// If blocker is right after this card in priority and we have sufficient damage to kill it, add it here
result.add(blocker);
newBlockerIsAdded = true;
}
}
// We don't have sufficient damage, just add it at the end!
if (!newBlockerIsAdded) {
result.add(blocker);
}
return result;
}
public static CardCollection orderAttackers(Card blocker, CardCollection attackers) {
// This shouldn't really take trample into account, but otherwise should be pretty similar to orderBlockers
// ordering of blockers, sort by evaluate, then try to kill the best
int damage = blocker.getNetCombatDamage();
ComputerUtilCard.sortByEvaluateCreature(attackers);
final CardCollection first = new CardCollection();
final CardCollection last = new CardCollection();
for (Card attacker : attackers) {
int lethal = ComputerUtilCombat.getEnoughDamageToKill(attacker, damage, blocker, true);
if (lethal > damage) {
last.add(attacker);
} else {
first.add(attacker);
damage -= lethal;
}
}
first.addAll(last);
// TODO: Take total damage, and attempt to maximize killing the greatest evaluation of creatures
// It's probably generally better to kill the largest creature, but sometimes its better to kill a few smaller ones
return first;
}
}

View File

@@ -0,0 +1,240 @@
/*
* 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.ai;
import forge.game.card.Card;
import forge.game.player.Player;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* <p>
* AiCardMemory class.
* </p>
*
* A simple class that allows the AI to "memorize" different cards on the battlefield (and possibly in other zones
* too, for instance as revealed from the opponent's hand) and assign them to different memory sets in order to help
* make somewhat more "educated" decisions to attack with certain cards or play certain spell abilities. Each
* AiController has its own memory that is created when the AI player is spawned. The card memory is accessible
* via AiController.getCardMemory.
*
* @author Forge
*/
public class AiCardMemory {
private HashSet<Card> memMandatoryAttackers = new HashSet<Card>();
private HashSet<Card> memHeldManaSources = new HashSet<Card>();
private HashSet<Card> memAttachedThisTurn = new HashSet<Card>();
//private HashSet<Card> memRevealedCards = new HashSet<Card>();
/**
* Defines the memory set in which the card is remembered
* (which, in its turn, defines how the AI utilizes the information
* about remembered cards).
*/
public enum MemorySet {
MANDATORY_ATTACKERS,
HELD_MANA_SOURCES,
ATTACHED_THIS_TURN,
//REVEALED_CARDS // stub, not linked to AI code yet
}
private Set<Card> getMemorySet(MemorySet set) {
switch (set) {
case MANDATORY_ATTACKERS:
return memMandatoryAttackers;
case HELD_MANA_SOURCES:
return memHeldManaSources;
case ATTACHED_THIS_TURN:
return memAttachedThisTurn;
//case REVEALED_CARDS:
// return memRevealedCards;
default:
return null;
}
}
/**
* Checks if the given card was remembered in the given memory set.
*
* @param c
* the card
* @param set the memory set that is to be checked
* @return true, if the card is remembered in the given memory set
*/
public boolean isRememberedCard(Card c, MemorySet set) {
if (c == null) {
return false;
}
Set<Card> memorySet = getMemorySet(set);
return memorySet == null ? false : memorySet.contains(c);
}
/**
* Checks if at least one card of the given name was remembered in the given memory set.
*
* @param cardName
* the card name
* @param set the memory set that is to be checked
* @return true, if at least one card with the given name is remembered in the given memory set
*/
public boolean isRememberedCardByName(String cardName, MemorySet set) {
Set<Card> memorySet = getMemorySet(set);
Iterator<Card> it = memorySet.iterator();
while (it.hasNext()) {
Card c = it.next();
if (c.getName().equals(cardName)) {
return true;
}
}
return false;
}
/**
* Checks if at least one card of the given name was remembered in the given memory set such
* that its owner is the given player.
*
* @param cardName
* the card name
* @param set the memory set that is to be checked
* @param owner the owner of the card
* @return true, if at least one card with the given name is remembered in the given memory set
*/
public boolean isRememberedCardByName(String cardName, MemorySet set, Player owner) {
Set<Card> memorySet = getMemorySet(set);
Iterator<Card> it = memorySet.iterator();
while (it.hasNext()) {
Card c = it.next();
if (c.getName().equals(cardName) && c.getOwner().equals(owner)) {
return true;
}
}
return false;
}
/**
* Remembers the given card in the given memory set.
* @param c
* the card
* @param set the memory set to remember the card in
* @return true, if the card is successfully stored in the given memory set
*/
public boolean rememberCard(Card c, MemorySet set) {
if (c == null)
return false;
getMemorySet(set).add(c);
return true;
}
/**
* Forgets the given card in the given memory set.
* @param c
* the card
* @param set the memory set to forget the card in
* @return true, if the card was previously remembered in the given memory set and was successfully forgotten
*/
public boolean forgetCard(Card c, MemorySet set) {
if (c == null) {
return false;
}
if (!isRememberedCard(c, set)) {
return false;
}
getMemorySet(set).remove(c);
return true;
}
/**
* Forgets a single card with the given name in the given memory set.
* @param cardName
* the card name
* @param set the memory set to forget the card in
* @return true, if at least one card with the given name was previously remembered in the given memory set and was successfully forgotten
*/
public boolean forgetAnyCardWithName(String cardName, MemorySet set) {
Set<Card> memorySet = getMemorySet(set);
Iterator<Card> it = memorySet.iterator();
while (it.hasNext()) {
Card c = it.next();
if (c.getName().equals(cardName)) {
return forgetCard(c, set);
}
}
return false;
}
/**
* Forgets a single card with the given name owned by the given player in the given memory set.
* @param cardName
* the card name
* @param set the memory set to forget the card in
* @param owner the owner of the card
* @return true, if at least one card with the given name was previously remembered in the given memory set and was successfully forgotten
*/
public boolean forgetAnyCardWithName(String cardName, MemorySet set, Player owner) {
Set<Card> memorySet = getMemorySet(set);
Iterator<Card> it = memorySet.iterator();
while (it.hasNext()) {
Card c = it.next();
if (c.getName().equals(cardName) && c.getOwner().equals(owner)) {
return forgetCard(c, set);
}
}
return false;
}
/**
* Determines if the memory set is empty.
* @param set the memory set to inspect.
* @return true, if the given memory set contains no remembered cards.
*/
public boolean isMemorySetEmpty(MemorySet set) {
return getMemorySet(set).isEmpty();
}
/**
* Clears the given memory set.
*/
public void clearMemorySet(MemorySet set) {
getMemorySet(set).clear();
}
/**
* Clears all memory sets stored in this card memory for the given player.
*/
public void clearAllRemembered() {
clearMemorySet(MemorySet.MANDATORY_ATTACKERS);
clearMemorySet(MemorySet.HELD_MANA_SOURCES);
clearMemorySet(MemorySet.ATTACHED_THIS_TURN);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,609 @@
package forge.ai;
import com.google.common.base.Predicate;
import forge.card.CardType;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CardPredicates.Presets;
import forge.game.card.CounterType;
import forge.game.cost.*;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance;
import forge.game.zone.ZoneType;
import forge.util.FCollectionView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class AiCostDecision extends CostDecisionMakerBase {
private final SpellAbility ability;
private final Card source;
public AiCostDecision(Player ai0, SpellAbility sa) {
super(ai0);
ability = sa;
source = ability.getHostCard();
}
@Override
public PaymentDecision visit(CostAddMana cost) {
Integer c = cost.convertAmount();
if (c == null) {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
return PaymentDecision.number(c);
}
@Override
public PaymentDecision visit(CostChooseCreatureType cost) {
String choice = player.getController().chooseSomeType("Creature", ability, new ArrayList<String>(CardType.Constant.CREATURE_TYPES), new ArrayList<String>());
return PaymentDecision.type(choice);
}
@Override
public PaymentDecision visit(CostDiscard cost) {
final String type = cost.getType();
final CardCollectionView hand = player.getCardsIn(ZoneType.Hand);
if (type.equals("LastDrawn")) {
if (!hand.contains(player.getLastDrawnCard())) {
return null;
}
return PaymentDecision.card(player.getLastDrawnCard());
}
else if (cost.payCostFromSource()) {
if (!hand.contains(source)) {
return null;
}
return PaymentDecision.card(source);
}
else if (type.equals("Hand")) {
return PaymentDecision.card(hand);
}
if (type.contains("WithSameName")) {
return null;
}
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
if (sVar.equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
if (type.equals("Random")) {
return PaymentDecision.card(CardLists.getRandomSubList(new CardCollection(hand), c));
}
else {
final AiController aic = ((PlayerControllerAi)player.getController()).getAi();
return PaymentDecision.card(aic.getCardsToDiscard(c, type.split(";"), ability));
}
}
@Override
public PaymentDecision visit(CostDamage cost) {
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null; // cannot pay
} else {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
}
return PaymentDecision.number(c);
}
@Override
public PaymentDecision visit(CostDraw cost) {
Integer c = cost.convertAmount();
if (c == null) {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
return PaymentDecision.number(c);
}
@Override
public PaymentDecision visit(CostExile cost) {
if (cost.payCostFromSource()) {
return PaymentDecision.card(source);
}
if (cost.getType().equals("All")) {
return PaymentDecision.card(player.getCardsIn(cost.getFrom()));
}
else if (cost.getType().contains("FromTopGrave")) {
return null;
}
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
if (cost.getFrom().equals(ZoneType.Library)) {
return PaymentDecision.card(player.getCardsIn(ZoneType.Library, c));
}
else if (cost.sameZone) {
// TODO Determine exile from same zone for AI
return null;
}
else {
CardCollectionView chosen = ComputerUtil.chooseExileFrom(player, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c);
return null == chosen ? null : PaymentDecision.card(chosen);
}
}
@Override
public PaymentDecision visit(CostExileFromStack cost) {
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
List<SpellAbility> chosen = new ArrayList<SpellAbility>();
for (SpellAbilityStackInstance si :source.getGame().getStack()) {
SpellAbility sp = si.getSpellAbility(true).getRootAbility();
if (si.getSourceCard().isValid(cost.getType().split(";"), source.getController(), source)) {
chosen.add(sp);
}
}
return chosen.isEmpty() ? null : PaymentDecision.spellabilities(chosen);
}
@Override
public PaymentDecision visit(CostExiledMoveToGrave cost) {
Integer c = cost.convertAmount();
CardCollection chosen = new CardCollection();
if (c == null) {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
CardCollection typeList = CardLists.getValidCards(player.getGame().getCardsIn(ZoneType.Exile), cost.getType().split(";"), player, source);
if (typeList.size() < c) {
return null;
}
CardLists.sortByPowerAsc(typeList);
Collections.reverse(typeList);
for (int i = 0; i < c; i++) {
chosen.add(typeList.get(i));
}
return chosen.isEmpty() ? null : PaymentDecision.card(chosen);
}
@Override
public PaymentDecision visit(CostFlipCoin cost) {
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
return PaymentDecision.number(c);
}
@Override
public PaymentDecision visit(CostGainControl cost) {
if (cost.payCostFromSource()) {
return PaymentDecision.card(source);
}
Integer c = cost.convertAmount();
if (c == null) {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
final CardCollection typeList = CardLists.getValidCards(player.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), player, source);
if (typeList.size() < c) {
return null;
}
CardLists.sortByPowerAsc(typeList);
final CardCollection res = new CardCollection();
for (int i = 0; i < c; i++) {
res.add(typeList.get(i));
}
return res.isEmpty() ? null : PaymentDecision.card(res);
}
@Override
public PaymentDecision visit(CostGainLife cost) {
final List<Player> oppsThatCanGainLife = new ArrayList<Player>();
for (final Player opp : cost.getPotentialTargets(player, source)) {
if (opp.canGainLife()) {
oppsThatCanGainLife.add(opp);
}
}
if (oppsThatCanGainLife.size() == 0) {
return null;
}
return PaymentDecision.players(oppsThatCanGainLife);
}
@Override
public PaymentDecision visit(CostMill cost) {
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
CardCollectionView topLib = player.getCardsIn(ZoneType.Library, c);
return topLib.size() < c ? null : PaymentDecision.card(topLib);
}
@Override
public PaymentDecision visit(CostPartMana cost) {
return PaymentDecision.number(0);
}
@Override
public PaymentDecision visit(CostPayLife cost) {
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null;
} else {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
}
if (!player.canPayLife(c)) {
return null;
}
// activator.payLife(c, null);
return PaymentDecision.number(c);
}
@Override
public PaymentDecision visit(CostPutCardToLib cost) {
Integer c = cost.convertAmount();
final Game game = player.getGame();
CardCollection chosen = new CardCollection();
CardCollectionView list;
if (cost.isSameZone()) {
list = new CardCollection(game.getCardsIn(cost.getFrom()));
}
else {
list = new CardCollection(player.getCardsIn(cost.getFrom()));
}
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
// Generalize cost
if (sVar.equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
list = CardLists.getValidCards(list, cost.getType().split(";"), player, source);
if (cost.isSameZone()) {
// Jotun Grunt
// TODO: improve AI
final FCollectionView<Player> players = game.getPlayers();
for (Player p : players) {
CardCollectionView enoughType = CardLists.filter(list, CardPredicates.isOwner(p));
if (enoughType.size() >= c) {
chosen.addAll(enoughType);
break;
}
}
chosen = chosen.subList(0, c);
}
else {
chosen = ComputerUtil.choosePutToLibraryFrom(player, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c);
}
return chosen.isEmpty() ? null : PaymentDecision.card(chosen);
}
@Override
public PaymentDecision visit(CostPutCounter cost) {
if (cost.payCostFromSource()) {
return PaymentDecision.card(source);
}
final CardCollection typeList = CardLists.getValidCards(player.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), player, source);
Card card;
if (cost.getType().equals("Creature.YouCtrl")) {
card = ComputerUtilCard.getWorstCreatureAI(typeList);
}
else {
card = ComputerUtilCard.getWorstPermanentAI(typeList, false, false, false, false);
}
return PaymentDecision.card(card);
}
@Override
public PaymentDecision visit(CostTap cost) {
return PaymentDecision.number(0);
}
@Override
public PaymentDecision visit(CostTapType cost) {
final String amount = cost.getAmount();
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(amount);
if (sVar.equals("XChoice")) {
CardCollectionView typeList =
CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), ability.getActivatingPlayer(), ability.getHostCard());
typeList = CardLists.filter(typeList, Presets.UNTAPPED);
c = typeList.size();
source.setSVar("ChosenX", "Number$" + Integer.toString(c));
} else {
c = AbilityUtils.calculateAmount(source, amount, ability);
}
}
if (cost.getType().contains("sharesCreatureTypeWith") || cost.getType().contains("withTotalPowerGE")) {
return null;
}
CardCollectionView totap = ComputerUtil.chooseTapType(player, cost.getType(), source, !cost.canTapSource, c);
if (totap == null) {
System.out.println("Couldn't find a valid card to tap for: " + source.getName());
return null;
}
return PaymentDecision.card(totap);
}
@Override
public PaymentDecision visit(CostSacrifice cost) {
if (cost.payCostFromSource()) {
return PaymentDecision.card(source);
}
if (cost.getAmount().equals("All")) {
/*CardCollectionView typeList = new CardCollection(activator.getCardsIn(ZoneType.Battlefield));
typeList = CardLists.getValidCards(typeList, cost.getType().split(";"), activator, source);
if (activator.hasKeyword("You can't sacrifice creatures to cast spells or activate abilities.")) {
typeList = CardLists.getNotType(typeList, "Creature");
}*/
// Does the AI want to use Sacrifice All?
return null;
}
Integer c = cost.convertAmount();
if (c == null) {
if (ability.getSVar(cost.getAmount()).equals("XChoice")) {
return null;
}
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
CardCollectionView list = ComputerUtil.chooseSacrificeType(player, cost.getType(), source, ability.getTargetCard(), c);
return PaymentDecision.card(list);
}
@Override
public PaymentDecision visit(CostReturn cost) {
if (cost.payCostFromSource())
return PaymentDecision.card(source);
Integer c = cost.convertAmount();
if (c == null) {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
CardCollectionView res = ComputerUtil.chooseReturnType(player, cost.getType(), source, ability.getTargetCard(), c);
return res.isEmpty() ? null : PaymentDecision.card(res);
}
@Override
public PaymentDecision visit(CostReveal cost) {
final String type = cost.getType();
CardCollectionView hand = player.getCardsIn(ZoneType.Hand);
if (cost.payCostFromSource()) {
if (!hand.contains(source)) {
return null;
}
return PaymentDecision.card(source);
}
if (cost.getType().equals("Hand")) {
return PaymentDecision.card(hand);
}
if (cost.getType().equals("SameColor")) {
return null;
}
hand = CardLists.getValidCards(hand, type.split(";"), player, source);
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(cost.getAmount());
if (sVar.equals("XChoice")) {
c = hand.size();
} else {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
}
}
final AiController aic = ((PlayerControllerAi)player.getController()).getAi();
return PaymentDecision.card(aic.getCardsToDiscard(c, type.split(";"), ability));
}
@Override
public PaymentDecision visit(CostRemoveAnyCounter cost) {
final String amount = cost.getAmount();
final int c = AbilityUtils.calculateAmount(source, amount, ability);
final String type = cost.getType();
CardCollectionView typeList = CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), type.split(";"), player, source);
CardCollectionView hperms = CardLists.filter(typeList, new Predicate<Card>() {
@Override
public boolean apply(final Card crd) {
for (final CounterType c1 : CounterType.values()) {
if (crd.getCounters(c1) >= c && ComputerUtil.isNegativeCounter(c1, crd)) {
return true;
}
}
return false;
}
});
if(hperms.isEmpty())
return null;
PaymentDecision result = PaymentDecision.card(hperms);
Card valid = hperms.get(0);
for (CounterType c1 : valid.getCounters().keySet()) {
if (valid.getCounters(c1) >= c && ComputerUtil.isNegativeCounter(c1, valid)) {
result.ct = c1;
break;
}
}
// Only find cards with enough negative counters
// TODO: add ai for Chisei, Heart of Oceans
return result;
}
@Override
public PaymentDecision visit(CostRemoveCounter cost) {
final String amount = cost.getAmount();
Integer c = cost.convertAmount();
final String type = cost.getType();
if (c == null) {
final String sVar = ability.getSVar(amount);
if (sVar.equals("XChoice")) {
c = AbilityUtils.calculateAmount(source, "ChosenX", ability);
} else if (amount.equals("All")) {
c = source.getCounters(cost.counter);
} else {
c = AbilityUtils.calculateAmount(source, amount, ability);
}
}
if (!cost.payCostFromSource()) {
CardCollectionView typeList;
if (type.equals("OriginalHost")) {
typeList = new CardCollection(ability.getOriginalHost());
} else {
typeList = CardLists.getValidCards(player.getCardsIn(cost.zone), type.split(";"), player, source);
}
for (Card card : typeList) {
if (card.getCounters(cost.counter) >= c) {
return PaymentDecision.card(card, c);
}
}
return null;
}
if (c > source.getCounters(cost.counter)) {
System.out.println("Not enough " + cost.counter + " on " + source.getName());
return null;
}
return PaymentDecision.card(source, c);
}
@Override
public PaymentDecision visit(CostUntapType cost) {
final String amount = cost.getAmount();
Integer c = cost.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(amount);
if (sVar.equals("XChoice")) {
CardCollection typeList = CardLists.getValidCards(player.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), player, ability.getHostCard());
if (!cost.canUntapSource) {
typeList.remove(source);
}
typeList = CardLists.filter(typeList, Presets.TAPPED);
c = typeList.size();
source.setSVar("ChosenX", "Number$" + Integer.toString(c));
} else {
c = AbilityUtils.calculateAmount(source, amount, ability);
}
}
CardCollectionView list = ComputerUtil.chooseUntapType(player, cost.getType(), source, cost.canUntapSource, c);
if (list == null) {
System.out.println("Couldn't find a valid card to untap for: " + source.getName());
return null;
}
return PaymentDecision.card(list);
}
@Override
public PaymentDecision visit(CostUntap cost) {
return PaymentDecision.number(0);
}
@Override
public PaymentDecision visit(CostUnattach cost) {
final Card cardToUnattach = cost.findCardToUnattach(source, player, ability);
if (cardToUnattach == null) {
// We really shouldn't be able to get here if there's nothing to unattach
return null;
}
return PaymentDecision.card(cardToUnattach);
}
@Override
public boolean paysRightAfterDecision() {
return false;
}
}

View File

@@ -0,0 +1,21 @@
package forge.ai;
public enum AiPlayDecision {
WillPlay,
CantPlaySa,
CantPlayAi,
CantAfford,
CantAffordX,
WaitForMain2,
AnotherTime,
MissingNeededCards,
NeedsToPlayCriteriaNotMet,
TargetingFailed,
CostNotAcceptable,
WouldDestroyLegend,
WouldDestroyOtherPlaneswalker,
WouldBecomeZeroToughnessCreature,
WouldDestroyWorldEnchantment,
BadEtbEffects,
CurseEffects;
}

View File

@@ -1,187 +1,194 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2013 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.game.ai;
import forge.game.player.LobbyPlayer;
import forge.game.player.LobbyPlayerAi;
import forge.util.Aggregates;
import forge.util.FileUtil;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
/**
* Holds default AI personality profile values in an enum.
* Loads profile from the given text file when setProfile is called.
* If a requested value is not loaded from a profile, default is returned.
*
* @author Forge
* @version $Id: AIProfile.java 20169 2013-03-08 08:24:17Z Agetian $
*/
public class AiProfileUtil {
private static Map<String, Map<AiProps, String>> loadedProfiles = new HashMap<String, Map<AiProps, String>>();
private static final String AI_PROFILE_DIR = "res/ai";
private static final String AI_PROFILE_EXT = ".ai";
public static final String AI_PROFILE_RANDOM_MATCH = "* Random (Match) *";
public static final String AI_PROFILE_RANDOM_DUEL = "* Random (Duel) *";
/** Builds an AI profile file name with full relative
* path based on the profile name.
* @param profileName the name of the profile.
* @return the full relative path and file name for the given profile.
*/
private static String buildFileName(final String profileName) {
return String.format("%s/%s%s", AI_PROFILE_DIR, profileName, AI_PROFILE_EXT);
}
/**
* Load all profiles
*/
public static final void loadAllProfiles() {
loadedProfiles.clear();
ArrayList<String> availableProfiles = getAvailableProfiles();
for (String profile : availableProfiles) {
loadedProfiles.put(profile, loadProfile(profile));
}
}
/**
* Load a single profile.
* @param profileName a profile to load.
*/
private static final Map<AiProps, String> loadProfile(final String profileName) {
Map<AiProps, String> profileMap = new HashMap<AiProps, String>();
List<String> lines = FileUtil.readFile(buildFileName(profileName));
for (String line : lines) {
if (line.startsWith("#") || (line.length() == 0)) {
continue;
}
final String[] split = line.split("=");
if (split.length == 2) {
profileMap.put(AiProps.valueOf(split[0]), split[1]);
} else if (split.length == 1 && line.endsWith("=")) {
profileMap.put(AiProps.valueOf(split[0]), "");
}
}
return profileMap;
}
/**
* Returns an AI property value for the current profile.
*
* @param fp0 an AI property.
* @return String
*/
public static String getAIProp(final LobbyPlayer p, final AiProps fp0) {
String val = null;
if (!(p instanceof LobbyPlayerAi))
return "";
String profile = ((LobbyPlayerAi) p).getAiProfile();
if (loadedProfiles.get(profile) != null) {
val = loadedProfiles.get(profile).get(fp0);
}
if (val == null) { val = fp0.getDefault(); }
return val;
}
/**
* Returns an array of strings containing all available profiles.
* @return ArrayList<String> - an array of strings containing all
* available profiles.
*/
public static ArrayList<String> getAvailableProfiles()
{
final ArrayList<String> availableProfiles = new ArrayList<String>();
final File dir = new File(AI_PROFILE_DIR);
final String[] children = dir.list();
if (children == null) {
System.err.println("AIProfile > can't find AI profile directory!");
} else {
for (int i = 0; i < children.length; i++) {
if (children[i].endsWith(AI_PROFILE_EXT)) {
availableProfiles.add(children[i].substring(0, children[i].length() - AI_PROFILE_EXT.length()));
}
}
}
return availableProfiles;
}
/**
* Returns an array of strings containing all available profiles including
* the special "Random" profiles.
* @return ArrayList<String> - an array list of strings containing all
* available profiles including special random profile tags.
*/
public static ArrayList<String> getProfilesDisplayList() {
final ArrayList<String> availableProfiles = new ArrayList<String>();
availableProfiles.add(AI_PROFILE_RANDOM_MATCH);
availableProfiles.add(AI_PROFILE_RANDOM_DUEL);
availableProfiles.addAll(getAvailableProfiles());
return availableProfiles;
}
/**
* Returns a random personality from the currently available ones.
* @return String - a string containing a random profile from all the
* currently available ones.
*/
public static String getRandomProfile() {
return Aggregates.random(getAvailableProfiles());
}
/**
* Simple class test facility for AiProfileUtil.
*-/
public static void selfTest() {
final LobbyPlayer activePlayer = Singletons.getControl().getPlayer().getLobbyPlayer();
System.out.println(String.format("Current profile = %s", activePlayer.getAiProfile()));
ArrayList<String> profiles = getAvailableProfiles();
System.out.println(String.format("Available profiles: %s", profiles));
if (profiles.size() > 0) {
System.out.println(String.format("Loading all profiles..."));
loadAllProfiles();
System.out.println(String.format("Setting profile %s...", profiles.get(0)));
activePlayer.setAiProfile(profiles.get(0));
for (AiProps property : AiProps.values()) {
System.out.println(String.format("%s = %s", property, getAIProp(activePlayer, property)));
}
String randomProfile = getRandomProfile();
System.out.println(String.format("Loading random profile %s...", randomProfile));
activePlayer.setAiProfile(randomProfile);
for (AiProps property : AiProps.values()) {
System.out.println(String.format("%s = %s", property, getAIProp(activePlayer, property)));
}
}
}
*/
}
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2013 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.ai;
import forge.LobbyPlayer;
import forge.util.Aggregates;
import forge.util.FileUtil;
import org.apache.commons.lang3.ArrayUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Holds default AI personality profile values in an enum.
* Loads profile from the given text file when setProfile is called.
* If a requested value is not loaded from a profile, default is returned.
*
* @author Forge
* @version $Id: AIProfile.java 20169 2013-03-08 08:24:17Z Agetian $
*/
public class AiProfileUtil {
private static Map<String, Map<AiProps, String>> loadedProfiles = new HashMap<String, Map<AiProps, String>>();
private static String AI_PROFILE_DIR;
private static final String AI_PROFILE_EXT = ".ai";
public static final String AI_PROFILE_RANDOM_MATCH = "* Random (Match) *";
public static final String AI_PROFILE_RANDOM_DUEL = "* Random (Duel) *";
/** Builds an AI profile file name with full relative
* path based on the profile name.
* @param profileName the name of the profile.
* @return the full relative path and file name for the given profile.
*/
private static String buildFileName(final String profileName) {
return String.format("%s/%s%s", AI_PROFILE_DIR, profileName, AI_PROFILE_EXT);
}
/**
* Load all profiles
*/
public static final void loadAllProfiles(String aiProfileDir) {
AI_PROFILE_DIR = aiProfileDir;
loadedProfiles.clear();
ArrayList<String> availableProfiles = getAvailableProfiles();
for (String profile : availableProfiles) {
loadedProfiles.put(profile, loadProfile(profile));
}
}
/**
* Load a single profile.
* @param profileName a profile to load.
*/
private static final Map<AiProps, String> loadProfile(final String profileName) {
Map<AiProps, String> profileMap = new HashMap<AiProps, String>();
List<String> lines = FileUtil.readFile(buildFileName(profileName));
for (String line : lines) {
if (line.startsWith("#") || (line.length() == 0)) {
continue;
}
final String[] split = line.split("=");
if (split.length == 2) {
profileMap.put(AiProps.valueOf(split[0]), split[1]);
} else if (split.length == 1 && line.endsWith("=")) {
profileMap.put(AiProps.valueOf(split[0]), "");
}
}
return profileMap;
}
/**
* Returns an AI property value for the current profile.
*
* @param fp0 an AI property.
* @return String
*/
public static String getAIProp(final LobbyPlayer p, final AiProps fp0) {
String val = null;
if (!(p instanceof LobbyPlayerAi))
return "";
String profile = ((LobbyPlayerAi) p).getAiProfile();
if (loadedProfiles.get(profile) != null) {
val = loadedProfiles.get(profile).get(fp0);
}
if (val == null) { val = fp0.getDefault(); }
return val;
}
/**
* Returns an array of strings containing all available profiles.
* @return ArrayList<String> - an array of strings containing all
* available profiles.
*/
public static ArrayList<String> getAvailableProfiles()
{
final ArrayList<String> availableProfiles = new ArrayList<String>();
final File dir = new File(AI_PROFILE_DIR);
final String[] children = dir.list();
if (children == null) {
System.err.println("AIProfile > can't find AI profile directory!");
} else {
for (int i = 0; i < children.length; i++) {
if (children[i].endsWith(AI_PROFILE_EXT)) {
availableProfiles.add(children[i].substring(0, children[i].length() - AI_PROFILE_EXT.length()));
}
}
}
return availableProfiles;
}
/**
* Returns an array of strings containing all available profiles including
* the special "Random" profiles.
* @return ArrayList<String> - an array list of strings containing all
* available profiles including special random profile tags.
*/
public static ArrayList<String> getProfilesDisplayList() {
final ArrayList<String> availableProfiles = new ArrayList<String>();
availableProfiles.add(AI_PROFILE_RANDOM_MATCH);
availableProfiles.add(AI_PROFILE_RANDOM_DUEL);
availableProfiles.addAll(getAvailableProfiles());
return availableProfiles;
}
public static String[] getProfilesArray() {
return getProfilesDisplayList().toArray(ArrayUtils.EMPTY_STRING_ARRAY);
}
/**
* Returns a random personality from the currently available ones.
* @return String - a string containing a random profile from all the
* currently available ones.
*/
public static String getRandomProfile() {
return Aggregates.random(getAvailableProfiles());
}
/**
* Simple class test facility for AiProfileUtil.
*-/
public static void selfTest() {
final LobbyPlayer activePlayer = Singletons.getControl().getPlayer().getLobbyPlayer();
System.out.println(String.format("Current profile = %s", activePlayer.getAiProfile()));
ArrayList<String> profiles = getAvailableProfiles();
System.out.println(String.format("Available profiles: %s", profiles));
if (profiles.size() > 0) {
System.out.println(String.format("Loading all profiles..."));
loadAllProfiles();
System.out.println(String.format("Setting profile %s...", profiles.get(0)));
activePlayer.setAiProfile(profiles.get(0));
for (AiProps property : AiProps.values()) {
System.out.println(String.format("%s = %s", property, getAIProp(activePlayer, property)));
}
String randomProfile = getRandomProfile();
System.out.println(String.format("Loading random profile %s...", randomProfile));
activePlayer.setAiProfile(randomProfile);
for (AiProps property : AiProps.values()) {
System.out.println(String.format("%s = %s", property, getAIProp(activePlayer, property)));
}
}
}
*/
}

View File

@@ -0,0 +1,50 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2013 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.ai;
/**
* AI personality profile settings identifiers, and their default values.
* When this class is instantiated, these enum values are used
* in a map that is populated with the current AI profile settings
* from the text file.
*/
public enum AiProps { /** */
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"),
CHEAT_WITH_MANA_ON_SHUFFLE ("false"),
MOVE_EQUIPMENT_TO_BETTER_CREATURES ("from_useless_only"),
PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS ("true"),
PREDICT_SPELLS_FOR_MAIN2 ("true"), /** */
RESERVE_MANA_FOR_MAIN2_CHANCE ("0"); /** */
private final String strDefaultVal;
/** @param s0 &emsp; {@link java.lang.String} */
AiProps(final String s0) {
this.strDefaultVal = s0;
}
/** @return {@link java.lang.String} */
public String getDefault() {
return strDefaultVal;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
package forge.ai;
import java.util.ArrayList;
import forge.card.CardStateName;
import forge.game.Game;
import forge.game.GameActionUtil;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
public class ComputerUtilAbility {
public static CardCollection getAvailableCards(final Game game, final Player player) {
CardCollection all = new CardCollection(player.getCardsIn(ZoneType.Hand));
all.addAll(player.getCardsIn(ZoneType.Graveyard));
all.addAll(player.getCardsIn(ZoneType.Command));
if (!player.getCardsIn(ZoneType.Library).isEmpty()) {
all.add(player.getCardsIn(ZoneType.Library).get(0));
}
for(Player p : game.getPlayers()) {
all.addAll(p.getCardsIn(ZoneType.Exile));
all.addAll(p.getCardsIn(ZoneType.Battlefield));
}
return all;
}
public static ArrayList<SpellAbility> getSpellAbilities(final CardCollectionView l, final Player player) {
final ArrayList<SpellAbility> spellAbilities = new ArrayList<SpellAbility>();
for (final Card c : l) {
for (final SpellAbility sa : c.getSpellAbilities()) {
spellAbilities.add(sa);
}
if (c.isFaceDown() && c.isInZone(ZoneType.Exile) && c.mayPlay(player) != null) {
for (final SpellAbility sa : c.getState(CardStateName.Original).getSpellAbilities()) {
spellAbilities.add(sa);
}
}
}
return spellAbilities;
}
public static ArrayList<SpellAbility> getOriginalAndAltCostAbilities(final ArrayList<SpellAbility> originList, final Player player) {
final ArrayList<SpellAbility> newAbilities = new ArrayList<SpellAbility>();
for (SpellAbility sa : originList) {
sa.setActivatingPlayer(player);
//add alternative costs as additional spell abilities
newAbilities.add(sa);
newAbilities.addAll(GameActionUtil.getAlternativeCosts(sa, player));
}
final ArrayList<SpellAbility> result = new ArrayList<SpellAbility>();
for (SpellAbility sa : newAbilities) {
sa.setActivatingPlayer(player);
result.addAll(GameActionUtil.getOptionalCosts(sa));
}
return result;
}
}

View File

@@ -0,0 +1,979 @@
package forge.ai;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import forge.card.CardType;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.card.MagicColor.Constant;
import forge.deck.CardPool;
import forge.deck.Deck;
import forge.deck.DeckSection;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.card.*;
import forge.game.combat.Combat;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.staticability.StaticAbility;
import forge.game.zone.MagicStack;
import forge.game.zone.ZoneType;
import forge.item.PaperCard;
import forge.util.Aggregates;
import forge.util.MyRandom;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import java.util.*;
import java.util.Map.Entry;
public class ComputerUtilCard {
public static Card getMostExpensivePermanentAI(final CardCollectionView list, final SpellAbility spell, final boolean targeted) {
CardCollectionView all = list;
if (targeted) {
all = CardLists.filter(all, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.canBeTargetedBy(spell);
}
});
}
return ComputerUtilCard.getMostExpensivePermanentAI(all);
}
/**
* <p>
* Sorts a List<Card> by "best" using the EvaluateCreature function.
* the best creatures will be first in the list.
* </p>
*
* @param list
* a {@link forge.CardList} object.
*/
public static void sortByEvaluateCreature(final CardCollection list) {
Collections.sort(list, ComputerUtilCard.EvaluateCreatureComparator);
} // sortByEvaluateCreature()
// The AI doesn't really pick the best artifact, just the most expensive.
/**
* <p>
* getBestArtifactAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.game.card.Card} object.
*/
public static Card getBestArtifactAI(final List<Card> list) {
List<Card> all = CardLists.filter(list, CardPredicates.Presets.ARTIFACTS);
if (all.size() == 0) {
return null;
}
// get biggest Artifact
return Aggregates.itemWithMax(all, CardPredicates.Accessors.fnGetCmc);
}
// The AI doesn't really pick the best enchantment, just the most expensive.
/**
* <p>
* getBestEnchantmentAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @param spell
* a {@link forge.game.card.Card} object.
* @param targeted
* a boolean.
* @return a {@link forge.game.card.Card} object.
*/
public static Card getBestEnchantmentAI(final List<Card> list, final SpellAbility spell, final boolean targeted) {
List<Card> all = CardLists.filter(list, CardPredicates.Presets.ENCHANTMENTS);
if (targeted) {
all = CardLists.filter(all, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.canBeTargetedBy(spell);
}
});
}
// get biggest Enchantment
return Aggregates.itemWithMax(all, CardPredicates.Accessors.fnGetCmc);
}
/**
* <p>
* getBestLandAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.game.card.Card} object.
*/
public static Card getBestLandAI(final Iterable<Card> list) {
final List<Card> land = CardLists.filter(list, CardPredicates.Presets.LANDS);
if (land.isEmpty()) {
return null;
}
// prefer to target non basic lands
final List<Card> nbLand = CardLists.filter(land, Predicates.not(CardPredicates.Presets.BASIC_LANDS));
if (!nbLand.isEmpty()) {
// TODO - Rank non basics?
return Aggregates.random(nbLand);
}
// if no non-basic lands, target the least represented basic land type
String sminBL = "";
int iminBL = 20000; // hopefully no one will ever have more than 20000
// lands of one type....
int n = 0;
for (String name : MagicColor.Constant.BASIC_LANDS) {
n = CardLists.getType(land, name).size();
if ((n < iminBL) && (n > 0)) {
// if two or more are tied, only the
// first
// one checked will be used
iminBL = n;
sminBL = name;
}
}
if (iminBL == 20000) {
return null; // no basic land was a minimum
}
final List<Card> bLand = CardLists.getType(land, sminBL);
for (Card ut : Iterables.filter(bLand, CardPredicates.Presets.UNTAPPED)) {
return ut;
}
return Aggregates.random(bLand); // random tapped land of least represented type
}
/**
* <p>
* getCheapestPermanentAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @param spell
* a {@link forge.game.card.Card} object.
* @param targeted
* a boolean.
* @return a {@link forge.game.card.Card} object.
*/
public static Card getCheapestPermanentAI(Iterable<Card> all, final SpellAbility spell, final boolean targeted) {
if (targeted) {
all = CardLists.filter(all, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.canBeTargetedBy(spell);
}
});
}
if (Iterables.isEmpty(all)) {
return null;
}
// get cheapest card:
Card cheapest = null;
for (Card c : all) {
if (cheapest == null || cheapest.getManaCost().getCMC() <= cheapest.getManaCost().getCMC()) {
cheapest = c;
}
}
return cheapest;
}
// returns null if list.size() == 0
/**
* <p>
* getBestAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.game.card.Card} object.
*/
public static Card getBestAI(final Iterable<Card> list) {
// Get Best will filter by appropriate getBest list if ALL of the list
// is of that type
if (Iterables.all(list, CardPredicates.Presets.CREATURES)) {
return ComputerUtilCard.getBestCreatureAI(list);
}
if (Iterables.all(list, CardPredicates.Presets.LANDS)) {
return getBestLandAI(list);
}
// TODO - Once we get an EvaluatePermanent this should call
// getBestPermanent()
return ComputerUtilCard.getMostExpensivePermanentAI(list);
}
/**
* getBestCreatureAI.
*
* @param list
* the list
* @return the card
*/
public static Card getBestCreatureAI(final Iterable<Card> list) {
return Aggregates.itemWithMax(Iterables.filter(list, CardPredicates.Presets.CREATURES), ComputerUtilCard.creatureEvaluator);
}
/**
* <p>
* getWorstCreatureAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.game.card.Card} object.
*/
public static Card getWorstCreatureAI(final Iterable<Card> list) {
return Aggregates.itemWithMin(Iterables.filter(list, CardPredicates.Presets.CREATURES), ComputerUtilCard.creatureEvaluator);
}
// This selection rates tokens higher
/**
* <p>
* getBestCreatureToBounceAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.game.card.Card} object.
*/
public static Card getBestCreatureToBounceAI(final CardCollectionView list) {
final int tokenBonus = 60;
Card biggest = null;
int biggestvalue = -1;
for (Card card : CardLists.filter(list, CardPredicates.Presets.CREATURES)) {
int newvalue = ComputerUtilCard.evaluateCreature(card);
newvalue += card.isToken() ? tokenBonus : 0; // raise the value of tokens
if (biggestvalue < newvalue) {
biggest = card;
biggestvalue = newvalue;
}
}
return biggest;
}
/**
* <p>
* getWorstAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.game.card.Card} object.
*/
public static Card getWorstAI(final Iterable<Card> list) {
return ComputerUtilCard.getWorstPermanentAI(list, false, false, false, false);
}
/**
* <p>
* getWorstPermanentAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @param biasEnch
* a boolean.
* @param biasLand
* a boolean.
* @param biasArt
* a boolean.
* @param biasCreature
* a boolean.
* @return a {@link forge.game.card.Card} object.
*/
public static Card getWorstPermanentAI(final Iterable<Card> list, final boolean biasEnch, final boolean biasLand,
final boolean biasArt, final boolean biasCreature) {
if (Iterables.isEmpty(list)) {
return null;
}
final boolean hasEnchantmants = Iterables.any(list, CardPredicates.Presets.ENCHANTMENTS);
if (biasEnch && hasEnchantmants) {
return getCheapestPermanentAI(CardLists.filter(list, CardPredicates.Presets.ENCHANTMENTS), null, false);
}
final boolean hasArtifacts = Iterables.any(list, CardPredicates.Presets.ARTIFACTS);
if (biasArt && hasArtifacts) {
return getCheapestPermanentAI(CardLists.filter(list, CardPredicates.Presets.ARTIFACTS), null, false);
}
if (biasLand && Iterables.any(list, CardPredicates.Presets.LANDS)) {
return ComputerUtilCard.getWorstLand(CardLists.filter(list, CardPredicates.Presets.LANDS));
}
final boolean hasCreatures = Iterables.any(list, CardPredicates.Presets.CREATURES);
if (biasCreature && hasCreatures) {
return getWorstCreatureAI(CardLists.filter(list, CardPredicates.Presets.CREATURES));
}
List<Card> lands = CardLists.filter(list, CardPredicates.Presets.LANDS);
if (lands.size() > 6) {
return ComputerUtilCard.getWorstLand(lands);
}
if (hasEnchantmants || hasArtifacts) {
final List<Card> ae = CardLists.filter(list, Predicates.<Card>or(CardPredicates.Presets.ARTIFACTS, CardPredicates.Presets.ENCHANTMENTS));
return getCheapestPermanentAI(ae, null, false);
}
if (hasCreatures) {
return getWorstCreatureAI(CardLists.filter(list, CardPredicates.Presets.CREATURES));
}
// Planeswalkers fall through to here, lands will fall through if there
// aren't very many
return getCheapestPermanentAI(list, null, false);
}
public static final Comparator<Card> EvaluateCreatureComparator = new Comparator<Card>() {
@Override
public int compare(final Card a, final Card b) {
return ComputerUtilCard.evaluateCreature(b) - ComputerUtilCard.evaluateCreature(a);
}
};
private static final CreatureEvaluator creatureEvaluator = new CreatureEvaluator();
/**
* <p>
* evaluateCreature.
* </p>
*
* @param c
* a {@link forge.game.card.Card} object.
* @return a int.
*/
public static int evaluateCreature(final Card c) {
return creatureEvaluator.evaluateCreature(c);
}
public static int evaluatePermanentList(final CardCollectionView list) {
int value = 0;
for (int i = 0; i < list.size(); i++) {
value += list.get(i).getCMC() + 1;
}
return value;
}
public static int evaluateCreatureList(final CardCollectionView list) {
return Aggregates.sum(list, creatureEvaluator);
}
public static boolean doesCreatureAttackAI(final Player ai, final Card card) {
AiAttackController aiAtk = new AiAttackController(ai);
Combat combat = new Combat(ai);
aiAtk.declareAttackers(combat);
return combat.isAttacking(card);
}
/**
* Extension of doesCreatureAttackAI() for "virtual" creatures that do not actually exist on the battlefield yet
* such as unanimated manlands.
* @param ai controller of creature
* @param card creature to be evaluated
* @return creature will be attack
*/
public static boolean doesSpecifiedCreatureAttackAI(final Player ai, final Card card) {
AiAttackController aiAtk = new AiAttackController(ai, card);
Combat combat = new Combat(ai);
aiAtk.declareAttackers(combat);
return combat.isAttacking(card);
}
public static boolean canBeKilledByRoyalAssassin(final Player ai, final Card card) {
boolean wasTapped = card.isTapped();
for (Player opp : ai.getOpponents()) {
for (Card c : opp.getCardsIn(ZoneType.Battlefield)) {
for (SpellAbility sa : c.getSpellAbilities()) {
if (sa.getApi() != ApiType.Destroy) {
continue;
}
if (!ComputerUtilCost.canPayCost(sa, opp)) {
continue;
}
sa.setActivatingPlayer(opp);
if (sa.canTarget(card)) {
continue;
}
// check whether the ability can only target tapped creatures
card.setTapped(true);
if (!sa.canTarget(card)) {
card.setTapped(wasTapped);
continue;
}
card.setTapped(wasTapped);
return true;
}
}
}
return false;
}
/**
* Create a mock combat and returns the list of likely blockers.
* @param ai blocking player
* @param blockers list of additional blockers to be considered
* @return list of creatures assigned to block in the simulation
*/
public static CardCollectionView getLikelyBlockers(final Player ai, final CardCollectionView blockers) {
AiBlockController aiBlk = new AiBlockController(ai);
final Player opp = ai.getOpponent();
Combat combat = new Combat(opp);
//Use actual attackers if available, else consider all possible attackers
if (ai.getGame().getCombat() == null) {
for (Card c : opp.getCreaturesInPlay()) {
if (ComputerUtilCombat.canAttackNextTurn(c, ai)) {
combat.addAttacker(c, ai);
}
}
} else {
for (Card c : ai.getGame().getCombat().getAttackers()) {
combat.addAttacker(c, ai);
}
}
if (blockers == null || blockers.isEmpty()) {
aiBlk.assignBlockersForCombat(combat);
} else {
aiBlk.assignAdditionalBlockers(combat, blockers);
}
return combat.getAllBlockers();
}
/**
* Decide if a creature is going to be used as a blocker.
* @param ai controller of creature
* @param blocker creature to be evaluated
* @return creature will be a blocker
*/
public static boolean doesSpecifiedCreatureBlock(final Player ai, Card blocker) {
return getLikelyBlockers(ai, new CardCollection(blocker)).contains(blocker);
}
/**
* Check if an attacker can be blocked profitably (ie. kill attacker)
* @param ai controller of attacking creature
* @param attacker attacking creature to evaluate
* @return attacker will die
*/
public static boolean canBeBlockedProfitably(final Player ai, Card attacker) {
AiBlockController aiBlk = new AiBlockController(ai);
Combat combat = new Combat(ai);
combat.addAttacker(attacker, ai);
final List<Card> attackers = new ArrayList<Card>();
attackers.add(attacker);
aiBlk.assignBlockersGivenAttackers(combat, attackers);
return ComputerUtilCombat.attackerWouldBeDestroyed(ai, attacker, combat);
}
/**
* getMostExpensivePermanentAI.
*
* @param all
* the all
* @return the card
*/
public static Card getMostExpensivePermanentAI(final Iterable<Card> all) {
Card biggest = null;
int bigCMC = -1;
for (final Card card : all) {
int curCMC = card.getCMC();
// Add all cost of all auras with the same controller
if (card.isEnchanted()) {
final List<Card> auras = CardLists.filterControlledBy(card.getEnchantedBy(false), card.getController());
curCMC += Aggregates.sum(auras, CardPredicates.Accessors.fnGetCmc) + auras.size();
}
if (curCMC >= bigCMC) {
bigCMC = curCMC;
biggest = card;
}
}
return biggest;
}
public static String getMostProminentCardName(final CardCollectionView list) {
if (list.size() == 0) {
return "";
}
final Map<String, Integer> map = new HashMap<String, Integer>();
for (final Card c : list) {
final String name = c.getName();
Integer currentCnt = map.get(name);
map.put(name, currentCnt == null ? Integer.valueOf(1) : Integer.valueOf(1 + currentCnt));
} // for
int max = 0;
String maxName = "";
for (final Entry<String, Integer> entry : map.entrySet()) {
final String type = entry.getKey();
// Log.debug(type + " - " + entry.getValue());
if (max < entry.getValue()) {
max = entry.getValue();
maxName = type;
}
}
return maxName;
}
/**
* <p>
* getMostProminentCreatureType.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link java.lang.String} object.
*/
public static String getMostProminentCreatureType(final CardCollectionView list) {
if (list.size() == 0) {
return "";
}
final Map<String, Integer> map = new HashMap<String, Integer>();
for (final Card c : list) {
for (final String var : c.getType()) {
if (CardType.isACreatureType(var)) {
if (!map.containsKey(var)) {
map.put(var, 1);
} else {
map.put(var, map.get(var) + 1);
}
}
}
} // for
int max = 0;
String maxType = "";
for (final Entry<String, Integer> entry : map.entrySet()) {
final String type = entry.getKey();
// Log.debug(type + " - " + entry.getValue());
if (max < entry.getValue()) {
max = entry.getValue();
maxType = type;
}
}
return maxType;
}
/**
* <p>
* getMostProminentColor.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link java.lang.String} object.
*/
public static String getMostProminentColor(final Iterable<Card> list) {
byte colors = CardFactoryUtil.getMostProminentColors(list);
for(byte c : MagicColor.WUBRG) {
if ( (colors & c) != 0 )
return MagicColor.toLongString(c);
}
return MagicColor.Constant.WHITE; // no difference, there was no prominent color
}
public static String getMostProminentColor(final CardCollectionView list, final List<String> restrictedToColors) {
byte colors = CardFactoryUtil.getMostProminentColorsFromList(list, restrictedToColors);
for (byte c : MagicColor.WUBRG) {
if ((colors & c) != 0) {
return MagicColor.toLongString(c);
}
}
return restrictedToColors.get(0); // no difference, there was no prominent color
}
public static List<String> getColorByProminence(final List<Card> list) {
int cntColors = MagicColor.WUBRG.length;
final List<Pair<Byte,Integer>> map = new ArrayList<Pair<Byte,Integer>>();
for(int i = 0; i < cntColors; i++) {
map.add(MutablePair.of(MagicColor.WUBRG[i], 0));
}
for (final Card crd : list) {
ColorSet color = CardUtil.getColors(crd);
if (color.hasWhite()) map.get(0).setValue(Integer.valueOf(map.get(0).getValue()+1));
if (color.hasBlue()) map.get(1).setValue(Integer.valueOf(map.get(1).getValue()+1));
if (color.hasBlack()) map.get(2).setValue(Integer.valueOf(map.get(2).getValue()+1));
if (color.hasRed()) map.get(3).setValue(Integer.valueOf(map.get(3).getValue()+1));
if (color.hasGreen()) map.get(4).setValue(Integer.valueOf(map.get(4).getValue()+1));
} // for
Collections.sort(map, new Comparator<Pair<Byte,Integer>>() {
@Override public int compare(Pair<Byte, Integer> o1, Pair<Byte, Integer> o2) {
return o2.getValue() - o1.getValue();
}
});
// will this part be once dropped?
List<String> result = new ArrayList<String>(cntColors);
for(Pair<Byte, Integer> idx : map) { // fetch color names in the same order
result.add(MagicColor.toLongString(idx.getKey()));
}
// reverse to get indices for most prominent colors first.
return result;
}
/**
* <p>
* getWorstLand.
* </p>
*
* @param lands
* a {@link forge.CardList} object.
* @return a {@link forge.game.card.Card} object.
*/
public static Card getWorstLand(final List<Card> lands) {
Card worstLand = null;
int maxScore = 0;
// first, check for tapped, basic lands
for (Card tmp : lands) {
int score = tmp.isTapped() ? 2 : 0;
score += tmp.isBasicLand() ? 1 : 0;
score -= tmp.isCreature() ? 4 : 0;
for (Card aura : tmp.getEnchantedBy(false)) {
if (aura.getController().isOpponentOf(tmp.getController())) {
score += 5;
} else {
score -= 5;
}
}
if (score >= maxScore) {
worstLand = tmp;
maxScore = score;
}
}
return worstLand;
} // end getWorstLand
public static final Predicate<Deck> AI_KNOWS_HOW_TO_PLAY_ALL_CARDS = new Predicate<Deck>() {
@Override
public boolean apply(Deck d) {
for(Entry<DeckSection, CardPool> cp: d) {
for(Entry<PaperCard, Integer> e : cp.getValue()) {
if ( e.getKey().getRules().getAiHints().getRemAIDecks() )
return false;
}
}
return true;
}
};
public static List<String> chooseColor(SpellAbility sa, int min, int max, List<String> colorChoices) {
List<String> chosen = new ArrayList<String>();
Player ai = sa.getActivatingPlayer();
final Game game = ai.getGame();
Player opp = ai.getOpponent();
if (sa.hasParam("AILogic")) {
final String logic = sa.getParam("AILogic");
if (logic.equals("MostProminentInHumanDeck")) {
chosen.add(ComputerUtilCard.getMostProminentColor(CardLists.filterControlledBy(game.getCardsInGame(), opp), colorChoices));
}
else if (logic.equals("MostProminentInComputerDeck")) {
chosen.add(ComputerUtilCard.getMostProminentColor(CardLists.filterControlledBy(game.getCardsInGame(), ai), colorChoices));
}
else if (logic.equals("MostProminentDualInComputerDeck")) {
List<String> prominence = ComputerUtilCard.getColorByProminence(CardLists.filterControlledBy(game.getCardsInGame(), ai));
chosen.add(prominence.get(0));
chosen.add(prominence.get(1));
}
else if (logic.equals("MostProminentInGame")) {
chosen.add(ComputerUtilCard.getMostProminentColor(game.getCardsInGame(), colorChoices));
}
else if (logic.equals("MostProminentHumanCreatures")) {
CardCollectionView list = opp.getCreaturesInPlay();
if (list.isEmpty()) {
list = CardLists.filter(CardLists.filterControlledBy(game.getCardsInGame(), opp), CardPredicates.Presets.CREATURES);
}
chosen.add(ComputerUtilCard.getMostProminentColor(list, colorChoices));
}
else if (logic.equals("MostProminentComputerControls")) {
chosen.add(ComputerUtilCard.getMostProminentColor(ai.getCardsIn(ZoneType.Battlefield), colorChoices));
}
else if (logic.equals("MostProminentHumanControls")) {
chosen.add(ComputerUtilCard.getMostProminentColor(ai.getOpponent().getCardsIn(ZoneType.Battlefield), colorChoices));
}
else if (logic.equals("MostProminentPermanent")) {
chosen.add(ComputerUtilCard.getMostProminentColor(game.getCardsIn(ZoneType.Battlefield), colorChoices));
}
else if (logic.equals("MostProminentAttackers") && game.getPhaseHandler().inCombat()) {
chosen.add(ComputerUtilCard.getMostProminentColor(game.getCombat().getAttackers(), colorChoices));
}
else if (logic.equals("MostProminentInActivePlayerHand")) {
chosen.add(ComputerUtilCard.getMostProminentColor(game.getPhaseHandler().getPlayerTurn().getCardsIn(ZoneType.Hand), colorChoices));
}
else if (logic.equals("MostProminentInComputerDeckButGreen")) {
List<String> prominence = ComputerUtilCard.getColorByProminence(CardLists.filterControlledBy(game.getCardsInGame(), ai));
if (prominence.get(0) == MagicColor.Constant.GREEN) {
chosen.add(prominence.get(1));
} else {
chosen.add(prominence.get(0));
}
}
else if (logic.equals("MostExcessOpponentControls")) {
int maxExcess = 0;
String bestColor = Constant.GREEN;
for (byte color : MagicColor.WUBRG) {
CardCollectionView ailist = ai.getCardsIn(ZoneType.Battlefield);
CardCollectionView opplist = ai.getOpponent().getCardsIn(ZoneType.Battlefield);
ailist = CardLists.filter(ailist, CardPredicates.isColor(color));
opplist = CardLists.filter(opplist, CardPredicates.isColor(color));
int excess = evaluatePermanentList(opplist) - evaluatePermanentList(ailist);
if (excess > maxExcess) {
maxExcess = excess;
bestColor = MagicColor.toLongString(color);
}
}
chosen.add(bestColor);
}
else if (logic.equals("MostProminentKeywordInComputerDeck")) {
CardCollectionView list = ai.getAllCards();
int m1 = 0;
String chosenColor = MagicColor.Constant.WHITE;
for (final String c : MagicColor.Constant.ONLY_COLORS) {
final int cmp = CardLists.filter(list, CardPredicates.containsKeyword(c)).size();
if (cmp > m1) {
m1 = cmp;
chosenColor = c;
}
}
chosen.add(chosenColor);
}
}
if (chosen.isEmpty()) {
chosen.add(MagicColor.Constant.GREEN);
}
return chosen;
}
public static boolean useRemovalNow(final SpellAbility sa, final Card c, final int dmg, ZoneType destination) {
final Player ai = sa.getActivatingPlayer();
final Player opp = ai.getOpponent();
final Game game = ai.getGame();
final PhaseHandler ph = game.getPhaseHandler();
final int costRemoval = sa.getHostCard().getCMC();
final int costTarget = c.getCMC();
if (!sa.isSpell()) {
return true;
}
//interrupt 1:remove blocker to save my attacker
if (ph.is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
Combat currCombat = game.getCombat();
if (currCombat != null && !currCombat.getAllBlockers().isEmpty() && currCombat.getAllBlockers().contains(c)) {
for (Card attacker : currCombat.getAttackersBlockedBy(c)) {
if (attacker.getShieldCount() == 0 && ComputerUtilCombat.attackerWouldBeDestroyed(ai, attacker, currCombat)) {
CardCollection blockers = currCombat.getBlockers(attacker);
ComputerUtilCard.sortByEvaluateCreature(blockers);
Combat combat = new Combat(ai);
combat.addAttacker(attacker, opp);
for (Card blocker : blockers) {
if (blocker == c) {
continue;
}
combat.addBlocker(attacker, blocker);
}
if (!ComputerUtilCombat.attackerWouldBeDestroyed(ai, attacker, combat)) {
return true;
}
}
}
}
}
//burn and curse spells
float valueBurn = 0;
if (dmg > 0) {
if (sa.getDescription().contains("would die, exile it instead")) {
destination = ZoneType.Exile;
}
valueBurn = 1.0f * c.getNetToughness() / dmg;
valueBurn *= valueBurn;
if (sa.getTargetRestrictions().canTgtPlayer()) {
valueBurn /= 2; //preserve option to burn to the face
}
}
//evaluate tempo gain
float valueTempo = Math.max(0.1f * costTarget / costRemoval, valueBurn);
if (c.isEquipped()) {
valueTempo *= 2;
}
if (SpellAbilityAi.isSorcerySpeed(sa)) {
valueTempo *= 2; //sorceries have less usage opportunities
}
if (!c.canBeDestroyed()) {
valueTempo *= 2; //deal with annoying things
}
if (!destination.equals(ZoneType.Graveyard) && //TODO:boat-load of "when blah dies" triggers
c.hasKeyword("Persist") || c.hasKeyword("Undying") || c.hasKeyword("Modular")) {
valueTempo *= 2;
}
if (destination.equals(ZoneType.Hand) && !c.isToken()) {
valueTempo /= 2; //bouncing non-tokens for tempo is less valuable
}
if (c.isLand()) {
valueTempo += 0.5f / opp.getLandsInPlay().size(); //set back opponent's mana
}
if (c.isEnchanted()) {
boolean myEnchants = false;
for (Card enc : c.getEnchantedBy(false)) {
if (enc.getOwner().equals(ai)) {
myEnchants = true;
break;
}
}
if (!myEnchants) {
valueTempo += 1; //card advantage > tempo
}
}
if (!ph.isPlayerTurn(ai) && ph.getPhase().equals(PhaseType.END_OF_TURN)) {
valueTempo *= 2; //prefer to cast at opponent EOT
}
//interrupt 2:opponent pumping target (only works if the pump target is the chosen best target to begin with)
final MagicStack stack = ai.getGame().getStack();
if (!stack.isEmpty()) {
final SpellAbility topStack = stack.peekAbility();
if (topStack.getActivatingPlayer().equals(opp) && c.equals(topStack.getTargetCard()) && topStack.isSpell()) {
valueTempo += 1;
}
}
//evaluate threat of targeted card
float threat = 0;
if (c.isCreature()) {
Combat combat = ai.getGame().getCombat();
threat = 1.0f * ComputerUtilCombat.damageIfUnblocked(c, opp, combat, true) / ai.getLife();
//TODO:add threat from triggers and other abilities (ie. Master of Cruelties)
} else {
for (final StaticAbility stAb : c.getStaticAbilities()) {
final Map<String, String> params = stAb.getMapParams();
//continuous buffs
if (params.get("Mode").equals("Continuous") && "Creature.YouCtrl".equals(params.get("Affected"))) {
int bonusPT = 0;
if (params.containsKey("AddPower")) {
bonusPT += AbilityUtils.calculateAmount(c, params.get("AddPower"), stAb);
}
if (params.containsKey("AddToughness")) {
bonusPT += AbilityUtils.calculateAmount(c, params.get("AddPower"), stAb);
}
String kws = params.get("AddKeyword");
if (kws != null) {
bonusPT += 4 * (1 + StringUtils.countMatches(kws, "&")); //treat each added keyword as a +2/+2 for now
}
if (bonusPT > 0) {
threat = bonusPT * (1 + opp.getCreaturesInPlay().size()) / 10.0f;
}
}
}
//TODO:add threat from triggers and other abilities (ie. Bident of Thassa)
}
if (!c.getManaAbilities().isEmpty()) {
threat += 0.5f * costTarget / opp.getLandsInPlay().size(); //set back opponent's mana
}
final float valueNow = Math.max(valueTempo, threat);
if (valueNow < 0.2) { //hard floor to reduce ridiculous odds for instants over time
return false;
} else {
final float chance = MyRandom.getRandom().nextFloat();
return chance < valueNow;
}
}
/**
* Applies static continuous Power/Toughness effects to a (virtual) creature.
* @param game game instance to work with
* @param vCard creature to work with
* @param exclude list of cards to exclude when considering ability sources, accepts null
*/
public static void applyStaticContPT(final Game game, Card vCard, final CardCollectionView exclude) {
if (!vCard.isCreature()) {
return;
}
final CardCollection list = new CardCollection(game.getCardsIn(ZoneType.Battlefield));
list.addAll(game.getCardsIn(ZoneType.Command));
if (exclude != null) {
list.removeAll(exclude);
}
for (final Card c : list) {
for (final StaticAbility stAb : c.getStaticAbilities()) {
final Map<String, String> params = stAb.getMapParams();
if (!params.get("Mode").equals("Continuous")) {
continue;
}
if (!params.containsKey("Affected")) {
continue;
}
final String valid = params.get("Affected");
if (!vCard.isValid(valid, c.getController(), c)) {
continue;
}
if (params.containsKey("AddPower")) {
String addP = params.get("AddPower");
int att = 0;
if (addP.equals("AffectedX")) {
att = CardFactoryUtil.xCount(vCard, AbilityUtils.getSVar(stAb, addP));
} else {
att = AbilityUtils.calculateAmount(c, addP, stAb);
}
vCard.addTempPowerBoost(att);
}
if (params.containsKey("AddToughness")) {
String addT = params.get("AddToughness");
int def = 0;
if (addT.equals("AffectedY")) {
def = CardFactoryUtil.xCount(vCard, AbilityUtils.getSVar(stAb, addT));
} else {
def = AbilityUtils.calculateAmount(c, addT, stAb);
}
vCard.addTempToughnessBoost(def);
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,467 @@
package forge.ai;
import forge.ai.AiAttackController;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.card.CounterType;
import forge.game.combat.Combat;
import forge.game.cost.*;
import forge.game.player.Player;
import forge.game.spellability.Spell;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.FCollectionView;
import forge.util.MyRandom;
import forge.util.TextUtil;
import org.apache.commons.lang3.StringUtils;
public class ComputerUtilCost {
/**
* Check add m1 m1 counter cost.
*
* @param cost
* the cost
* @param source
* the source
* @return true, if successful
*/
public static boolean checkAddM1M1CounterCost(final Cost cost, final Card source) {
if (cost == null) {
return true;
}
for (final CostPart part : cost.getCostParts()) {
if (part instanceof CostPutCounter) {
final CostPutCounter addCounter = (CostPutCounter) part;
final CounterType type = addCounter.getCounter();
if (type.equals(CounterType.M1M1)) {
return false;
}
}
}
return true;
}
/**
* Check remove counter cost.
*
* @param cost
* the cost
* @param source
* the source
* @return true, if successful
*/
public static boolean checkRemoveCounterCost(final Cost cost, final Card source) {
if (cost == null) {
return true;
}
for (final CostPart part : cost.getCostParts()) {
if (part instanceof CostRemoveCounter) {
final CostRemoveCounter remCounter = (CostRemoveCounter) part;
final CounterType type = remCounter.counter;
if (!part.payCostFromSource()) {
if (type.name().equals("P1P1")) {
return false;
}
continue;
}
//don't kill the creature
if (type.name().equals("P1P1") && source.getLethalDamage() <= 1) {
return false;
}
}
}
return true;
}
/**
* Check discard cost.
*
* @param cost
* the cost
* @param source
* the source
* @return true, if successful
*/
public static boolean checkDiscardCost(final Player ai, final Cost cost, final Card source) {
if (cost == null) {
return true;
}
for (final CostPart part : cost.getCostParts()) {
if (part instanceof CostDiscard) {
final CostDiscard disc = (CostDiscard) part;
final String type = disc.getType();
if (type.equals("CARDNAME") && source.getAbilityText().contains("Bloodrush")) {
continue;
}
final CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Hand), type.split(","), source.getController(), source);
if (typeList.size() > ai.getMaxHandSize()) {
continue;
}
int num = AbilityUtils.calculateAmount(source, disc.getAmount(), null);
for (int i = 0; i < num; i++) {
Card pref = ComputerUtil.getCardPreference(ai, source, "DiscardCost", typeList);
if (pref == null) {
return false;
} else {
typeList.remove(pref);
}
}
}
}
return true;
}
/**
* Check life cost.
*
* @param cost
* the cost
* @param source
* the source
* @param remainingLife
* the remaining life
* @return true, if successful
*/
public static boolean checkDamageCost(final Player ai, final Cost cost, final Card source, final int remainingLife) {
if (cost == null) {
return true;
}
for (final CostPart part : cost.getCostParts()) {
if (part instanceof CostDamage) {
final CostDamage pay = (CostDamage) part;
int realDamage = ComputerUtilCombat.predictDamageTo(ai, pay.convertAmount(), source, false);
if (ai.getLife() - realDamage < remainingLife
&& realDamage > 0 && !ai.cantLoseForZeroOrLessLife()
&& ai.canLoseLife()) {
return false;
}
if (source.getName().equals("Skullscorch") && ai.getCardsIn(ZoneType.Hand).size() < 2) {
return false;
}
}
}
return true;
}
/**
* Check life cost.
*
* @param cost
* the cost
* @param source
* the source
* @param remainingLife
* the remaining life
* @param sourceAbility TODO
* @return true, if successful
*/
public static boolean checkLifeCost(final Player ai, final Cost cost, final Card source, final int remainingLife, SpellAbility sourceAbility) {
// TODO - Pass in SA for everything else that calls this function
if (cost == null) {
return true;
}
for (final CostPart part : cost.getCostParts()) {
if (part instanceof CostPayLife) {
final CostPayLife payLife = (CostPayLife) part;
Integer amount = payLife.convertAmount();
if (amount == null) {
amount = AbilityUtils.calculateAmount(source, payLife.getAmount(), sourceAbility);
}
if ((ai.getLife() - amount) < remainingLife) {
return false;
}
}
}
return true;
}
/**
* Check creature sacrifice cost.
*
* @param cost
* the cost
* @param source
* the source
* @return true, if successful
*/
public static boolean checkCreatureSacrificeCost(final Player ai, final Cost cost, final Card source) {
if (cost == null) {
return true;
}
for (final CostPart part : cost.getCostParts()) {
if (part instanceof CostSacrifice) {
final CostSacrifice sac = (CostSacrifice) part;
if (sac.payCostFromSource() && source.isCreature()) {
return false;
}
final String type = sac.getType();
if (type.equals("CARDNAME")) {
continue;
}
final CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(","), source.getController(), source);
if (ComputerUtil.getCardPreference(ai, source, "SacCost", typeList) == null) {
return false;
}
}
}
return true;
}
/**
* Check sacrifice cost.
*
* @param cost
* the cost
* @param source
* the source
* @param important
* is the gain important enough?
* @return true, if successful
*/
public static boolean checkSacrificeCost(final Player ai, final Cost cost, final Card source, final boolean important) {
if (cost == null) {
return true;
}
for (final CostPart part : cost.getCostParts()) {
if (part instanceof CostSacrifice) {
final CostSacrifice sac = (CostSacrifice) part;
final String type = sac.getType();
if (type.equals("CARDNAME")) {
if (!important) {
return false;
}
if (!CardLists.filterControlledBy(source.getEnchantedBy(false), source.getController()).isEmpty()) {
return false;
}
continue;
}
final CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(","), source.getController(), source);
if (ComputerUtil.getCardPreference(ai, source, "SacCost", typeList) == null) {
return false;
}
}
}
return true;
}
public static boolean isSacrificeSelfCost(final Cost cost) {
if (cost == null) {
return false;
}
for (final CostPart part : cost.getCostParts()) {
if (part instanceof CostSacrifice) {
if ("CARDNAME".equals(part.getType())) {
return true;
}
}
}
return false;
}
/**
* Check creature sacrifice cost.
*
* @param cost
* the cost
* @param source
* the source
* @return true, if successful
*/
public static boolean checkTapTypeCost(final Player ai, final Cost cost, final Card source) {
if (cost == null) {
return true;
}
for (final CostPart part : cost.getCostParts()) {
if (part instanceof CostTapType) {
return false;
}
}
return true;
}
/**
* Check sacrifice cost.
*
* @param cost
* the cost
* @param source
* the source
* @return true, if successful
*/
public static boolean checkSacrificeCost(final Player ai, final Cost cost, final Card source) {
return checkSacrificeCost(ai, cost, source, true);
}
/**
* <p>
* shouldPayCost.
* </p>
*
* @param hostCard
* a {@link forge.game.card.Card} object.
* @param costString
* a {@link java.lang.String} object.
* @return a boolean.
*/
public static boolean shouldPayCost(final Player ai, final Card hostCard, final Cost cost) {
for (final CostPart part : cost.getCostParts()) {
if (part instanceof CostPayLife) {
final int remainingLife = ai.getLife();
final int lifeCost = ((CostPayLife) part).convertAmount();
if ((remainingLife - lifeCost) < 10) {
return false; //Don't pay life if it would put AI under 10 life
} else if ((remainingLife / lifeCost) < 4) {
return false; //Don't pay life if it is more than 25% of current life
}
}
}
return true;
} // shouldPayCost()
/**
* <p>
* canPayCost.
* </p>
*
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @param player
* a {@link forge.game.player.Player} object.
* @return a boolean.
*/
public static boolean canPayCost(final SpellAbility sa, final Player player) {
if (sa.getActivatingPlayer() == null) {
sa.setActivatingPlayer(player); // complaints on NPE had came before this line was added.
}
// Check for stuff like Nether Void
int extraManaNeeded = 0;
if (sa instanceof Spell) {
for (Card c : player.getGame().getCardsIn(ZoneType.Battlefield)) {
final String snem = c.getSVar("AI_SpellsNeedExtraMana");
if (!StringUtils.isBlank(snem)) {
String[] parts = TextUtil.split(snem, ' ');
boolean meetsRestriction = parts.length == 1 || player.isValid(parts[1], c.getController(), c);
if(!meetsRestriction)
continue;
try {
extraManaNeeded += Integer.parseInt(snem);
} catch (final NumberFormatException e) {
System.out.println("wrong SpellsNeedExtraMana SVar format on " + c);
}
}
}
for (Card c : player.getCardsIn(ZoneType.Command)) {
final String snem = c.getSVar("SpellsNeedExtraManaEffect");
if (!StringUtils.isBlank(snem)) {
try {
extraManaNeeded += Integer.parseInt(snem);
} catch (final NumberFormatException e) {
System.out.println("wrong SpellsNeedExtraManaEffect SVar format on " + c);
}
}
}
}
return ComputerUtilMana.canPayManaCost(sa, player, extraManaNeeded)
&& CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa);
} // canPayCost()
public static boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
final Card source = sa.getHostCard();
final String aiLogic = sa.getParam("UnlessAI");
boolean payForOwnOnly = "OnlyOwn".equals(aiLogic);
boolean payOwner = sa.hasParam("UnlessAI") ? aiLogic.startsWith("Defined") : false;
boolean payNever = "Never".equals(aiLogic);
boolean shockland = "Shockland".equals(aiLogic);
boolean isMine = sa.getActivatingPlayer().equals(payer);
if (payNever) { return false; }
if (payForOwnOnly && !isMine) { return false; }
if (payOwner) {
final String defined = aiLogic.substring(7);
final Player player = AbilityUtils.getDefinedPlayers(source, defined, sa).get(0);
if (!payer.equals(player)) {
return false;
}
} else if ("OnlyDontControl".equals(aiLogic)) {
if (sa.getHostCard() == null || payer.equals(sa.getHostCard().getController())) {
return false;
}
} else if (shockland) {
if (payer.getLife() > 3 && payer.canPayLife(2)) {
// If the new land size would equal the CMC of a card in AIs hand, play it untapped
final int landsize = payer.getLandsInPlay().size() + 1;
for (Card c : payer.getCardsIn(ZoneType.Hand)) {
if (landsize == c.getCMC()) {
return true;
}
}
}
return false;
} else if ("Paralyze".equals(aiLogic)) {
final Card c = source.getEnchantingCard();
if (c == null || c.isUntapped()) {
return false;
}
} else if ("MorePowerful".equals(aiLogic)) {
final int sourceCreatures = sa.getActivatingPlayer().getCreaturesInPlay().size();
final int payerCreatures = payer.getCreaturesInPlay().size();
if (payerCreatures > sourceCreatures + 1) {
return false;
}
} else if ("LifeLE2".equals(aiLogic)) {
if (payer.getLife() < 3) {
return true;
}
} else if ("WillAttack".equals(aiLogic)) {
AiAttackController aiAtk = new AiAttackController(payer);
Combat combat = new Combat(payer);
aiAtk.declareAttackers(combat);
if (combat.getAttackers().isEmpty()) {
return false;
}
} else if ("nonToken".equals(aiLogic) && AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa).get(0).isToken()) {
return false;
} else if ("LowPriority".equals(aiLogic) && MyRandom.getRandom().nextInt(100) < 67) {
return false;
}
// AI will only pay when it's not already payed and only opponents abilities
if (alreadyPaid || (payers.size() > 1 && (isMine && !payForOwnOnly))) {
return false;
}
// AI was crashing because the blank ability used to pay costs
// Didn't have any of the data on the original SA to pay dependant costs
return checkLifeCost(payer, cost, source, 4, sa)
&& checkDamageCost(payer, cost, source, 4)
&& (isMine || checkSacrificeCost(payer, cost, source))
&& (isMine || checkDiscardCost(payer, cost, source))
&& (!source.getName().equals("Tyrannize") || payer.getCardsIn(ZoneType.Hand).size() > 2)
&& (!source.getName().equals("Perplex") || payer.getCardsIn(ZoneType.Hand).size() < 2)
&& (!source.getName().equals("Breaking Point") || payer.getCreaturesInPlay().size() > 1)
&& (!source.getName().equals("Chain of Vapor") || (payer.getOpponent().getCreaturesInPlay().size() > 0 && payer.getLandsInPlay().size() > 3));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,212 @@
package forge.ai;
import com.google.common.base.Function;
import forge.game.card.Card;
import forge.game.spellability.SpellAbility;
public class CreatureEvaluator implements Function<Card, Integer> {
protected int getEffectivePower(final Card c) {
return c.getNetCombatDamage();
}
protected int getEffectiveToughness(final Card c) {
return c.getNetToughness();
}
@Override
public Integer apply(Card c) {
return evaluateCreature(c);
}
public int evaluateCreature(final Card c) {
int value = 80;
if (!c.isToken()) {
value += addValue(80, "non-token"); // tokens should be worth less than actual cards
}
int power = getEffectivePower(c);
final int toughness = getEffectiveToughness(c);
for (String keyword : c.getKeywords()) {
if (keyword.equals("Prevent all combat damage that would be dealt by CARDNAME.")
|| keyword.equals("Prevent all damage that would be dealt by CARDNAME.")
|| keyword.equals("Prevent all combat damage that would be dealt to and dealt by CARDNAME.")
|| keyword.equals("Prevent all damage that would be dealt to and dealt by CARDNAME.")) {
power = 0;
break;
}
}
value += addValue(power * 15, "power");
value += addValue(toughness * 10, "toughness");
value += addValue(c.getCMC() * 5, "cmc");
// Evasion keywords
if (c.hasKeyword("Flying")) {
value += addValue(power * 10, "flying");
}
if (c.hasKeyword("Horsemanship")) {
value += addValue(power * 10, "horses");
}
if (c.hasKeyword("Unblockable")) {
value += addValue(power * 10, "unblockable");
} else {
if (c.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")) {
value += addValue(power * 6, "thorns");
}
if (c.hasKeyword("Fear")) {
value += addValue(power * 6, "fear");
}
if (c.hasKeyword("Intimidate")) {
value += addValue(power * 6, "intimidate");
}
if (c.hasStartOfKeyword("CantBeBlockedBy")) {
value += addValue(power * 3, "block-restrict");
}
}
// Other good keywords
if (power > 0) {
if (c.hasKeyword("Double Strike")) {
value += addValue(10 + (power * 15), "ds");
} else if (c.hasKeyword("First Strike")) {
value += addValue(10 + (power * 5), "fs");
}
if (c.hasKeyword("Deathtouch")) {
value += addValue(25, "dt");
}
if (c.hasKeyword("Lifelink")) {
value += addValue(power * 10, "lifelink");
}
if (power > 1 && c.hasKeyword("Trample")) {
value += addValue((power - 1) * 5, "trample");
}
if (c.hasKeyword("Vigilance")) {
value += addValue((power * 5) + (toughness * 5), "vigilance");
}
if (c.hasKeyword("Wither")) {
value += addValue(power * 10, "Wither");
}
if (c.hasKeyword("Infect")) {
value += addValue(power * 15, "infect");
}
value += addValue(c.getKeywordMagnitude("Rampage"), "rampage");
}
value += addValue(c.getKeywordMagnitude("Bushido") * 16, "bushido");
value += addValue(c.getAmountOfKeyword("Flanking") * 15, "flanking");
value += addValue(c.getAmountOfKeyword("Exalted") * 15, "exalted");
value += addValue(c.getKeywordMagnitude("Annihilator") * 50, "eldrazi");
value += addValue(c.getKeywordMagnitude("Absorb") * 11, "absorb");
// Defensive Keywords
if (c.hasKeyword("Reach") && !c.hasKeyword("Flying")) {
value += addValue(5, "reach");
}
if (c.hasKeyword("CARDNAME can block creatures with shadow as though they didn't have shadow.")) {
value += addValue(3, "shadow-block");
}
// Protection
if (c.hasKeyword("Indestructible")) {
value += addValue(70, "darksteel");
}
if (c.hasKeyword("Prevent all damage that would be dealt to CARDNAME.")) {
value += addValue(60, "cho-manno");
} else if (c.hasKeyword("Prevent all combat damage that would be dealt to CARDNAME.")) {
value += addValue(50, "fogbank");
}
if (c.hasKeyword("Hexproof")) {
value += addValue(35, "hexproof");
} else if (c.hasKeyword("Shroud")) {
value += addValue(30, "shroud");
}
if (c.hasStartOfKeyword("Protection")) {
value += addValue(20, "protection");
}
if (c.hasStartOfKeyword("PreventAllDamageBy")) {
value += addValue(10, "prevent-dmg");
}
// Bad keywords
if (c.hasKeyword("Defender") || c.hasKeyword("CARDNAME can't attack.")) {
value -= subValue((power * 9) + 40, "defender");
} else if (c.getSVar("SacrificeEndCombat").equals("True")) {
value -= subValue(40, "sac-end");
}
if (c.hasKeyword("CARDNAME can't block.")) {
value -= subValue(10, "cant-block");
} else if (c.hasKeyword("CARDNAME attacks each turn if able.")
|| c.hasKeyword("CARDNAME attacks each combat if able.")) {
value -= subValue(10, "must-attack");
} else if (c.hasStartOfKeyword("CARDNAME attacks specific player each combat if able")) {
value -= subValue(10, "must-attack-player");
} else if (c.hasKeyword("CARDNAME can block only creatures with flying.")) {
value -= subValue(toughness * 5, "reverse-reach");
}
if (c.hasSVar("DestroyWhenDamaged")) {
value -= subValue((toughness - 1) * 9, "dies-to-dmg");
}
if (c.hasKeyword("CARDNAME can't attack or block.")) {
value = addValue(50 + (c.getCMC() * 5), "useless"); // reset everything - useless
}
if (c.hasKeyword("CARDNAME doesn't untap during your untap step.")) {
if (c.isTapped()) {
value = addValue(50 + (c.getCMC() * 5), "tapped-useless"); // reset everything - useless
} else {
value -= subValue(50, "doesnt-untap");
}
}
if (c.hasSVar("EndOfTurnLeavePlay")) {
value -= subValue(50, "eot-leaves");
} else if (c.hasStartOfKeyword("Cumulative upkeep")) {
value -= subValue(30, "cupkeep");
} else if (c.hasStartOfKeyword("At the beginning of your upkeep, sacrifice CARDNAME unless you pay")) {
value -= subValue(20, "sac-unless");
} else if (c.hasStartOfKeyword("(Echo unpaid)")) {
value -= subValue(10, "echo-unpaid");
}
if (c.hasStartOfKeyword("At the beginning of your upkeep, CARDNAME deals")) {
value -= subValue(20, "upkeep-dmg");
}
if (c.hasStartOfKeyword("Fading")) {
value -= subValue(20, "fading");
}
if (c.hasStartOfKeyword("Vanishing")) {
value -= subValue(20, "vanishing");
}
if (c.getSVar("Targeting").equals("Dies")) {
value -= subValue(25, "dies");
}
for (final SpellAbility sa : c.getSpellAbilities()) {
if (sa.isAbility()) {
value += addValue(10, "sa: " + sa);
}
}
if (!c.getManaAbilities().isEmpty()) {
value += addValue(10, "manadork");
}
if (c.isUntapped()) {
value += addValue(1, "untapped");
}
// paired creatures are more valuable because they grant a bonus to the other creature
if (c.isPaired()) {
value += addValue(14, "paired");
}
if (!c.getEncodedCards().isEmpty()) {
value += addValue(24, "encoded");
}
return value;
}
protected int addValue(int value, String text) {
return value;
}
protected int subValue(int value, String text) {
return -addValue(-value, text);
}
}

View File

@@ -0,0 +1,293 @@
package forge.ai;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import forge.card.CardStateName;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardFactory;
import forge.game.card.CounterType;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.item.IPaperCard;
import forge.util.FCollectionView;
public abstract class GameState {
private static final Map<ZoneType, String> ZONES = new HashMap<ZoneType, String>();
static {
ZONES.put(ZoneType.Battlefield, "play");
ZONES.put(ZoneType.Hand, "hand");
ZONES.put(ZoneType.Graveyard, "graveyard");
ZONES.put(ZoneType.Library, "library");
ZONES.put(ZoneType.Exile, "exile");
ZONES.put(ZoneType.Command, "command");
}
private int humanLife = -1;
private int computerLife = -1;
private final Map<ZoneType, String> humanCardTexts = new EnumMap<ZoneType, String>(ZoneType.class);
private final Map<ZoneType, String> aiCardTexts = new EnumMap<ZoneType, String>(ZoneType.class);
private String tChangePlayer = "NONE";
private String tChangePhase = "NONE";
public GameState() {
}
public abstract IPaperCard getPaperCard(String cardName);
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(String.format("humanlife=%d\n", humanLife));
sb.append(String.format("ailife=%d\n", computerLife));
sb.append(String.format("activeplayer=%s\n", tChangePlayer));
sb.append(String.format("activephase=%s\n", tChangePhase));
appendCards(humanCardTexts, "human", sb);
appendCards(aiCardTexts, "ai", sb);
return sb.toString();
}
private void appendCards(Map<ZoneType, String> cardTexts, String categoryPrefix, StringBuilder sb) {
for (Entry<ZoneType, String> kv : cardTexts.entrySet()) {
sb.append(String.format("%scardsin%s=%s\n", categoryPrefix, ZONES.get(kv.getKey()), kv.getValue()));
}
}
public void initFromGame(Game game) throws Exception {
FCollectionView<Player> players = game.getPlayers();
// Can only serialized a two player game with one AI and one human.
if (players.size() != 2) {
throw new Exception("Game not supported");
}
final Player human = game.getPlayers().get(0);
final Player ai = game.getPlayers().get(1);
if (!human.getController().isGuiPlayer() || !ai.getController().isAI()) {
throw new Exception("Game not supported");
}
humanLife = human.getLife();
computerLife = ai.getLife();
tChangePlayer = game.getPhaseHandler().getPlayerTurn() == ai ? "ai" : "human";
tChangePhase = game.getPhaseHandler().getPhase().toString();
aiCardTexts.clear();
humanCardTexts.clear();
for (ZoneType zone : ZONES.keySet()) {
// Init texts to empty, so that restoring will clear the state
// if the zone had no cards in it (e.g. empty hand).
aiCardTexts.put(zone, "");
humanCardTexts.put(zone, "");
for (Card card : game.getCardsIn(zone)) {
addCard(zone, card.getOwner() == ai ? aiCardTexts : humanCardTexts, card);
}
}
}
private void addCard(ZoneType zoneType, Map<ZoneType, String> cardTexts, Card c) {
StringBuilder newText = new StringBuilder(cardTexts.get(zoneType));
if (newText.length() > 0) {
newText.append(";");
}
if (c.isToken()) {
newText.append("t:" + new CardFactory.TokenInfo(c).toString());
} else {
newText.append(c.getPaperCard().getName());
}
if (zoneType == ZoneType.Battlefield) {
if (c.isTapped()) {
newText.append("|Tapped:True");
}
if (c.isSick()) {
newText.append("|SummonSick:True");
}
if (c.isFaceDown()) {
newText.append("|FaceDown:True");
}
Map<CounterType, Integer> counters = c.getCounters();
if (!counters.isEmpty()) {
newText.append("|Counters:");
boolean start = true;
for(Entry<CounterType, Integer> kv : counters.entrySet()) {
String str = kv.getKey().toString();
int count = kv.getValue();
for (int i = 0; i < count; i++) {
if (!start) {
newText.append(",");
}
newText.append(str);
start = false;
}
}
}
}
cardTexts.put(zoneType, newText.toString());
}
private String[] parseLine(String line) {
if (line.charAt(0) == '#') {
return null;
}
final String[] tempData = line.split("=");
if (tempData.length >= 2) {
return tempData;
}
if (tempData.length == 1 && line.endsWith("=")) {
// Empty value.
return new String[] {tempData[0], ""};
}
return null;
}
public void parse(InputStream in) throws Exception {
final BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = br.readLine()) != null) {
String[] keyValue = parseLine(line);
if (keyValue == null) {
continue;
}
final String categoryName = keyValue[0].toLowerCase();
final String categoryValue = keyValue[1];
if (categoryName.equals("humanlife")) humanLife = Integer.parseInt(categoryValue);
else if (categoryName.equals("ailife")) computerLife = Integer.parseInt(categoryValue);
else if (categoryName.equals("activeplayer")) tChangePlayer = categoryValue.trim().toLowerCase();
else if (categoryName.equals("activephase")) tChangePhase = categoryValue;
else if (categoryName.equals("humancardsinplay")) humanCardTexts.put(ZoneType.Battlefield, categoryValue);
else if (categoryName.equals("aicardsinplay")) aiCardTexts.put(ZoneType.Battlefield, categoryValue);
else if (categoryName.equals("humancardsinhand")) humanCardTexts.put(ZoneType.Hand, categoryValue);
else if (categoryName.equals("aicardsinhand")) aiCardTexts.put(ZoneType.Hand, categoryValue);
else if (categoryName.equals("humancardsingraveyard")) humanCardTexts.put(ZoneType.Graveyard, categoryValue);
else if (categoryName.equals("aicardsingraveyard")) aiCardTexts.put(ZoneType.Graveyard, categoryValue);
else if (categoryName.equals("humancardsinlibrary")) humanCardTexts.put(ZoneType.Library, categoryValue);
else if (categoryName.equals("aicardsinlibrary")) aiCardTexts.put(ZoneType.Library, categoryValue);
else if (categoryName.equals("humancardsinexile")) humanCardTexts.put(ZoneType.Exile, categoryValue);
else if (categoryName.equals("aicardsinexile")) aiCardTexts.put(ZoneType.Exile, categoryValue);
else System.out.println("Unknown key: " + categoryName);
}
}
public void applyToGame(final Game game) {
game.getAction().invoke(new Runnable() {
@Override
public void run() {
final Player human = game.getPlayers().get(0);
final Player ai = game.getPlayers().get(1);
Player newPlayerTurn = tChangePlayer.equals("human") ? newPlayerTurn = human : tChangePlayer.equals("ai") ? newPlayerTurn = ai : null;
PhaseType newPhase = tChangePhase.trim().equalsIgnoreCase("none") ? null : PhaseType.smartValueOf(tChangePhase);
game.getPhaseHandler().devModeSet(newPhase, newPlayerTurn);
game.getTriggerHandler().suppressMode(TriggerType.ChangesZone);
setupPlayerState(humanLife, humanCardTexts, human);
setupPlayerState(computerLife, aiCardTexts, ai);
game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
game.getAction().checkStateEffects(true); //ensure state based effects and triggers are updated
}
});
}
private void setupPlayerState(int life, Map<ZoneType, String> cardTexts, final Player p) {
Map<ZoneType, CardCollectionView> playerCards = new EnumMap<ZoneType, CardCollectionView>(ZoneType.class);
for(Entry<ZoneType, String> kv : cardTexts.entrySet()) {
String value = kv.getValue();
playerCards.put(kv.getKey(), processCardsForZone(value.isEmpty() ? new String[0] : value.split(";"), p));
}
if (life > 0) p.setLife(life, null);
for (Entry<ZoneType, CardCollectionView> kv : playerCards.entrySet()) {
if (kv.getKey() == ZoneType.Battlefield) {
ArrayList<Card> cards = new ArrayList<Card>();
for (final Card c : kv.getValue()) {
if (c.isToken()) {
cards.add(c);
}
}
p.getZone(kv.getKey()).setCards(cards);
for (final Card c : kv.getValue()) {
if (c.isToken()) {
continue;
}
boolean tapped = c.isTapped();
boolean sickness = c.hasSickness();
p.getZone(ZoneType.Hand).add(c);
p.getGame().getAction().moveToPlay(c);
c.setTapped(tapped);
c.setSickness(sickness);
}
} else {
p.getZone(kv.getKey()).setCards(kv.getValue());
}
}
}
/**
* <p>
* processCardsForZone.
* </p>
*
* @param data
* an array of {@link java.lang.String} objects.
* @param player
* a {@link forge.game.player.Player} object.
* @return a {@link forge.CardList} object.
*/
private CardCollectionView processCardsForZone(final String[] data, final Player player) {
final CardCollection cl = new CardCollection();
for (final String element : data) {
final String[] cardinfo = element.trim().split("\\|");
Card c;
if (cardinfo[0].startsWith("t:")) {
String tokenStr = cardinfo[0].substring(2);
// TODO: Use a version of the API that doesn't return a list (i.e. these shouldn't be affected
// by doubling season, etc).
c = CardFactory.makeToken(CardFactory.TokenInfo.fromString(tokenStr), player).get(0);
} else {
c = Card.fromPaperCard(getPaperCard(cardinfo[0]), player);
}
c.setSickness(false);
boolean hasSetCurSet = false;
for (final String info : cardinfo) {
if (info.startsWith("Set:")) {
c.setSetCode(info.substring(info.indexOf(':') + 1));
hasSetCurSet = true;
} else if (info.equalsIgnoreCase("Tapped:True")) {
c.tap();
} else if (info.startsWith("Counters:")) {
final String[] counterStrings = info.substring(info.indexOf(':') + 1).split(",");
for (final String counter : counterStrings) {
c.addCounter(CounterType.valueOf(counter), 1, true);
}
} else if (info.equalsIgnoreCase("SummonSick:True")) {
c.setSickness(true);
} else if (info.equalsIgnoreCase("FaceDown:True")) {
c.setState(CardStateName.FaceDown, true);
}
}
if (!hasSetCurSet && !c.isToken()) {
c.setSetCode(c.getMostRecentSet());
}
cl.add(c);
}
return cl;
}
}

View File

@@ -0,0 +1,71 @@
package forge.ai;
import java.util.Map;
import forge.LobbyPlayer;
import forge.game.Game;
import forge.game.player.IGameEntitiesFactory;
import forge.game.player.Player;
import forge.game.player.PlayerController;
public class LobbyPlayerAi extends LobbyPlayer implements IGameEntitiesFactory {
private String aiProfile = "";
private boolean rotateProfileEachGame;
private boolean allowCheatShuffle;
private boolean useSimulation;
public LobbyPlayerAi(String name, Map<String, String> options) {
super(name);
if (options != null && "True".equals(options.get("UseSimulation"))) {
this.useSimulation = true;
}
}
public boolean isAllowCheatShuffle() {
return allowCheatShuffle;
}
public void setAllowCheatShuffle(boolean allowCheatShuffle) {
this.allowCheatShuffle = allowCheatShuffle;
}
public void setAiProfile(String profileName) {
aiProfile = profileName;
}
public String getAiProfile() {
return aiProfile;
}
public void setRotateProfileEachGame(boolean rotateProfileEachGame) {
this.rotateProfileEachGame = rotateProfileEachGame;
}
private PlayerControllerAi createControllerFor(Player ai) {
PlayerControllerAi result = new PlayerControllerAi(ai.getGame(), ai, this);
result.setUseSimulation(useSimulation);
result.allowCheatShuffle(allowCheatShuffle);
return result;
}
@Override
public PlayerController createMindSlaveController(Player master, Player slave) {
return createControllerFor(slave);
}
@Override
public Player createIngamePlayer(Game game, final int id) {
Player ai = new Player(getName(), game, id);
ai.setFirstController(createControllerFor(ai));
if (rotateProfileEachGame) {
setAiProfile(AiProfileUtil.getRandomProfile());
System.out.println(String.format("AI profile %s was chosen for the lobby player %s.", getAiProfile(), getName()));
}
return ai;
}
@Override
public void hear(LobbyPlayer player, String message) { /* Local AI is deaf. */ }
}

View File

@@ -0,0 +1,857 @@
package forge.ai;
import com.esotericsoftware.minlog.Log;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import forge.LobbyPlayer;
import forge.ai.ability.ChangeZoneAi;
import forge.ai.ability.CharmAi;
import forge.ai.ability.ProtectAi;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostShard;
import forge.deck.Deck;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GameObject;
import forge.game.GameType;
import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.card.*;
import forge.game.card.CardPredicates.Presets;
import forge.game.combat.Combat;
import forge.game.cost.Cost;
import forge.game.cost.CostPart;
import forge.game.cost.CostPartMana;
import forge.game.mana.Mana;
import forge.game.mana.ManaCostBeingPaid;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.DelayedReveal;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.player.PlayerController;
import forge.game.replacement.ReplacementEffect;
import forge.game.spellability.*;
import forge.game.trigger.Trigger;
import forge.game.trigger.WrappedAbility;
import forge.game.zone.ZoneType;
import forge.item.PaperCard;
import forge.util.Aggregates;
import forge.util.FCollection;
import forge.util.FCollectionView;
import forge.util.ITriggerEvent;
import forge.util.MyRandom;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import java.security.InvalidParameterException;
import java.util.*;
/**
* A prototype for player controller class
*
* Handles phase skips for now.
*/
public class PlayerControllerAi extends PlayerController {
private final AiController brains;
public PlayerControllerAi(Game game, Player p, LobbyPlayer lp) {
super(game, p, lp);
brains = new AiController(p, game);
}
public void allowCheatShuffle(boolean value){
brains.allowCheatShuffle(value);
}
public void setUseSimulation(boolean value) {
brains.setUseSimulation(value);
}
public SpellAbility getAbilityToPlay(List<SpellAbility> abilities, ITriggerEvent triggerEvent) {
if (abilities.size() == 0) {
return null;
}
else {
return abilities.get(0);
}
}
public AiController getAi() {
return brains;
}
@Override
public boolean isAI() {
return true;
}
@Override
public List<PaperCard> sideboard(Deck deck, GameType gameType) {
// AI does not know how to sideboard
return null;
}
@Override
public Map<Card, Integer> assignCombatDamage(Card attacker, CardCollectionView blockers, int damageDealt, GameEntity defender, boolean overrideOrder) {
return ComputerUtilCombat.distributeAIDamage(attacker, blockers, damageDealt, defender, overrideOrder);
}
@Override
public Integer announceRequirements(SpellAbility ability, String announce, boolean allowZero) {
// For now, these "announcements" are made within the AI classes of the appropriate SA effects
if (ability.getApi() != null) {
switch (ability.getApi()) {
case ChooseNumber:
return ability.getActivatingPlayer().isOpponentOf(player) ? 0 : ComputerUtilMana.determineLeftoverMana(ability, player);
case BidLife:
return 0;
default:
return null;
}
}
return null; // return incorrect value to indicate that
}
@Override
public CardCollectionView choosePermanentsToSacrifice(SpellAbility sa, int min, int max, CardCollectionView validTargets, String message) {
return ComputerUtil.choosePermanentsToSacrifice(player, validTargets, max, sa, false, min == 0);
}
@Override
public CardCollectionView choosePermanentsToDestroy(SpellAbility sa, int min, int max, CardCollectionView validTargets, String message) {
return ComputerUtil.choosePermanentsToSacrifice(player, validTargets, max, sa, true, min == 0);
}
@Override
public CardCollectionView chooseCardsForEffect(CardCollectionView sourceList, SpellAbility sa, String title, int min, int max, boolean isOptional) {
return brains.chooseCardsForEffect(sourceList, sa, min, max, isOptional);
}
@Override
public <T extends GameEntity> T chooseSingleEntityForEffect(FCollectionView<T> optionList, DelayedReveal delayedReveal, SpellAbility sa, String title, boolean isOptional, Player targetedPlayer) {
if (delayedReveal != null) {
delayedReveal.reveal(this);
}
ApiType api = sa.getApi();
if (null == api) {
throw new InvalidParameterException("SA is not api-based, this is not supported yet");
}
return SpellApiToAi.Converter.get(api).chooseSingleEntity(player, sa, (FCollection<T>)optionList, isOptional, targetedPlayer);
}
@Override
public SpellAbility chooseSingleSpellForEffect(java.util.List<SpellAbility> spells, SpellAbility sa, String title) {
ApiType api = sa.getApi();
if (null == api) {
throw new InvalidParameterException("SA is not api-based, this is not supported yet");
}
return SpellApiToAi.Converter.get(api).chooseSingleSpellAbility(player, sa, spells);
}
@Override
public boolean confirmAction(SpellAbility sa, PlayerActionConfirmMode mode, String message) {
return getAi().confirmAction(sa, mode, message);
}
@Override
public boolean confirmBidAction(SpellAbility sa, PlayerActionConfirmMode mode, String string,
int bid, Player winner) {
return getAi().confirmBidAction(sa, mode, string, bid, winner);
}
@Override
public boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message) {
return getAi().confirmStaticApplication(hostCard, affected, logic, message);
}
@Override
public boolean confirmTrigger(SpellAbility sa, Trigger regtrig, Map<String, String> triggerParams, boolean isMandatory) {
if (triggerParams.containsKey("DelayedTrigger") || isMandatory) {
//TODO: The only card with an optional delayed trigger is Shirei, Shizo's Caretaker,
// needs to be expanded when a more difficult cards comes up
return true;
}
// Store/replace target choices more properly to get this SA cleared.
TargetChoices tc = null;
TargetChoices subtc = null;
boolean storeChoices = sa.getTargetRestrictions() != null;
final SpellAbility sub = sa.getSubAbility();
boolean storeSubChoices = sub != null && sub.getTargetRestrictions() != null;
boolean ret = true;
if (storeChoices) {
tc = sa.getTargets();
sa.resetTargets();
}
if (storeSubChoices) {
subtc = sub.getTargets();
sub.resetTargets();
}
// There is no way this doTrigger here will have the same target as stored above
// So it's possible it's making a different decision here than will actually happen
if (!brains.doTrigger(sa, false)) {
ret = false;
}
if (storeChoices) {
sa.resetTargets();
sa.setTargets(tc);
}
if (storeSubChoices) {
sub.resetTargets();
sub.setTargets(subtc);
}
return ret;
}
@Override
public Player chooseStartingPlayer(boolean isFirstGame) {
return this.player; // AI is brave :)
}
@Override
public CardCollection orderBlockers(Card attacker, CardCollection blockers) {
return AiBlockController.orderBlockers(attacker, blockers);
}
@Override
public CardCollection orderBlocker(Card attacker, Card blocker, CardCollection oldBlockers) {
return AiBlockController.orderBlocker(attacker, blocker, oldBlockers);
};
@Override
public CardCollection orderAttackers(Card blocker, CardCollection attackers) {
return AiBlockController.orderAttackers(blocker, attackers);
}
@Override
public void reveal(CardCollectionView cards, ZoneType zone, Player owner, String messagePrefix) {
// We don't know how to reveal cards to AI
}
@Override
public ImmutablePair<CardCollection, CardCollection> arrangeForScry(CardCollection topN) {
CardCollection toBottom = new CardCollection();
CardCollection toTop = new CardCollection();
for (Card c: topN) {
if (ComputerUtil.scryWillMoveCardToBottomOfLibrary(player, c)) {
toBottom.add(c);
}
else {
toTop.add(c);
}
}
// put the rest on top in random order
Collections.shuffle(toTop);
return ImmutablePair.of(toTop, toBottom);
}
@Override
public boolean willPutCardOnTop(Card c) {
return true; // AI does not know what will happen next (another clash or that would become his topdeck)
}
@Override
public CardCollectionView orderMoveToZoneList(CardCollectionView cards, ZoneType destinationZone) {
//TODO Add logic for AI ordering here
return cards;
}
@Override
public CardCollection chooseCardsToDiscardFrom(Player p, SpellAbility sa, CardCollection validCards, int min, int max) {
if (p == player) {
return brains.getCardsToDiscard(min, max, validCards, sa);
}
boolean isTargetFriendly = !p.isOpponentOf(player);
return isTargetFriendly
? ComputerUtil.getCardsToDiscardFromFriend(player, p, sa, validCards, min, max)
: ComputerUtil.getCardsToDiscardFromOpponent(player, p, sa, validCards, min, max);
}
@Override
public void playSpellAbilityForFree(SpellAbility copySA, boolean mayChooseNewTargets) {
// Ai is known to set targets in doTrigger, so if it cannot choose new targets, we won't call canPlays
if (mayChooseNewTargets) {
if (copySA instanceof Spell) {
Spell spell = (Spell) copySA;
((PlayerControllerAi) player.getController()).getAi().canPlayFromEffectAI(spell, true, true);
}
else {
getAi().canPlaySa(copySA);
}
}
ComputerUtil.playSpellAbilityForFree(player, copySA);
}
@Override
public void playSpellAbilityNoStack(SpellAbility effectSA, boolean canSetupTargets) {
if (canSetupTargets)
brains.doTrigger(effectSA, true); // first parameter does not matter, since return value won't be used
ComputerUtil.playNoStack(player, effectSA, game);
}
@Override
public void playMiracle(SpellAbility miracle, Card card) {
getAi().chooseAndPlaySa(false, false, miracle);
}
@Override
public CardCollectionView chooseCardsToDelve(int colorlessCost, CardCollection grave) {
return getAi().chooseCardsToDelve(colorlessCost, grave);
}
@Override
public TargetChoices chooseNewTargetsFor(SpellAbility ability) {
// AI currently can't do this. But when it can it will need to be based on Ability API
return null;
}
@Override
public CardCollectionView chooseCardsToDiscardUnlessType(int num, CardCollectionView hand, String uType, SpellAbility sa) {
final CardCollectionView cardsOfType = CardLists.getType(hand, uType);
if (!cardsOfType.isEmpty()) {
Card toDiscard = Aggregates.itemWithMin(cardsOfType, CardPredicates.Accessors.fnGetCmc);
return new CardCollection(toDiscard);
}
return getAi().getCardsToDiscard(num, (String[])null, sa);
}
@Override
public Mana chooseManaFromPool(List<Mana> manaChoices) {
return manaChoices.get(0); // no brains used
}
@Override
public String chooseSomeType(String kindOfType, SpellAbility sa, List<String> validTypes, List<String> invalidTypes, boolean isOptional) {
String chosen = ComputerUtil.chooseSomeType(player, kindOfType, sa.getParam("AILogic"), invalidTypes);
if (StringUtils.isBlank(chosen) && !validTypes.isEmpty())
{
chosen = validTypes.get(0);
Log.warn("AI has no idea how to choose " + kindOfType +", defaulting to 1st element: chosen");
}
game.getAction().nofityOfValue(sa, null, "Computer picked: " + chosen, player);
return chosen;
}
@Override
public Object vote(SpellAbility sa, String prompt, List<Object> options, ArrayListMultimap<Object, Player> votes) {
return ComputerUtil.vote(player, options, sa, votes);
}
@Override
public boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, String question) {
return brains.aiShouldRun(replacementEffect, effectSA);
}
@Override
public CardCollectionView getCardsToMulligan(boolean isCommander, Player firstPlayer) {
if (!ComputerUtil.wantMulligan(player)) {
return null;
}
if (!isCommander) {
return player.getCardsIn(ZoneType.Hand);
}
else {
return ComputerUtil.getPartialParisCandidates(player);
}
}
@Override
public void declareAttackers(Player attacker, Combat combat) {
brains.declareAttackers(attacker, combat);
}
@Override
public void declareBlockers(Player defender, Combat combat) {
brains.declareBlockersFor(defender, combat);
}
@Override
public List<SpellAbility> chooseSpellAbilityToPlay() {
return brains.chooseSpellAbilityToPlay();
}
@Override
public void playChosenSpellAbility(SpellAbility sa) {
// System.out.println("Playing sa: " + sa);
if (sa == Ability.PLAY_LAND_SURROGATE) {
player.playLand(sa.getHostCard(), false);
}
else {
ComputerUtil.handlePlayingSpellAbility(player, sa, game);
}
}
@Override
public CardCollection chooseCardsToDiscardToMaximumHandSize(int numDiscard) {
return brains.getCardsToDiscard(numDiscard, (String[])null, null);
}
@Override
public CardCollection chooseCardsToRevealFromHand(int min, int max, CardCollectionView valid) {
int numCardsToReveal = Math.min(max, valid.size());
return numCardsToReveal == 0 ? new CardCollection() : (CardCollection)valid.subList(0, numCardsToReveal);
}
@Override
public boolean payManaOptional(Card c, Cost cost, SpellAbility sa, String prompt, ManaPaymentPurpose purpose) {
final Ability ability = new AbilityStatic(c, cost, null) { @Override public void resolve() {} };
ability.setActivatingPlayer(c.getController());
if (ComputerUtilCost.canPayCost(ability, c.getController())) {
ComputerUtil.playNoStack(c.getController(), ability, game);
return true;
}
return false;
}
@Override
public List<SpellAbility> chooseSaToActivateFromOpeningHand(List<SpellAbility> usableFromOpeningHand) {
// AI would play everything. But limits to one copy of (Leyline of Singularity) and (Gemstone Caverns)
return brains.chooseSaToActivateFromOpeningHand(usableFromOpeningHand);
}
@Override
public int chooseNumber(SpellAbility sa, String title, int min, int max) {
return brains.chooseNumber(sa, title, min, max);
}
public int chooseNumber(SpellAbility sa, String title, List<Integer> options, Player relatedPlayer) {
return brains.chooseNumber(sa, title, options, relatedPlayer);
}
/* (non-Javadoc)
* @see forge.game.player.PlayerController#chooseFlipResult(forge.Card, forge.game.player.Player, java.lang.String[], boolean)
*/
@Override
public boolean chooseFlipResult(SpellAbility sa, Player flipper, boolean[] results, boolean call) {
if (call) {
// Win if possible
boolean result = false;
for (boolean s : results) {
if (s) {
result = s;
break;
}
}
return result;
} else {
// heads or tails, AI doesn't know which is better now
int i = MyRandom.getRandom().nextInt(results.length);
return results[i];
}
}
@Override
public Pair<SpellAbilityStackInstance, GameObject> chooseTarget(SpellAbility saSrc, List<Pair<SpellAbilityStackInstance, GameObject>> allTargets) {
// TODO Teach AI how to use Spellskite
return allTargets.get(0);
}
@Override
public void notifyOfValue(SpellAbility saSource, GameObject realtedTarget, String value) {
// AI should take into consideration creature types, numbers and other information (mostly choices) arriving through this channel
}
@Override
public boolean chooseBinary(SpellAbility sa, String question, BinaryChoiceType kindOfChoice, Boolean defaultVal) {
switch(kindOfChoice) {
case TapOrUntap: return true;
case UntapOrLeaveTapped: return defaultVal != null && defaultVal.booleanValue();
case UntapTimeVault: return false; // TODO Should AI skip his turn for time vault?
case LeftOrRight: return brains.chooseDirection(sa);
default:
return MyRandom.getRandom().nextBoolean();
}
}
@Override
public Card chooseProtectionShield(GameEntity entityBeingDamaged, List<String> options, Map<String, Card> choiceMap) {
int i = MyRandom.getRandom().nextInt(options.size());
return choiceMap.get(options.get(i));
}
/* (non-Javadoc)
* @see forge.game.player.PlayerController#chooseModeForAbility(forge.card.spellability.SpellAbility, java.util.List, int, int)
*/
@Override
public List<AbilitySub> chooseModeForAbility(SpellAbility sa, int min, int num) {
return CharmAi.chooseOptionsAi(sa, player, sa.isTrigger(), num, min, !player.equals(sa.getActivatingPlayer()));
}
@Override
public Pair<CounterType,String> chooseAndRemoveOrPutCounter(Card cardWithCounter) {
if (!cardWithCounter.hasCounters()) {
System.out.println("chooseCounterType was reached with a card with no counters on it. Consider filtering this card out earlier");
return null;
}
final Player controller = cardWithCounter.getController();
final List<Player> enemies = player.getOpponents();
final List<Player> allies = player.getAllies();
allies.add(player);
List<CounterType> countersToIncrease = new ArrayList<CounterType>();
List<CounterType> countersToDecrease = new ArrayList<CounterType>();
for (final CounterType counter : cardWithCounter.getCounters().keySet()) {
if ((!ComputerUtil.isNegativeCounter(counter, cardWithCounter) && allies.contains(controller))
|| (ComputerUtil.isNegativeCounter(counter, cardWithCounter) && enemies.contains(controller))) {
countersToIncrease.add(counter);
} else {
countersToDecrease.add(counter);
}
}
if (!countersToIncrease.isEmpty()) {
int random = MyRandom.getRandom().nextInt(countersToIncrease.size());
return new ImmutablePair<CounterType,String>(countersToIncrease.get(random),"Put");
}
else if (!countersToDecrease.isEmpty()) {
int random = MyRandom.getRandom().nextInt(countersToDecrease.size());
return new ImmutablePair<CounterType,String>(countersToDecrease.get(random),"Remove");
}
// shouldn't reach here but just in case, remove random counter
List<CounterType> countersOnCard = new ArrayList<CounterType>();
int random = MyRandom.getRandom().nextInt(countersOnCard.size());
return new ImmutablePair<CounterType,String>(countersOnCard.get(random),"Remove");
}
@Override
public byte chooseColorAllowColorless(String message, Card card, ColorSet colors) {
final String c = ComputerUtilCard.getMostProminentColor(player.getCardsIn(ZoneType.Hand));
byte chosenColorMask = MagicColor.fromName(c);
if ((colors.getColor() & chosenColorMask) != 0) {
return chosenColorMask;
} else {
return Iterables.getFirst(colors, (byte)0);
}
}
@Override
public byte chooseColor(String message, SpellAbility sa, ColorSet colors) {
// You may switch on sa.getApi() here and use sa.getParam("AILogic")
CardCollectionView hand = player.getCardsIn(ZoneType.Hand);
if (sa.getApi() == ApiType.Mana) {
hand = CardCollection.combine(hand, player.getCardsIn(ZoneType.Stack));
}
final String c = ComputerUtilCard.getMostProminentColor(hand);
byte chosenColorMask = MagicColor.fromName(c);
if ((colors.getColor() & chosenColorMask) != 0) {
return chosenColorMask;
}
else {
return Iterables.getFirst(colors, MagicColor.WHITE);
}
}
@Override
public PaperCard chooseSinglePaperCard(SpellAbility sa, String message,
Predicate<PaperCard> cpp, String name) {
throw new UnsupportedOperationException("Should not be called for AI"); // or implement it if you know how
}
@Override
public List<String> chooseColors(String message, SpellAbility sa, int min, int max, List<String> options) {
return ComputerUtilCard.chooseColor(sa, min, max, options);
}
@Override
public CounterType chooseCounterType(Collection<CounterType> options, SpellAbility sa, String prompt) {
// may write a smarter AI if you need to (with calls to AI-clas for given API ability)
// TODO: ArsenalNut (06 Feb 12)computer needs
// better logic to pick a counter type and probably
// an initial target
// find first nonzero counter on target
return Iterables.getFirst(options, null);
}
@Override
public boolean confirmPayment(CostPart costPart, String prompt) {
return brains.confirmPayment(costPart); // AI is expected to know what it is paying for at the moment (otherwise add another parameter to this method)
}
@Override
public ReplacementEffect chooseSingleReplacementEffect(String prompt, List<ReplacementEffect> possibleReplacers, HashMap<String, Object> runParams) {
// AI logic for choosing which replacement effect to apply
// happens here.
return possibleReplacers.get(0);
}
@Override
public String chooseProtectionType(String string, SpellAbility sa, List<String> choices) {
String choice = choices.get(0);
if (game.stack.size() > 1) {
for (SpellAbilityStackInstance si : game.getStack()) {
SpellAbility spell = si.getSpellAbility(true);
if (sa != spell) {
String s = ProtectAi.toProtectFrom(spell.getHostCard(), sa);
if (s != null) {
return s;
}
break;
}
}
}
final Combat combat = game.getCombat();
if (combat != null) {
Card toSave = sa.getTargetCard();
CardCollection threats = null;
if (combat.isBlocked(toSave)) {
threats = combat.getBlockers(toSave);
}
if (combat.isBlocking(toSave)) {
threats = combat.getAttackersBlockedBy(toSave);
}
if (threats != null) {
ComputerUtilCard.sortByEvaluateCreature(threats);
String s = ProtectAi.toProtectFrom(threats.get(0), sa);
if (s != null) {
return s;
}
}
}
final PhaseHandler ph = game.getPhaseHandler();
if (ph.getPlayerTurn() == sa.getActivatingPlayer() && ph.getPhase() == PhaseType.MAIN1 && sa.getTargetCard() != null) {
AiAttackController aiAtk = new AiAttackController(sa.getActivatingPlayer(), sa.getTargetCard());
String s = aiAtk.toProtectAttacker(sa);
if (s != null) {
return s;
}
}
final String logic = sa.getParam("AILogic");
if (logic == null || logic.equals("MostProminentHumanCreatures")) {
CardCollection list = new CardCollection();
for (Player opp : player.getOpponents()) {
list.addAll(opp.getCreaturesInPlay());
}
if (list.isEmpty()) {
list = CardLists.filterControlledBy(game.getCardsInGame(), player.getOpponents());
}
if (!list.isEmpty()) {
choice = ComputerUtilCard.getMostProminentColor(list);
}
}
return choice;
}
@Override
public boolean payCostToPreventEffect(Cost cost, SpellAbility sa, boolean alreadyPaid, FCollectionView<Player> allPayers) {
final Card source = sa.getHostCard();
final Ability emptyAbility = new AbilityStatic(source, cost, sa.getTargetRestrictions()) { @Override public void resolve() { } };
emptyAbility.setActivatingPlayer(player);
if (ComputerUtilCost.willPayUnlessCost(sa, player, cost, alreadyPaid, allPayers) && ComputerUtilCost.canPayCost(emptyAbility, player)) {
ComputerUtil.playNoStack(player, emptyAbility, game); // AI needs something to resolve to pay that cost
return true;
}
return false;
}
@Override
public void orderAndPlaySimultaneousSa(List<SpellAbility> activePlayerSAs) {
for (final SpellAbility sa : activePlayerSAs) {
prepareSingleSa(sa.getHostCard(),sa,true);
ComputerUtil.playStack(sa, player, game);
}
}
private void prepareSingleSa(final Card host, final SpellAbility sa, boolean isMandatory){
if (sa.hasParam("TargetingPlayer")) {
Player targetingPlayer = AbilityUtils.getDefinedPlayers(host, sa.getParam("TargetingPlayer"), sa).get(0);
sa.setTargetingPlayer(targetingPlayer);
targetingPlayer.getController().chooseTargetsFor(sa);
} else {
brains.doTrigger(sa, isMandatory);
}
}
@Override
public void playTrigger(Card host, WrappedAbility wrapperAbility, boolean isMandatory) {
prepareSingleSa(host, wrapperAbility, isMandatory);
ComputerUtil.playNoStack(wrapperAbility.getActivatingPlayer(), wrapperAbility, game);
}
@Override
public boolean playSaFromPlayEffect(SpellAbility tgtSA) {
boolean optional = tgtSA.hasParam("Optional");
boolean noManaCost = tgtSA.hasParam("WithoutManaCost");
if (tgtSA instanceof Spell) { // Isn't it ALWAYS a spell?
Spell spell = (Spell) tgtSA;
if (brains.canPlayFromEffectAI(spell, !optional, noManaCost) == AiPlayDecision.WillPlay || !optional) {
if (noManaCost) {
ComputerUtil.playSpellAbilityWithoutPayingManaCost(player, tgtSA, game);
} else {
ComputerUtil.playStack(tgtSA, player, game);
}
} else
return false; // didn't play spell
}
return true;
}
@Override
public Map<GameEntity, CounterType> chooseProliferation() {
return brains.chooseProliferation();
}
@Override
public boolean chooseTargetsFor(SpellAbility currentAbility) {
return brains.doTrigger(currentAbility, true);
}
@Override
public boolean chooseCardsPile(SpellAbility sa, CardCollectionView pile1, CardCollectionView pile2, boolean faceUp) {
if (!faceUp) {
// AI will choose the first pile if it is larger or the same
// TODO Improve this to be slightly more random to not be so predictable
return pile1.size() >= pile2.size();
} else {
boolean allCreatures = Iterables.all(Iterables.concat(pile1, pile2), CardPredicates.Presets.CREATURES);
int cmc1 = allCreatures ? ComputerUtilCard.evaluateCreatureList(pile1) : ComputerUtilCard.evaluatePermanentList(pile1);
int cmc2 = allCreatures ? ComputerUtilCard.evaluateCreatureList(pile2) : ComputerUtilCard.evaluatePermanentList(pile2);
System.out.println("value:" + cmc1 + " " + cmc2);
// for now, this assumes that the outcome will be bad
// TODO: This should really have a ChooseLogic param to
// figure this out
return "Worst".equals(sa.getParam("AILogic")) ^ (cmc1 >= cmc2);
}
}
@Override
public void revealAnte(String message, Multimap<Player, PaperCard> removedAnteCards) {
// Ai won't understand that anyway
}
@Override
public Collection<? extends PaperCard> complainCardsCantPlayWell(Deck myDeck) {
return brains.complainCardsCantPlayWell(myDeck);
}
@Override
public CardCollectionView cheatShuffle(CardCollectionView list) {
return brains.getBooleanProperty(AiProps.CHEAT_WITH_MANA_ON_SHUFFLE) ? brains.cheatShuffle(list) : list;
}
@Override
public CardShields chooseRegenerationShield(Card c) {
return Iterables.getFirst(c.getShields(), null);
}
@Override
public List<PaperCard> chooseCardsYouWonToAddToDeck(List<PaperCard> losses) {
// TODO AI takes all by default
return losses;
}
@Override
public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt /* ai needs hints as well */, boolean isActivatedSa) {
// TODO Auto-generated method stub
ManaCostBeingPaid cost = isActivatedSa ? ComputerUtilMana.calculateManaCost(sa, false, 0) : new ManaCostBeingPaid(toPay);
return ComputerUtilMana.payManaCost(cost, sa, player);
}
@Override
public Map<Card, ManaCostShard> chooseCardsForConvoke(SpellAbility sa, ManaCost manaCost, CardCollectionView untappedCreats0) {
final Player ai = sa.getActivatingPlayer();
final PhaseHandler ph = ai.getGame().getPhaseHandler();
//Filter out mana sources that will interfere with payManaCost()
CardCollection untappedCreats = CardLists.filter(untappedCreats0, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.getManaAbilities().isEmpty();
}
});
//Only convoke after attackers have been declared
if (ph.isPlayerTurn(ai) && ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
return new HashMap<Card, ManaCostShard>();
}
//Do not convoke potential blockers until after opponent's attack
final CardCollectionView blockers = ComputerUtilCard.getLikelyBlockers(ai, null);
if ((ph.isPlayerTurn(ai) && ph.getPhase().isAfter(PhaseType.COMBAT_BEGIN)) ||
(!ph.isPlayerTurn(ai) && ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS))) {
untappedCreats.removeAll((List<?>)blockers);
//Add threatened creatures
if (!ai.getGame().getStack().isEmpty()) {
final List<GameObject> objects = ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), null);
for (Card c : blockers) {
if (objects.contains(c)) {
untappedCreats.add(c);
}
}
}
}
return ComputerUtilMana.getConvokeFromList(manaCost, untappedCreats);
}
@Override
public String chooseCardName(SpellAbility sa, Predicate<PaperCard> cpp, String valid, String message) {
if (sa.hasParam("AILogic")) {
final String logic = sa.getParam("AILogic");
if (logic.equals("MostProminentInComputerDeck")) {
return ComputerUtilCard.getMostProminentCardName(player.getCardsIn(ZoneType.Library));
} else if (logic.equals("MostProminentInHumanDeck")) {
return ComputerUtilCard.getMostProminentCardName(player.getOpponent().getCardsIn(ZoneType.Library));
} else if (logic.equals("MostProminentCreatureInComputerDeck")) {
CardCollectionView cards = CardLists.getValidCards(player.getCardsIn(ZoneType.Library), "Creature", player, sa.getHostCard());
return ComputerUtilCard.getMostProminentCardName(cards);
} else if (logic.equals("BestCreatureInComputerDeck")) {
return ComputerUtilCard.getBestCreatureAI(player.getCardsIn(ZoneType.Library)).getName();
} else if (logic.equals("RandomInComputerDeck")) {
return Aggregates.random(player.getCardsIn(ZoneType.Library)).getName();
} else if (logic.equals("MostProminentSpellInComputerDeck")) {
CardCollectionView cards = CardLists.getValidCards(player.getCardsIn(ZoneType.Library), "Card.Instant,Card.Sorcery", player, sa.getHostCard());
return ComputerUtilCard.getMostProminentCardName(cards);
}
} else {
CardCollectionView list = CardLists.filterControlledBy(game.getCardsInGame(), player.getOpponent());
list = CardLists.filter(list, Predicates.not(Presets.LANDS));
if (!list.isEmpty()) {
return list.get(0).getName();
}
}
return "Morphling";
}
@Override
public Card chooseSingleCardForZoneChange(ZoneType destination,
List<ZoneType> origin, SpellAbility sa, CardCollection fetchList, DelayedReveal delayedReveal,
String selectPrompt, boolean isOptional, Player decider) {
if (delayedReveal != null) {
delayedReveal.reveal(this);
}
return ChangeZoneAi.chooseCardToHiddenOriginChangeZone(destination, origin, sa, fetchList, player, decider);
}
@Override
public void resetAtEndOfTurn() {
// TODO - if card memory is ever used to remember something for longer than a turn, make sure it's not reset here.
getAi().getCardMemory().clearAllRemembered();
}
}

View File

@@ -0,0 +1,178 @@
package forge.ai;
import com.google.common.collect.Iterables;
import forge.game.GameEntity;
import forge.game.ability.SaTargetRoutines;
import forge.game.card.Card;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import java.util.Collection;
import java.util.List;
public abstract class SpellAbilityAi extends SaTargetRoutines {
public final boolean canPlayAIWithSubs(final Player aiPlayer, final SpellAbility sa) {
if (!canPlayAI(aiPlayer, sa)) {
return false;
}
final AbilitySub subAb = sa.getSubAbility();
return subAb == null || chkDrawbackWithSubs(aiPlayer, subAb);
}
protected abstract boolean canPlayAI(final Player aiPlayer, final SpellAbility sa);
public final boolean doTriggerAI(final Player aiPlayer, final SpellAbility sa, final boolean mandatory) {
if (!ComputerUtilCost.canPayCost(sa, aiPlayer) && !mandatory) {
return false;
}
return doTriggerNoCostWithSubs(aiPlayer, sa, mandatory);
}
public final boolean doTriggerNoCostWithSubs(final Player aiPlayer, final SpellAbility sa, final boolean mandatory)
{
if (!doTriggerAINoCost(aiPlayer, sa, mandatory)) {
return false;
}
final AbilitySub subAb = sa.getSubAbility();
return subAb == null || chkDrawbackWithSubs(aiPlayer, subAb) || mandatory;
}
protected boolean doTriggerAINoCost(final Player aiPlayer, final SpellAbility sa, final boolean mandatory) {
if (canPlayAI(aiPlayer, sa)) {
return true;
}
if (mandatory) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Player opp = aiPlayer.getOpponent();
if (tgt != null) {
if (opp.canBeTargetedBy(sa)) {
sa.resetTargets();
sa.getTargets().add(opp);
} else if (mandatory) {
if (aiPlayer.canBeTargetedBy(sa)) {
sa.resetTargets();
sa.getTargets().add(opp);
} else {
return false;
}
} else {
return false;
}
}
return true;
}
return false;
}
public boolean chkAIDrawback(final SpellAbility sa, final Player aiPlayer) {
return true;
}
/**
* <p>
* isSorcerySpeed.
* </p>
*
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @return a boolean.
*/
protected static boolean isSorcerySpeed(final SpellAbility sa) {
return (sa.isSpell() && sa.getHostCard().isSorcery())
|| (sa.isAbility() && sa.getRestrictions().isSorcerySpeed())
|| (sa.getRestrictions().isPwAbility() && !sa.getHostCard().hasKeyword("CARDNAME's loyalty abilities can be activated at instant speed."));
}
/**
* <p>
* playReusable.
* </p>
*
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @return a boolean.
*/
protected static boolean playReusable(final Player ai, final SpellAbility sa) {
// TODO probably also consider if winter orb or similar are out
if (sa.getPayCosts() == null || sa instanceof AbilitySub) {
return true; // This is only true for Drawbacks and triggers
}
if (!sa.getPayCosts().isReusuableResource()) {
return false;
}
if (sa.isTrigger()) {
return true;
}
if (ComputerUtil.playImmediately(ai, sa)) {
return true;
}
if (sa.getRestrictions().isPwAbility() && ai.getGame().getPhaseHandler().is(PhaseType.MAIN2)) {
return true;
}
if (sa.isSpell() && !sa.isBuyBackAbility()) {
return false;
}
PhaseHandler phase = ai.getGame().getPhaseHandler();
return phase.is(PhaseType.END_OF_TURN) && phase.getNextTurn().equals(ai);
}
/**
* TODO: Write javadoc for this method.
* @param ai
* @param subAb
* @return
*/
public boolean chkDrawbackWithSubs(Player aiPlayer, AbilitySub ab) {
final AbilitySub subAb = ab.getSubAbility();
return SpellApiToAi.Converter.get(ab.getApi()).chkAIDrawback(ab, aiPlayer) && (subAb == null || chkDrawbackWithSubs(aiPlayer, subAb));
}
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
System.err.println("Warning: default (ie. inherited from base class) implementation of confirmAction is used for " + this.getClass().getName() + ". Consider declaring an overloaded method");
return true;
}
@SuppressWarnings("unchecked")
public <T extends GameEntity> T chooseSingleEntity(Player ai, SpellAbility sa, Collection<T> options, boolean isOptional, Player targetedPlayer) {
T firstOption = Iterables.getFirst(options, null);
if (firstOption instanceof Card) {
return (T) chooseSingleCard(ai, sa, (Collection<Card>) options, isOptional, targetedPlayer);
}
if (firstOption instanceof Player) {
return (T) chooseSinglePlayer(ai, sa, (Collection<Player>) options);
}
return null;
}
public SpellAbility chooseSingleSpellAbility(Player player, SpellAbility sa, List<SpellAbility> spells) {
System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSingleSpellAbility is used for " + this.getClass().getName() + ". Consider declaring an overloaded method");
return spells.get(0);
}
protected Card chooseSingleCard(Player ai, SpellAbility sa, Iterable<Card> options, boolean isOptional, Player targetedPlayer) {
System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSingleEntity is used for " + this.getClass().getName() + ". Consider declaring an overloaded method");
return Iterables.getFirst(options, null);
}
protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options) {
System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSingleEntity is used for " + this.getClass().getName() + ". Consider declaring an overloaded method");
return Iterables.getFirst(options, null);
}
}

View File

@@ -0,0 +1,162 @@
package forge.ai;
import java.util.EnumMap;
import forge.ai.ability.*;
import forge.game.ability.ApiType;
import forge.util.ReflectionUtil;
public enum SpellApiToAi {
Converter;
private final static EnumMap<ApiType, Class<? extends SpellAbilityAi>> apiToClass = new EnumMap<>(ApiType.class);
private final EnumMap<ApiType, SpellAbilityAi> apiToInstance = new EnumMap<>(ApiType.class);
static {
apiToClass.put(ApiType.Abandon, AlwaysPlayAi.class);
apiToClass.put(ApiType.ActivateAbility, ActivateAbilityAi.class);
apiToClass.put(ApiType.AddOrRemoveCounter, CountersPutOrRemoveAi.class);
apiToClass.put(ApiType.AddPhase, AddPhaseAi.class);
apiToClass.put(ApiType.AddTurn, AddTurnAi.class);
apiToClass.put(ApiType.Animate, AnimateAi.class);
apiToClass.put(ApiType.AnimateAll, AnimateAllAi.class);
apiToClass.put(ApiType.Attach, AttachAi.class);
apiToClass.put(ApiType.Balance, BalanceAi.class);
apiToClass.put(ApiType.BecomesBlocked, BecomesBlockedAi.class);
apiToClass.put(ApiType.BidLife, BidLifeAi.class);
apiToClass.put(ApiType.Bond, BondAi.class);
apiToClass.put(ApiType.ChangeTargets, ChangeTargetsAi.class);
apiToClass.put(ApiType.ChangeZone, ChangeZoneAi.class);
apiToClass.put(ApiType.ChangeZoneAll, ChangeZoneAllAi.class);
apiToClass.put(ApiType.Charm, CharmAi.class);
apiToClass.put(ApiType.ChooseCard, ChooseCardAi.class);
apiToClass.put(ApiType.ChooseColor, ChooseColorAi.class);
apiToClass.put(ApiType.ChooseDirection, ChooseDirectionAi.class);
apiToClass.put(ApiType.ChooseNumber, ChooseNumberAi.class);
apiToClass.put(ApiType.ChoosePlayer, ChoosePlayerAi.class);
apiToClass.put(ApiType.ChooseSource, ChooseSourceAi.class);
apiToClass.put(ApiType.ChooseType, ChooseTypeAi.class);
apiToClass.put(ApiType.Clash, ClashAi.class);
apiToClass.put(ApiType.Cleanup, AlwaysPlayAi.class);
apiToClass.put(ApiType.Clone, CloneAi.class);
apiToClass.put(ApiType.CopyPermanent, CopyPermanentAi.class);
apiToClass.put(ApiType.CopySpellAbility, CanPlayAsDrawbackAi.class);
apiToClass.put(ApiType.ControlPlayer, CannotPlayAi.class);
apiToClass.put(ApiType.ControlSpell, CannotPlayAi.class);
apiToClass.put(ApiType.Counter, CounterAi.class);
apiToClass.put(ApiType.DamageAll, DamageAllAi.class);
apiToClass.put(ApiType.DealDamage, DamageDealAi.class);
apiToClass.put(ApiType.Debuff, DebuffAi.class);
apiToClass.put(ApiType.DeclareCombatants, CannotPlayAi.class);
apiToClass.put(ApiType.DelayedTrigger, DelayedTriggerAi.class);
apiToClass.put(ApiType.Destroy, DestroyAi.class);
apiToClass.put(ApiType.DestroyAll, DestroyAllAi.class);
apiToClass.put(ApiType.Dig, DigAi.class);
apiToClass.put(ApiType.DigUntil, DigUntilAi.class);
apiToClass.put(ApiType.Discard, DiscardAi.class);
apiToClass.put(ApiType.DrainMana, DrainManaAi.class);
apiToClass.put(ApiType.Draw, DrawAi.class);
apiToClass.put(ApiType.EachDamage, DamageEachAi.class);
apiToClass.put(ApiType.Effect, EffectAi.class);
apiToClass.put(ApiType.Encode, EncodeAi.class);
apiToClass.put(ApiType.EndTurn, EndTurnAi.class);
apiToClass.put(ApiType.ExchangeLife, LifeExchangeAi.class);
apiToClass.put(ApiType.ExchangeControl, ControlExchangeAi.class);
apiToClass.put(ApiType.ExchangeControlVariant, CannotPlayAi.class);
apiToClass.put(ApiType.ExchangePower, PowerExchangeAi.class);
apiToClass.put(ApiType.ExchangeZone, ZoneExchangeAi.class);
apiToClass.put(ApiType.Fight, FightAi.class);
apiToClass.put(ApiType.FlipACoin, FlipACoinAi.class);
apiToClass.put(ApiType.Fog, FogAi.class);
apiToClass.put(ApiType.GainControl, ControlGainAi.class);
apiToClass.put(ApiType.GainLife, LifeGainAi.class);
apiToClass.put(ApiType.GainOwnership, CannotPlayAi.class);
apiToClass.put(ApiType.GenericChoice, ChooseGenericEffectAi.class);
apiToClass.put(ApiType.LoseLife, LifeLoseAi.class);
apiToClass.put(ApiType.LosesGame, GameLossAi.class);
apiToClass.put(ApiType.Mana, ManaEffectAi.class);
apiToClass.put(ApiType.ManaReflected, CannotPlayAi.class);
apiToClass.put(ApiType.Manifest, ManifestAi.class);
apiToClass.put(ApiType.Mill, MillAi.class);
apiToClass.put(ApiType.MoveCounter, CountersMoveAi.class);
apiToClass.put(ApiType.MultiplePiles, CannotPlayAi.class);
apiToClass.put(ApiType.MustAttack, MustAttackAi.class);
apiToClass.put(ApiType.MustBlock, MustBlockAi.class);
apiToClass.put(ApiType.NameCard, ChooseCardNameAi.class);
apiToClass.put(ApiType.PeekAndReveal, PeekAndRevealAi.class);
apiToClass.put(ApiType.PermanentCreature, PermanentCreatureAi.class);
apiToClass.put(ApiType.PermanentNoncreature, PermanentNoncreatureAi.class);
apiToClass.put(ApiType.Phases, PhasesAi.class);
apiToClass.put(ApiType.Planeswalk, AlwaysPlayAi.class);
apiToClass.put(ApiType.Play, PlayAi.class);
apiToClass.put(ApiType.PlayLandVariant, CannotPlayAi.class);
apiToClass.put(ApiType.Poison, PoisonAi.class);
apiToClass.put(ApiType.PreventDamage, DamagePreventAi.class);
apiToClass.put(ApiType.PreventDamageAll, DamagePreventAllAi.class);
apiToClass.put(ApiType.Proliferate, CountersProliferateAi.class);
apiToClass.put(ApiType.Protection, ProtectAi.class);
apiToClass.put(ApiType.ProtectionAll, ProtectAllAi.class);
apiToClass.put(ApiType.Pump, PumpAi.class);
apiToClass.put(ApiType.PumpAll, PumpAllAi.class);
apiToClass.put(ApiType.PutCounter, CountersPutAi.class);
apiToClass.put(ApiType.PutCounterAll, CountersPutAllAi.class);
apiToClass.put(ApiType.RearrangeTopOfLibrary, RearrangeTopOfLibraryAi.class);
apiToClass.put(ApiType.Regenerate, RegenerateAi.class);
apiToClass.put(ApiType.RegenerateAll, RegenerateAllAi.class);
apiToClass.put(ApiType.RemoveCounter, CountersRemoveAi.class);
apiToClass.put(ApiType.RemoveCounterAll, CannotPlayAi.class);
apiToClass.put(ApiType.RemoveFromCombat, RemoveFromCombatAi.class);
apiToClass.put(ApiType.ReorderZone, AlwaysPlayAi.class);
apiToClass.put(ApiType.Repeat, RepeatAi.class);
apiToClass.put(ApiType.RepeatEach, RepeatEachAi.class);
apiToClass.put(ApiType.RestartGame, RestartGameAi.class);
apiToClass.put(ApiType.Reveal, RevealAi.class);
apiToClass.put(ApiType.RevealHand, RevealHandAi.class);
apiToClass.put(ApiType.ReverseTurnOrder, AlwaysPlayAi.class);
apiToClass.put(ApiType.RollPlanarDice, RollPlanarDiceAi.class);
apiToClass.put(ApiType.RunSVarAbility, AlwaysPlayAi.class);
apiToClass.put(ApiType.Sacrifice, SacrificeAi.class);
apiToClass.put(ApiType.SacrificeAll, SacrificeAllAi.class);
apiToClass.put(ApiType.Scry, ScryAi.class);
apiToClass.put(ApiType.SetInMotion, AlwaysPlayAi.class);
apiToClass.put(ApiType.SetLife, LifeSetAi.class);
apiToClass.put(ApiType.SetState, SetStateAi.class);
apiToClass.put(ApiType.Shuffle, ShuffleAi.class);
apiToClass.put(ApiType.SkipTurn, SkipTurnAi.class);
apiToClass.put(ApiType.StoreMap, StoreMapAi.class);
apiToClass.put(ApiType.StoreSVar, StoreSVarAi.class);
apiToClass.put(ApiType.Tap, TapAi.class);
apiToClass.put(ApiType.TapAll, TapAllAi.class);
apiToClass.put(ApiType.TapOrUntap, TapOrUntapAi.class);
apiToClass.put(ApiType.TapOrUntapAll, TapOrUntapAllAi.class);
apiToClass.put(ApiType.Token, TokenAi.class);
apiToClass.put(ApiType.TwoPiles, TwoPilesAi.class);
apiToClass.put(ApiType.Unattach, CannotPlayAi.class);
apiToClass.put(ApiType.UnattachAll, UnattachAllAi.class);
apiToClass.put(ApiType.Untap, UntapAi.class);
apiToClass.put(ApiType.UntapAll, UntapAllAi.class);
apiToClass.put(ApiType.Vote, VoteAi.class);
apiToClass.put(ApiType.WinsGame, GameWinAi.class);
apiToClass.put(ApiType.InternalEtbReplacement, CanPlayAsDrawbackAi.class);
apiToClass.put(ApiType.InternalLegendaryRule, LegendaryRuleAi.class);
apiToClass.put(ApiType.InternalHaunt, HauntAi.class);
apiToClass.put(ApiType.InternalIgnoreEffect, CannotPlayAi.class);
}
public SpellAbilityAi get(ApiType api) {
SpellAbilityAi result = apiToInstance.get(api);
if( null == result ) {
Class<? extends SpellAbilityAi> clz = apiToClass.get(api);
if(null == clz) {
System.err.println("No AI assigned for API: " + api);
clz = CannotPlayAi.class;
}
result = ReflectionUtil.makeDefaultInstanceOf(clz);
apiToInstance.put(api, result);
}
return result;
}
}

View File

@@ -0,0 +1,100 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class ActivateAbilityAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
// AI cannot use this properly until he can use SAs during Humans turn
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
final Player opp = ai.getOpponent();
final Random r = MyRandom.getRandom();
boolean randomReturn = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
List<Card> list = CardLists.getType(opp.getCardsIn(ZoneType.Battlefield), sa.getParamOrDefault("Type", "Card"));
if (list.isEmpty()) {
return false;
}
if (tgt == null) {
final List<Player> defined = AbilityUtils.getDefinedPlayers(source, sa.getParam("Defined"), sa);
if (!defined.contains(opp)) {
return false;
}
} else {
sa.resetTargets();
sa.getTargets().add(opp);
}
return randomReturn;
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final Player opp = ai.getOpponent();
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
if (null == tgt) {
if (mandatory) {
return true;
} else {
final List<Player> defined = AbilityUtils.getDefinedPlayers(source, sa.getParam("Defined"), sa);
if (!defined.contains(opp)) {
return false;
}
}
return true;
} else {
sa.resetTargets();
sa.getTargets().add(opp);
}
return true;
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
// AI cannot use this properly until he can use SAs during Humans turn
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
boolean randomReturn = true;
if (tgt == null) {
final List<Player> defined = AbilityUtils.getDefinedPlayers(source, sa.getParam("Defined"), sa);
if (defined.contains(ai)) {
return false;
}
} else {
sa.resetTargets();
sa.getTargets().add(ai.getOpponent());
}
return randomReturn;
}
@Override
public SpellAbility chooseSingleSpellAbility(Player player, SpellAbility sa, List<SpellAbility> spells) {
return spells.get(0);
}
}

View File

@@ -0,0 +1,18 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
/**
* TODO: Write javadoc for this type.
*
*/
public class AddPhaseAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
return false;
}
}

View File

@@ -0,0 +1,86 @@
/*
* 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.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
/**
* <p>
* AbilityFactory_Turns class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class AddTurnAi extends SpellAbilityAi {
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final Player opp = ai.getWeakestOpponent();
if (sa.usesTargeting()) {
sa.resetTargets();
if (sa.canTarget(ai)) {
sa.getTargets().add(ai);
} else if (mandatory) {
for (final Player ally : ai.getAllies()) {
if (sa.canTarget(ally)) {
sa.getTargets().add(ally);
break;
}
}
if (!sa.getTargetRestrictions().isMinTargetsChosen(sa.getHostCard(), sa) && sa.canTarget(opp)) {
sa.getTargets().add(opp);
} else {
return false;
}
}
} else {
final List<Player> tgtPlayers = AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Defined"), sa);
for (final Player p : tgtPlayers) {
if (p.isOpponentOf(ai) && !mandatory) {
return false;
}
}
if (!StringUtils.isNumeric(sa.getParam("NumTurns"))) {
// TODO: improve ai for Sage of Hours
return false;
}
// not sure if the AI should be playing with cards that give the
// Human more turns.
}
return true;
}
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
return doTriggerAINoCost(aiPlayer, sa, false);
}
}

View File

@@ -0,0 +1,16 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
public class AlwaysPlayAi extends SpellAbilityAi {
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
return true;
}
}

View File

@@ -0,0 +1,508 @@
package forge.ai.ability;
import com.google.common.collect.Iterables;
import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCost;
import forge.ai.SpellAbilityAi;
import forge.card.CardType;
import forge.game.Game;
import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardFactory;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CardUtil;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.replacement.ReplacementEffect;
import forge.game.replacement.ReplacementHandler;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.staticability.StaticAbility;
import forge.game.staticability.StaticAbilityContinuous;
import forge.game.staticability.StaticAbilityLayer;
import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerHandler;
import forge.game.zone.ZoneType;
import forge.util.FCollectionView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* <p>
* AbilityFactoryAnimate class.
* </p>
*
* @author Forge
* @version $Id: AbilityFactoryAnimate.java 17608 2012-10-20 22:27:27Z Max mtg $
*/
public class AnimateAi extends SpellAbilityAi {
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
final Game game = aiPlayer.getGame();
final PhaseHandler ph = game.getPhaseHandler();
// TODO - add some kind of check to answer
// "Am I going to attack with this?"
// TODO - add some kind of check for during human turn to answer
// "Can I use this to block something?"
//interrupt sacrifice effect
if (!game.getStack().isEmpty()) {
SpellAbility topStack = game.getStack().peekAbility();
if (topStack.getApi() == ApiType.Sacrifice) {
final String valid = topStack.getParamOrDefault("SacValid", "Card.Self");
String num = topStack.getParam("Amount");
num = (num == null) ? "1" : num;
final int nToSac = AbilityUtils.calculateAmount(topStack.getHostCard(), num, topStack);
CardCollection list =
CardLists.getValidCards(aiPlayer.getCardsIn(ZoneType.Battlefield), valid.split(","), aiPlayer.getOpponent(), topStack.getHostCard());
list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(topStack));
ComputerUtilCard.sortByEvaluateCreature(list);
if (!list.isEmpty() && list.size() == nToSac && ComputerUtilCost.canPayCost(sa, aiPlayer)) {
Card animatedCopy = CardFactory.copyCard(source, true);
becomeAnimated(animatedCopy, source.hasSickness(), sa);
list.add(animatedCopy);
list = CardLists.getValidCards(list, valid.split(","), aiPlayer.getOpponent(), topStack.getHostCard());
list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(topStack));
if (ComputerUtilCard.evaluateCreature(animatedCopy) < ComputerUtilCard.evaluateCreature(list.get(0))
&& list.contains(animatedCopy)) {
return true;
}
}
}
}
// Launch the Fleet (why is this an Animate ability?)
if (sa.hasParam("AILogic") && "Attacking".equals(sa.getParam("AILogic"))) {
if (ph.getPlayerTurn().isOpponentOf(aiPlayer) || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
return false;
}
List<Card> list = CardLists.getValidCards(aiPlayer.getCreaturesInPlay(), tgt.getValidTgts(), aiPlayer, source);
for (Card c : list) {
if (ComputerUtilCard.doesCreatureAttackAI(aiPlayer, c)) {
sa.getTargets().add(c);
}
}
return !sa.getTargets().isEmpty();
}
// don't use instant speed animate abilities outside computers
// Combat_Begin step
if (!ph.is(PhaseType.COMBAT_BEGIN)
&& ph.isPlayerTurn(aiPlayer)
&& !SpellAbilityAi.isSorcerySpeed(sa)
&& !sa.hasParam("ActivationPhases") && !sa.hasParam("Permanent")) {
return false;
}
Player opponent = aiPlayer.getWeakestOpponent();
// don't animate if the AI won't attack anyway
if (ph.isPlayerTurn(aiPlayer)
&& aiPlayer.getLife() < 6
&& opponent.getLife() > 6
&& Iterables.any(opponent.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES)
&& !sa.hasParam("AILogic")) {
return false;
}
// don't use instant speed animate abilities outside humans
// Combat_Declare_Attackers_InstantAbility step
if (ph.getPlayerTurn().isOpponentOf(aiPlayer) &&
(!ph.is(PhaseType.COMBAT_DECLARE_ATTACKERS, opponent) || game.getCombat() != null && game.getCombat().getAttackersOf(aiPlayer).isEmpty())) {
return false;
}
// don't activate during main2 unless this effect is permanent
if (ph.is(PhaseType.MAIN2) && !sa.hasParam("Permanent") && !sa.hasParam("UntilYourNextTurn")) {
return false;
}
if (null == tgt) {
final List<Card> defined = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa);
boolean bFlag = false;
if (sa.hasParam("AILogic")) {
if ("EOT".equals(sa.getParam("AILogic"))) {
if (ph.getPhase().isBefore(PhaseType.MAIN2)) {
return false;
} else {
bFlag = true;
}
} if ("Never".equals(sa.getParam("AILogic"))) {
return false;
}
} else {
boolean givesHaste = sa.hasParam("Keywords") && sa.getParam("Keywords").contains("Haste");
for (final Card c : defined) {
bFlag |= !c.isCreature() && !c.isTapped()
&& (c.getTurnInZone() != ph.getTurn() || givesHaste || ph.getPlayerTurn().isOpponentOf(aiPlayer))
&& !c.isEquipping();
// for creatures that could be improved (like Figure of Destiny)
if (!bFlag && c.isCreature() && (sa.hasParam("Permanent") || (!c.isTapped() && !c.isSick()))) {
int power = -5;
if (sa.hasParam("Power")) {
power = AbilityUtils.calculateAmount(source, sa.getParam("Power"), sa);
}
int toughness = -5;
if (sa.hasParam("Toughness")) {
toughness = AbilityUtils.calculateAmount(source, sa.getParam("Toughness"), sa);
}
if ((power + toughness) > (c.getCurrentPower() + c.getCurrentToughness())) {
bFlag = true;
}
}
if (!SpellAbilityAi.isSorcerySpeed(sa)) {
Card animatedCopy = CardFactory.getCard(c.getPaperCard(), aiPlayer, c.getGame());
AnimateAi.becomeAnimated(animatedCopy, c.hasSickness(), sa);
if (ph.isPlayerTurn(aiPlayer) && !ComputerUtilCard.doesSpecifiedCreatureAttackAI(aiPlayer, animatedCopy)) {
return false;
}
if (ph.getPlayerTurn().isOpponentOf(aiPlayer) && !ComputerUtilCard.doesSpecifiedCreatureBlock(aiPlayer, animatedCopy)) {
return false;
}
}
}
}
if (!bFlag) { // All of the defined stuff is animated, not very
// useful
return false;
}
} else {
sa.resetTargets();
if (!animateTgtAI(sa)) {
return false;
}
}
return true;
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player aiPlayer) {
if (sa.usesTargeting()) {
sa.resetTargets();
if (!animateTgtAI(sa)) {
return false;
}
}
return true;
}
@Override
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
if (sa.usesTargeting() && !animateTgtAI(sa) && !mandatory) {
return false;
}
// Improve AI for triggers. If source is a creature with:
// When ETB, sacrifice a creature. Check to see if the AI has something
// to sacrifice
// Eventually, we can call the trigger of ETB abilities with
// not mandatory as part of the checks to cast something
if (sa.hasParam("AITgts")) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card animateSource = sa.getHostCard();
CardCollectionView list = aiPlayer.getGame().getCardsIn(tgt.getZone());
list = CardLists.getValidCards(list, tgt.getValidTgts(), sa.getActivatingPlayer(), animateSource);
CardCollection prefList = CardLists.getValidCards(list, sa.getParam("AITgts"), sa.getActivatingPlayer(), animateSource);
if (!prefList.isEmpty()){
CardLists.shuffle(prefList);
sa.getTargets().add(prefList.getFirst());
}
}
return true;
}
private boolean animateTgtAI(final SpellAbility sa) {
// This is reasonable for now. Kamahl, Fist of Krosa and a sorcery or
// two are the only things
// that animate a target. Those can just use SVar:RemAIDeck:True until
// this can do a reasonably
// good job of picking a good target
return false;
}
public static void becomeAnimated(final Card card, final boolean hasOriginalCardSickness, final SpellAbility sa) {
//duplicating AnimateEffect.resolve
final Card source = sa.getHostCard();
final Game game = sa.getActivatingPlayer().getGame();
final Map<String, String> svars = source.getSVars();
final long timestamp = game.getNextTimestamp();
card.setSickness(hasOriginalCardSickness);
// AF specific sa
int power = -1;
if (sa.hasParam("Power")) {
power = AbilityUtils.calculateAmount(source, sa.getParam("Power"), sa);
}
int toughness = -1;
if (sa.hasParam("Toughness")) {
toughness = AbilityUtils.calculateAmount(source, sa.getParam("Toughness"), sa);
}
final CardType types = new CardType();
if (sa.hasParam("Types")) {
types.addAll(Arrays.asList(sa.getParam("Types").split(",")));
}
final CardType removeTypes = new CardType();
if (sa.hasParam("RemoveTypes")) {
removeTypes.addAll(Arrays.asList(sa.getParam("RemoveTypes").split(",")));
}
// allow ChosenType - overrides anything else specified
if (types.hasSubtype("ChosenType")) {
types.clear();
types.add(source.getChosenType());
}
final ArrayList<String> keywords = new ArrayList<String>();
if (sa.hasParam("Keywords")) {
keywords.addAll(Arrays.asList(sa.getParam("Keywords").split(" & ")));
}
final ArrayList<String> removeKeywords = new ArrayList<String>();
if (sa.hasParam("RemoveKeywords")) {
removeKeywords.addAll(Arrays.asList(sa.getParam("RemoveKeywords").split(" & ")));
}
final ArrayList<String> hiddenKeywords = new ArrayList<String>();
if (sa.hasParam("HiddenKeywords")) {
hiddenKeywords.addAll(Arrays.asList(sa.getParam("HiddenKeywords").split(" & ")));
}
// allow SVar substitution for keywords
for (int i = 0; i < keywords.size(); i++) {
final String k = keywords.get(i);
if (svars.containsKey(k)) {
keywords.add(svars.get(k));
keywords.remove(k);
}
}
// colors to be added or changed to
String tmpDesc = "";
if (sa.hasParam("Colors")) {
final String colors = sa.getParam("Colors");
if (colors.equals("ChosenColor")) {
tmpDesc = CardUtil.getShortColorsString(source.getChosenColors());
}
else {
tmpDesc = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(","))));
}
}
final String finalDesc = tmpDesc;
// abilities to add to the animated being
final ArrayList<String> abilities = new ArrayList<String>();
if (sa.hasParam("Abilities")) {
abilities.addAll(Arrays.asList(sa.getParam("Abilities").split(",")));
}
// replacement effects to add to the animated being
final ArrayList<String> replacements = new ArrayList<String>();
if (sa.hasParam("Replacements")) {
replacements.addAll(Arrays.asList(sa.getParam("Replacements").split(",")));
}
// triggers to add to the animated being
final ArrayList<String> triggers = new ArrayList<String>();
if (sa.hasParam("Triggers")) {
triggers.addAll(Arrays.asList(sa.getParam("Triggers").split(",")));
}
// static abilities to add to the animated being
final ArrayList<String> stAbs = new ArrayList<String>();
if (sa.hasParam("staticAbilities")) {
stAbs.addAll(Arrays.asList(sa.getParam("staticAbilities").split(",")));
}
// sVars to add to the animated being
final ArrayList<String> sVars = new ArrayList<String>();
if (sa.hasParam("sVars")) {
sVars.addAll(Arrays.asList(sa.getParam("sVars").split(",")));
}
//duplicating AnimateEffectBase.doAnimate
boolean removeSuperTypes = false;
boolean removeCardTypes = false;
boolean removeSubTypes = false;
boolean removeCreatureTypes = false;
if (sa.hasParam("OverwriteTypes")) {
removeSuperTypes = true;
removeCardTypes = true;
removeSubTypes = true;
removeCreatureTypes = true;
}
if (sa.hasParam("KeepSupertypes")) {
removeSuperTypes = false;
}
if (sa.hasParam("KeepCardTypes")) {
removeCardTypes = false;
}
if (sa.hasParam("RemoveSuperTypes")) {
removeSuperTypes = true;
}
if (sa.hasParam("RemoveCardTypes")) {
removeCardTypes = true;
}
if (sa.hasParam("RemoveSubTypes")) {
removeSubTypes = true;
}
if (sa.hasParam("RemoveCreatureTypes")) {
removeCreatureTypes = true;
}
if ((power != -1) || (toughness != -1)) {
card.addNewPT(power, toughness, timestamp);
}
if (!types.isEmpty() || !removeTypes.isEmpty() || removeCreatureTypes) {
card.addChangedCardTypes(types, removeTypes, removeSuperTypes, removeCardTypes, removeSubTypes,
removeCreatureTypes, timestamp);
}
card.addChangedCardKeywords(keywords, removeKeywords, sa.hasParam("RemoveAllAbilities"), timestamp);
for (final String k : hiddenKeywords) {
card.addHiddenExtrinsicKeyword(k);
}
card.addColor(finalDesc, !sa.hasParam("OverwriteColors"), timestamp);
//back to duplicating AnimateEffect.resolve
//TODO will all these abilities/triggers/replacements/etc. lead to memory leaks or unintended effects?
// remove abilities
final ArrayList<SpellAbility> removedAbilities = new ArrayList<SpellAbility>();
boolean clearAbilities = sa.hasParam("OverwriteAbilities");
boolean clearSpells = sa.hasParam("OverwriteSpells");
boolean removeAll = sa.hasParam("RemoveAllAbilities");
if (clearAbilities || clearSpells || removeAll) {
for (final SpellAbility ab : card.getSpellAbilities()) {
if (removeAll || (ab.isAbility() && clearAbilities)
|| (ab.isSpell() && clearSpells)) {
card.removeSpellAbility(ab);
removedAbilities.add(ab);
}
}
}
// give abilities
final ArrayList<SpellAbility> addedAbilities = new ArrayList<SpellAbility>();
if (abilities.size() > 0) {
for (final String s : abilities) {
final String actualAbility = source.getSVar(s);
final SpellAbility grantedAbility = AbilityFactory.getAbility(actualAbility, source);
addedAbilities.add(grantedAbility);
card.addSpellAbility(grantedAbility);
}
}
// Grant triggers
final ArrayList<Trigger> addedTriggers = new ArrayList<Trigger>();
if (triggers.size() > 0) {
for (final String s : triggers) {
final String actualTrigger = source.getSVar(s);
final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, source, false);
addedTriggers.add(card.addTrigger(parsedTrigger));
}
}
// give replacement effects
final ArrayList<ReplacementEffect> addedReplacements = new ArrayList<ReplacementEffect>();
if (replacements.size() > 0) {
for (final String s : replacements) {
final String actualReplacement = source.getSVar(s);
final ReplacementEffect parsedReplacement = ReplacementHandler.parseReplacement(actualReplacement, source, false);
addedReplacements.add(card.addReplacementEffect(parsedReplacement));
}
}
// suppress triggers from the animated card
final ArrayList<Trigger> removedTriggers = new ArrayList<Trigger>();
if (sa.hasParam("OverwriteTriggers") || removeAll) {
final FCollectionView<Trigger> triggersToRemove = card.getTriggers();
for (final Trigger trigger : triggersToRemove) {
trigger.setSuppressed(true);
removedTriggers.add(trigger);
}
}
// give static abilities (should only be used by cards to give
// itself a static ability)
if (stAbs.size() > 0) {
for (final String s : stAbs) {
final String actualAbility = source.getSVar(s);
final StaticAbility stAb = card.addStaticAbility(actualAbility);
if ("Continuous".equals(stAb.getMapParams().get("Mode"))) {
for (final StaticAbilityLayer layer : stAb.getLayers()) {
StaticAbilityContinuous.applyContinuousAbility(stAb, new CardCollection(card), layer);
}
}
}
}
// give sVars
if (sVars.size() > 0) {
for (final String s : sVars) {
String actualsVar = source.getSVar(s);
String name = s;
if (actualsVar.startsWith("SVar:")) {
actualsVar = actualsVar.split("SVar:")[1];
name = actualsVar.split(":")[0];
actualsVar = actualsVar.split(":")[1];
}
card.setSVar(name, actualsVar);
}
}
// suppress static abilities from the animated card
final ArrayList<StaticAbility> removedStatics = new ArrayList<StaticAbility>();
if (sa.hasParam("OverwriteStatics") || removeAll) {
final FCollectionView<StaticAbility> staticsToRemove = card.getStaticAbilities();
for (final StaticAbility stAb : staticsToRemove) {
stAb.setTemporarilySuppressed(true);
removedStatics.add(stAb);
}
}
// suppress static abilities from the animated card
final ArrayList<ReplacementEffect> removedReplacements = new ArrayList<ReplacementEffect>();
if (sa.hasParam("OverwriteReplacements") || removeAll) {
for (final ReplacementEffect re : card.getReplacementEffects()) {
re.setTemporarilySuppressed(true);
removedReplacements.add(re);
}
}
ComputerUtilCard.applyStaticContPT(game, card, null);
}
}

View File

@@ -0,0 +1,19 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
public class AnimateAllAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
return false;
} // end animateAllCanPlayAI()
@Override
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
return false;
}
} // end class AbilityFactoryAnimate

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
public class BalanceAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
String logic = sa.getParam("AILogic");
int diff = 0;
// TODO Add support for multiplayer logic
final Player opp = aiPlayer.getOpponent();
final CardCollectionView humPerms = opp.getCardsIn(ZoneType.Battlefield);
final CardCollectionView compPerms = aiPlayer.getCardsIn(ZoneType.Battlefield);
if ("BalanceCreaturesAndLands".equals(logic)) {
// Copied over from hardcoded Balance. We should be checking value of the lands/creatures not just counting
diff += CardLists.filter(humPerms, CardPredicates.Presets.LANDS).size() -
CardLists.filter(compPerms, CardPredicates.Presets.LANDS).size();
diff += 1.5 * ( CardLists.filter(humPerms, CardPredicates.Presets.CREATURES).size() -
CardLists.filter(compPerms, CardPredicates.Presets.CREATURES).size());
}
else if ("BalancePermanents".equals(logic)) {
// Don't cast if you have to sacrifice permanents
diff += humPerms.size() - compPerms.size();
}
if (diff < 0) {
// Don't sacrifice permanents even if opponent has a ton of cards in hand
return false;
}
final CardCollectionView humHand = opp.getCardsIn(ZoneType.Hand);
final CardCollectionView compHand = aiPlayer.getCardsIn(ZoneType.Hand);
diff += 0.5 * (humHand.size() - compHand.size());
// Larger differential == more chance to actually cast this spell
return diff > 2 && MyRandom.getRandom().nextInt(100) < diff*10;
}
}

View File

@@ -0,0 +1,70 @@
package forge.ai.ability;
import forge.ai.ComputerUtilCard;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
public class BecomesBlockedAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
final Card source = sa.getHostCard();
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Game game = aiPlayer.getGame();
if (!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)
|| !game.getPhaseHandler().getPlayerTurn().isOpponentOf(aiPlayer)) {
return false;
}
if (tgt != null) {
sa.resetTargets();
CardCollection list = CardLists.filterControlledBy(game.getCardsIn(ZoneType.Battlefield), aiPlayer.getOpponents());
list = CardLists.getValidCards(list, tgt.getValidTgts(), source.getController(), source);
list = CardLists.getTargetableCards(list, sa);
list = CardLists.getNotKeyword(list, "Trample");
while (sa.getTargets().getNumTargeted() < tgt.getMaxTargets(source, sa)) {
Card choice = null;
if (list.isEmpty()) {
return false;
}
choice = ComputerUtilCard.getBestCreatureAI(list);
if (choice == null) { // can't find anything left
return false;
}
list.remove(choice);
sa.getTargets().add(choice);
}
}
return true;
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player aiPlayer) {
// TODO - implement AI
return false;
}
@Override
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
boolean chance;
// TODO - implement AI
chance = false;
return chance;
}
}

View File

@@ -0,0 +1,57 @@
package forge.ai.ability;
import java.util.List;
import forge.ai.ComputerUtilCard;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardLists;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
public class BidLifeAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
final Card source = sa.getHostCard();
final Game game = source.getGame();
TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
sa.resetTargets();
if (tgt.canTgtCreature()) {
List<Card> list = CardLists.getTargetableCards(aiPlayer.getOpponent().getCardsIn(ZoneType.Battlefield), sa);
list = CardLists.getValidCards(list, tgt.getValidTgts(), source.getController(), source);
if (list.isEmpty()) {
return false;
}
Card c = ComputerUtilCard.getBestCreatureAI(list);
if (sa.canTarget(c)) {
sa.getTargets().add(c);
} else {
return false;
}
} else if (tgt.getZone().contains(ZoneType.Stack)) {
if (game.getStack().isEmpty()) {
return false;
}
final SpellAbility topSA = game.getStack().peekAbility();
if (!CardFactoryUtil.isCounterableBy(topSA.getHostCard(), sa) || aiPlayer.equals(topSA.getActivatingPlayer())) {
return false;
}
if (sa.canTargetSpellAbility(topSA)) {
sa.getTargets().add(topSA);
} else {
return false;
}
}
}
boolean chance = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
return chance;
}
}

View File

@@ -0,0 +1,56 @@
/*
* 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.ai.ability;
import forge.ai.ComputerUtilCard;
import forge.ai.SpellAbilityAi;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
/**
* <p>
* AbilityFactoryBond class.
* </p>
*
* @author Forge
* @version $Id: AbilityFactoryBond.java 15090 2012-04-07 12:50:31Z Max mtg $
*/
public final class BondAi extends SpellAbilityAi {
/**
* <p>
* bondCanPlayAI.
* </p>
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @param af
* a {@link forge.game.ability.AbilityFactory} object.
*
* @return a boolean.
*/
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
return true;
} // end bondCanPlayAI()
@Override
protected Card chooseSingleCard(Player ai, SpellAbility sa, Iterable<Card> options, boolean isOptional, Player targetedPlayer) {
return ComputerUtilCard.getBestCreatureAI(options);
}
}

View File

@@ -0,0 +1,44 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import java.util.List;
public class CanPlayAsDrawbackAi extends SpellAbilityAi {
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
return false;
}
/**
* <p>
* copySpellTriggerAI.
* </p>
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @param mandatory
* a boolean.
* @param af
* a {@link forge.game.ability.AbilityFactory} object.
*
* @return a boolean.
*/
@Override
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
return false;
}
@Override
public SpellAbility chooseSingleSpellAbility(Player player, SpellAbility sa, List<SpellAbility> spells) {
// This might be called from CopySpellAbilityEffect - to hide warning (for having no overload) use this simple overload
return spells.get(0);
}
}

View File

@@ -1,9 +1,9 @@
package forge.card.ability.ai;
package forge.ai.ability;
import forge.card.ability.SpellAbilityAi;
import forge.card.spellability.SpellAbility;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
public class CannotPlayAi extends SpellAbilityAi {
/* (non-Javadoc)

View File

@@ -0,0 +1,26 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
public class ChangeTargetsAi extends SpellAbilityAi {
/*
* (non-Javadoc)
*
* @see
* forge.card.abilityfactory.AbilityFactoryAlterLife.SpellAiLogic#canPlayAI
* (forge.game.player.Player, java.util.Map,
* forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
return false;
}
@Override
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
return true;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,34 +1,31 @@
package forge.card.ability.ai;
package forge.ai.ability;
import java.util.List;
import java.util.Random;
import forge.Card;
import forge.CardLists;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi;
import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost;
import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCost;
import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.cost.Cost;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
public class ChangeZoneAllAi extends SpellAbilityAi {
import java.util.Random;
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
*/
public class ChangeZoneAllAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
// Change Zone All, can be any type moving from one zone to another
final Cost abCost = sa.getPayCosts();
final Card source = sa.getSourceCard();
final Card source = sa.getHostCard();
final ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination"));
final ZoneType origin = ZoneType.smartValueOf(sa.getParam("Origin"));
final ZoneType origin = ZoneType.listValueOf(sa.getParam("Origin")).get(0);
if (abCost != null) {
// AI currently disabled for these costs
@@ -39,7 +36,6 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
return false;
}
}
final Random r = MyRandom.getRandom();
@@ -54,10 +50,10 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
// ex. "Return all blocking/blocked by target creature"
final Player opp = ai.getOpponent();
final List<Card> humanType = AbilityUtils.filterListByType(opp.getCardsIn(origin), sa.getParam("ChangeType"), sa);
List<Card> computerType = ai.getCardsIn(origin);
final CardCollectionView humanType = AbilityUtils.filterListByType(opp.getCardsIn(origin), sa.getParam("ChangeType"), sa);
CardCollectionView computerType = ai.getCardsIn(origin);
computerType = AbilityUtils.filterListByType(computerType, sa.getParam("ChangeType"), sa);
final Target tgt = sa.getTarget();
final TargetRestrictions tgt = sa.getTargetRestrictions();
// TODO improve restrictions on when the AI would want to use this
// spBounceAll has some AI we can compare to.
@@ -67,8 +63,8 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|| !opp.canBeTargetedBy(sa)) {
return false;
}
tgt.resetTargets();
tgt.addTarget(opp);
sa.resetTargets();
sa.getTargets().add(opp);
}
} else if (origin.equals(ZoneType.Battlefield)) {
// this statement is assuming the AI is trying to use this spell
@@ -82,9 +78,9 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|| !opp.canBeTargetedBy(sa)) {
return false;
}
tgt.resetTargets();
tgt.addTarget(opp);
computerType.clear();
sa.resetTargets();
sa.getTargets().add(opp);
computerType = new CardCollection();
}
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
if ((ComputerUtilCard.evaluateCreatureList(computerType) + 200) >= ComputerUtilCard
@@ -108,8 +104,8 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|| !opp.canBeTargetedBy(sa)) {
return false;
}
tgt.resetTargets();
tgt.addTarget(opp);
sa.resetTargets();
sa.getTargets().add(opp);
}
} else if (origin.equals(ZoneType.Exile)) {
@@ -159,9 +155,9 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
* changeZoneAllPlayDrawbackAI.
* </p>
* @param sa
* a {@link forge.card.spellability.SpellAbility} object.
* a {@link forge.game.spellability.SpellAbility} object.
* @param af
* a {@link forge.card.ability.AbilityFactory} object.
* a {@link forge.game.ability.AbilityFactory} object.
*
* @return a boolean.
*/
@@ -182,21 +178,21 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
final ZoneType origin = ZoneType.smartValueOf(sa.getParam("Origin"));
final Player opp = ai.getOpponent();
final List<Card> humanType = AbilityUtils.filterListByType(opp.getCardsIn(origin), sa.getParam("ChangeType"), sa);
List<Card> computerType = ai.getCardsIn(origin);
final CardCollectionView humanType = AbilityUtils.filterListByType(opp.getCardsIn(origin), sa.getParam("ChangeType"), sa);
CardCollectionView computerType = ai.getCardsIn(origin);
computerType = AbilityUtils.filterListByType(computerType, sa.getParam("ChangeType"), sa);
// TODO improve restrictions on when the AI would want to use this
// spBounceAll has some AI we can compare to.
if (origin.equals(ZoneType.Hand) || origin.equals(ZoneType.Library)) {
final Target tgt = sa.getTarget();
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
if (opp.getCardsIn(ZoneType.Hand).isEmpty()
|| !opp.canBeTargetedBy(sa)) {
return false;
}
tgt.resetTargets();
tgt.addTarget(opp);
sa.resetTargets();
sa.getTargets().add(opp);
}
} else if (origin.equals(ZoneType.Battlefield)) {
// this statement is assuming the AI is trying to use this spell offensively
@@ -215,14 +211,14 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
return false;
}
} else if (origin.equals(ZoneType.Graveyard)) {
final Target tgt = sa.getTarget();
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
if (opp.getCardsIn(ZoneType.Graveyard).isEmpty()
|| !opp.canBeTargetedBy(sa)) {
return false;
}
tgt.resetTargets();
tgt.addTarget(opp);
sa.resetTargets();
sa.getTargets().add(opp);
}
} else if (origin.equals(ZoneType.Exile)) {

View File

@@ -0,0 +1,99 @@
package forge.ai.ability;
import forge.ai.AiController;
import forge.ai.AiPlayDecision;
import forge.ai.PlayerControllerAi;
import forge.ai.SpellAbilityAi;
import forge.game.ability.effects.CharmEffect;
import forge.game.player.Player;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.util.Aggregates;
import forge.util.MyRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class CharmAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Random r = MyRandom.getRandom();
final int num = Integer.parseInt(sa.hasParam("CharmNum") ? sa.getParam("CharmNum") : "1");
final int min = sa.hasParam("MinCharmNum") ? Integer.parseInt(sa.getParam("MinCharmNum")) : num;
boolean timingRight = sa.isTrigger(); //is there a reason to play the charm now?
// reset the chosen list. Otherwise it will be locked in forever
sa.setChosenList(null);
List<AbilitySub> chosenList = chooseOptionsAi(sa, ai, timingRight, num, min, false);
if (chosenList.isEmpty()) {
return false;
} else {
sa.setChosenList(chosenList);
}
// prevent run-away activations - first time will always return true
return r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
}
public static List<AbilitySub> chooseOptionsAi(SpellAbility sa, final Player ai, boolean playNow, int num, int min, boolean opponentChoser) {
if (sa.getChosenList() != null) {
return sa.getChosenList();
}
List<AbilitySub> choices = CharmEffect.makePossibleOptions(sa);
List<AbilitySub> chosenList = new ArrayList<AbilitySub>();
if (opponentChoser) {
// This branch is for "An Opponent chooses" Charm spells from Alliances
// Current just choose the first available spell, which seem generally less disastrous for the AI.
//return choices.subList(0, 1);
return choices.subList(1, choices.size());
}
AiController aic = ((PlayerControllerAi) ai.getController()).getAi();
for (int i = 0; i < num; i++) {
AbilitySub thisPick = null;
for (SpellAbility sub : choices) {
sub.setActivatingPlayer(ai);
if (!playNow && AiPlayDecision.WillPlay == aic.canPlaySa(sub)) {
thisPick = (AbilitySub) sub;
choices.remove(sub);
playNow = true;
break;
}
if ((playNow || i < num - 1) && aic.doTrigger(sub, false)) {
thisPick = (AbilitySub) sub;
choices.remove(sub);
break;
}
}
if (thisPick != null) {
chosenList.add(thisPick);
}
}
if (playNow && chosenList.size() < min) {
for (int i = 0; i < min; i++) {
AbilitySub thisPick = null;
for (SpellAbility sub : choices) {
sub.setActivatingPlayer(ai);
if (aic.doTrigger(sub, true)) {
thisPick = (AbilitySub) sub;
choices.remove(sub);
break;
}
}
if (thisPick != null) {
chosenList.add(thisPick);
}
}
}
return chosenList;
}
@Override
public Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> opponents) {
return Aggregates.random(opponents);
}
}

View File

@@ -0,0 +1,236 @@
package forge.ai.ability;
import com.google.common.base.Predicate;
import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCombat;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates.Presets;
import forge.game.card.CounterType;
import forge.game.combat.Combat;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.Aggregates;
import java.util.Collections;
public class ChooseCardAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(final Player ai, SpellAbility sa) {
final Card host = sa.getHostCard();
final Game game = ai.getGame();
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
sa.resetTargets();
if (sa.canTarget(ai.getOpponent())) {
sa.getTargets().add(ai.getOpponent());
} else {
return false;
}
}
if (sa.hasParam("AILogic")) {
ZoneType choiceZone = ZoneType.Battlefield;
String logic = sa.getParam("AILogic");
if (sa.hasParam("ChoiceZone")) {
choiceZone = ZoneType.smartValueOf(sa.getParam("ChoiceZone"));
}
CardCollectionView choices = ai.getGame().getCardsIn(choiceZone);
if (sa.hasParam("Choices")) {
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), host.getController(), host);
}
if (sa.hasParam("TargetControls")) {
choices = CardLists.filterControlledBy(choices, ai.getOpponent());
}
if (logic.equals("AtLeast1") || logic.equals("OppPreferred")) {
if (choices.isEmpty()) {
return false;
}
} else if (logic.equals("AtLeast2") || logic.equals("BestBlocker")) {
if (choices.size() < 2) {
return false;
}
} else if (logic.equals("Clone")) {
choices = CardLists.getValidCards(choices, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host);
if (choices.isEmpty()) {
return false;
}
} else if (logic.equals("Never")) {
return false;
} else if (logic.equals("NeedsPrevention")) {
if (!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
return false;
}
final Combat combat = game.getCombat();
choices = CardLists.filter(choices, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
if (!combat.isAttacking(c, ai) || !combat.isUnblocked(c)) {
return false;
}
int ref = host.getName().equals("Forcefield") ? 1 : 0;
return ComputerUtilCombat.damageIfUnblocked(c, ai, combat, true) > ref;
}
});
if (choices.isEmpty()) {
return false;
}
} else if (logic.equals("Ashiok")) {
final int loyalty = host.getCounters(CounterType.LOYALTY) - 1;
for (int i = loyalty; i >= 0; i--) {
host.setSVar("ChosenX", "Number$" + i);
choices = ai.getGame().getCardsIn(choiceZone);
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), host.getController(), host);
if (!choices.isEmpty()) {
return true;
}
}
if (choices.isEmpty()) {
return false;
}
} else if (logic.equals("RandomNonLand")) {
if (CardLists.getValidCards(choices, "Card.nonLand", host.getController(), host).isEmpty()) {
return false;
}
} else if (logic.equals("Duneblast")) {
CardCollection aiCreatures = ai.getCreaturesInPlay();
CardCollection oppCreatures = ai.getOpponent().getCreaturesInPlay();
aiCreatures = CardLists.getNotKeyword(aiCreatures, "Indestructible");
oppCreatures = CardLists.getNotKeyword(oppCreatures, "Indestructible");
// Use it as a wrath, when the human creatures threat the ai's life
if (aiCreatures.isEmpty() && ComputerUtilCombat.sumDamageIfUnblocked(oppCreatures, ai) >= ai.getLife()) {
return true;
}
Card chosen = ComputerUtilCard.getBestCreatureAI(aiCreatures);
aiCreatures.remove(chosen);
int minGain = 200;
if ((ComputerUtilCard.evaluateCreatureList(aiCreatures) + minGain) >= ComputerUtilCard
.evaluateCreatureList(oppCreatures)) {
return false;
}
}
}
return true;
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
return canPlayAI(ai, sa);
}
/* (non-Javadoc)
* @see forge.card.ability.SpellAbilityAi#chooseSingleCard(forge.card.spellability.SpellAbility, java.util.List, boolean)
*/
@Override
public Card chooseSingleCard(final Player ai, SpellAbility sa, Iterable<Card> options, boolean isOptional, Player targetedPlayer) {
final Card host = sa.getHostCard();
final String logic = sa.getParam("AILogic");
Card choice = null;
if (logic == null) {
// Base Logic is choose "best"
choice = ComputerUtilCard.getBestAI(options);
} else if ("WorstCard".equals(logic)) {
choice = ComputerUtilCard.getWorstAI(options);
} else if (logic.equals("BestBlocker")) {
if (!CardLists.filter(options, Presets.UNTAPPED).isEmpty()) {
options = CardLists.filter(options, Presets.UNTAPPED);
}
choice = ComputerUtilCard.getBestCreatureAI(options);
} else if (logic.equals("Clone")) {
if (!CardLists.getValidCards(options, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host).isEmpty()) {
options = CardLists.getValidCards(options, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host);
}
choice = ComputerUtilCard.getBestAI(options);
} else if ("RandomNonLand".equals(logic)) {
options = CardLists.getValidCards(options, "Card.nonLand", host.getController(), host);
choice = Aggregates.random(options);
} else if (logic.equals("Untap")) {
if (!CardLists.getValidCards(options, "Permanent.YouCtrl,Permanent.tapped", host.getController(), host).isEmpty()) {
options = CardLists.getValidCards(options, "Permanent.YouCtrl,Permanent.tapped", host.getController(), host);
}
choice = ComputerUtilCard.getBestAI(options);
} else if (logic.equals("NeedsPrevention")) {
final Game game = ai.getGame();
final Combat combat = game.getCombat();
CardCollectionView better = CardLists.filter(options, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
if (combat == null || !combat.isAttacking(c, ai) || !combat.isUnblocked(c)) {
return false;
}
int ref = host.getName().equals("Forcefield") ? 1 : 0;
return ComputerUtilCombat.damageIfUnblocked(c, ai, combat, true) > ref;
}
});
if (!better.isEmpty()) {
choice = ComputerUtilCard.getBestAI(better);
} else {
choice = ComputerUtilCard.getBestAI(options);
}
} else if ("OppPreferred".equals(logic)) {
CardCollectionView oppControlled = CardLists.filterControlledBy(options, ai.getOpponents());
if (!oppControlled.isEmpty()) {
choice = ComputerUtilCard.getBestAI(oppControlled);
} else {
CardCollectionView aiControlled = CardLists.filterControlledBy(options, ai);
choice = ComputerUtilCard.getWorstAI(aiControlled);
}
} else if ("LowestCMCCreature".equals(logic)) {
CardCollection creats = CardLists.filter(options, Presets.CREATURES);
creats = CardLists.filterToughness(creats, 1);
if (creats.isEmpty()) {
choice = ComputerUtilCard.getWorstAI(options);
} else {
CardLists.sortByCmcDesc(creats);
Collections.reverse(creats);
choice = creats.get(0);
}
} else if ("TangleWire".equals(logic)) {
CardCollectionView betterList = CardLists.filter(options, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
if (c.isCreature()) {
return false;
}
for (SpellAbility sa : c.getAllSpellAbilities()) {
if (sa.getPayCosts() != null && sa.getPayCosts().hasTapCost()) {
return false;
}
}
return true;
}
});
System.out.println("Tangle Wire" + options + " - " + betterList);
if (!betterList.isEmpty()) {
choice = betterList.get(0);
} else {
choice = ComputerUtilCard.getWorstPermanentAI(options, false, false, false, false);
}
} else if (logic.equals("Duneblast")) {
CardCollectionView aiCreatures = ai.getCreaturesInPlay();
aiCreatures = CardLists.getNotKeyword(aiCreatures, "Indestructible");
if (aiCreatures.isEmpty()) {
return null;
}
Card chosen = ComputerUtilCard.getBestCreatureAI(aiCreatures);
return chosen;
} else {
choice = ComputerUtilCard.getBestAI(options);
}
return choice;
}
}

View File

@@ -0,0 +1,63 @@
package forge.ai.ability;
import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilMana;
import forge.ai.SpellAbilityAi;
import forge.game.card.Card;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
public class ChooseCardNameAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
Card source = sa.getHostCard();
if (sa.hasParam("AILogic")) {
// Don't tap creatures that may be able to block
if (ComputerUtil.waitForBlocking(sa)) {
return false;
}
String logic = sa.getParam("AILogic");
if (logic.equals("MomirAvatar")) {
if (source.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN1)) {
return false;
}
// Set PayX here to maximum value.
int tokenSize = ComputerUtilMana.determineLeftoverMana(sa, ai);
// Some basic strategy for Momir
if (tokenSize < 2) {
return false;
}
if (tokenSize > 11) {
tokenSize = 11;
}
source.setSVar("PayX", Integer.toString(tokenSize));
}
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
sa.resetTargets();
if (tgt.canOnlyTgtOpponent()) {
sa.getTargets().add(ai.getOpponent());
} else {
sa.getTargets().add(ai);
}
}
return true;
}
return false;
}
@Override
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
// TODO - there is no AILogic implemented yet
return false;
}
}

View File

@@ -0,0 +1,79 @@
package forge.ai.ability;
import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilMana;
import forge.ai.SpellAbilityAi;
import forge.card.MagicColor;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
public class ChooseColorAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Card source = sa.getHostCard();
final Game game = ai.getGame();
if (!sa.hasParam("AILogic")) {
return false;
}
final String logic = sa.getParam("AILogic");
if (ComputerUtil.preventRunAwayActivations(sa)) {
return false;
}
if ("Oona, Queen of the Fae".equals(sa.getHostCard().getName())) {
PhaseHandler ph = game.getPhaseHandler();
if (ph.isPlayerTurn(ai) || ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
return false;
}
// Set PayX here to maximum value.
int x = ComputerUtilMana.determineLeftoverMana(sa, ai);
source.setSVar("PayX", Integer.toString(x));
return true;
}
if ("Addle".equals(sa.getHostCard().getName())) {
PhaseHandler ph = game.getPhaseHandler();
if (ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) || ai.getOpponent().getCardsIn(ZoneType.Hand).isEmpty()) {
return false;
}
return true;
}
if (logic.equals("MostExcessOpponentControls")) {
for (byte color : MagicColor.WUBRG) {
CardCollectionView ailist = ai.getCardsIn(ZoneType.Battlefield);
CardCollectionView opplist = ai.getOpponent().getCardsIn(ZoneType.Battlefield);
ailist = CardLists.filter(ailist, CardPredicates.isColor(color));
opplist = CardLists.filter(opplist, CardPredicates.isColor(color));
int excess = ComputerUtilCard.evaluatePermanentList(opplist) - ComputerUtilCard.evaluatePermanentList(ailist);
if (excess > 4) {
return true;
}
}
return false;
}
boolean chance = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
return chance;
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
return mandatory || canPlayAI(ai, sa);
}
}

View File

@@ -0,0 +1,32 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
public class ChooseDirectionAi extends SpellAbilityAi {
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final String logic = sa.getParam("AILogic");
if (logic == null) {
return false;
} else {
// TODO: default ai
}
return true;
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
return canPlayAI(ai, sa);
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
return canPlayAI(ai, sa);
}
}

View File

@@ -0,0 +1,66 @@
package forge.ai.ability;
import forge.ai.ComputerUtilCost;
import forge.ai.SpellAbilityAi;
import forge.game.cost.Cost;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.util.Aggregates;
import forge.util.FCollection;
import java.util.List;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
/**
* TODO: Write javadoc for this type.
*
*/
public class ChooseGenericEffectAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
return false;
}
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#chkAIDrawback(java.util.Map, forge.card.spellability.SpellAbility, forge.game.player.Player)
*/
@Override
public boolean chkAIDrawback(SpellAbility sa, Player aiPlayer) {
return canPlayAI(aiPlayer, sa);
}
@Override
public SpellAbility chooseSingleSpellAbility(Player player, SpellAbility sa, List<SpellAbility> spells) {
final String logic = sa.getParam("AILogic");
if ("Random".equals(logic)) {
return Aggregates.random(spells);
} else if ("Phasing".equals(logic)) { // Teferi's Realm : keep aggressive
List<SpellAbility> filtered = Lists.newArrayList(Iterables.filter(spells, new Predicate<SpellAbility>() {
@Override
public boolean apply(final SpellAbility sp) {
return !sp.getDescription().contains("Creature") && !sp.getDescription().contains("Land");
}
}));
return Aggregates.random(filtered);
} else if ("PayUnlessCost".equals(logic)) {
for (final SpellAbility sp : spells) {
String unlessCost = sp.getParam("UnlessCost");
sp.setActivatingPlayer(sa.getActivatingPlayer());
Cost unless = new Cost(unlessCost, false);
SpellAbility paycost = new SpellAbility.EmptySa(sa.getHostCard(), player);
paycost.setPayCosts(unless);
if (ComputerUtilCost.willPayUnlessCost(sp, player, unless, false, new FCollection<Player>(player))
&& ComputerUtilCost.canPayCost(paycost, player)) {
return sp;
}
}
return spells.get(0);
} else {
return spells.get(0);
}
}
}

View File

@@ -0,0 +1,34 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom;
public class ChooseNumberAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
if (!sa.hasParam("AILogic")) {
return false;
}
TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
sa.resetTargets();
if (sa.canTarget(aiPlayer.getOpponent())) {
sa.getTargets().add(aiPlayer.getOpponent());
} else {
return false;
}
}
boolean chance = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
return chance;
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
return mandatory || canPlayAI(ai, sa);
}
}

View File

@@ -0,0 +1,81 @@
package forge.ai.ability;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.ai.ComputerUtil;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import java.util.List;
public class ChoosePlayerAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
return true;
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
return canPlayAI(ai, sa);
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
return canPlayAI(ai, sa);
}
@Override
public Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> choices) {
Player chosen = null;
if ("Curse".equals(sa.getParam("AILogic"))) {
for (Player pc : choices) {
if (pc.isOpponentOf(ai)) {
chosen = pc;
break;
}
}
if (chosen == null) {
chosen = Iterables.getFirst(choices, null);
System.out.println("No good curse choices. Picking first available: " + chosen);
}
}
else if ("Pump".equals(sa.getParam("AILogic"))) {
chosen = Iterables.contains(choices, ai) ? ai : Iterables.getFirst(choices, null);
}
else if ("BestAllyBoardPosition".equals(sa.getParam("AILogic"))) {
List<Player> prefChoices = Lists.newArrayList(choices);
prefChoices.removeAll(ai.getOpponents());
if (!prefChoices.isEmpty()) {
chosen = ComputerUtil.evaluateBoardPosition(prefChoices);
}
if (chosen == null) {
chosen = Iterables.getFirst(choices, null);
System.out.println("No good curse choices. Picking first available: " + chosen);
}
} else if ("MostCardsInHand".equals(sa.getParam("AILogic"))) {
int cardsInHand = 0;
for (final Player p : choices) {
int hand = p.getCardsIn(ZoneType.Hand).size();
if (hand >= cardsInHand) {
chosen = p;
cardsInHand = hand;
}
}
} else if ("LeastCreatures".equals(sa.getParam("AILogic"))) {
int creats = 50;
for (final Player p : choices) {
int curr = p.getCreaturesInPlay().size();
if (curr <= creats) {
chosen = p;
creats = curr;
}
}
} else {
System.out.println("Default player choice logic.");
chosen = Iterables.contains(choices, ai) ? ai : Iterables.getFirst(choices, null);
}
return chosen;
}
}

View File

@@ -0,0 +1,187 @@
package forge.ai.ability;
import com.google.common.base.Predicate;
import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCombat;
import forge.ai.ComputerUtilCost;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.GameObject;
import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.card.Card;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.combat.Combat;
import forge.game.cost.Cost;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import java.util.List;
public class ChooseSourceAi extends SpellAbilityAi {
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(final Player ai, SpellAbility sa) {
// TODO: AI Support! Currently this is copied from AF ChooseCard.
// When implementing AI, I believe AI also needs to be made aware of the damage sources chosen
// to be prevented (e.g. so the AI doesn't attack with a creature that will not deal any damage
// to the player because a CoP was pre-activated on it - unless, of course, there's another
// possible reason to attack with that creature).
final Card host = sa.getHostCard();
final Cost abCost = sa.getPayCosts();
final Card source = sa.getHostCard();
if (abCost != null) {
// AI currently disabled for these costs
if (!ComputerUtilCost.checkLifeCost(ai, abCost, source, 4, null)) {
return false;
}
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
return false;
}
if (!ComputerUtilCost.checkSacrificeCost(ai, abCost, source)) {
return false;
}
if (!ComputerUtilCost.checkRemoveCounterCost(abCost, source)) {
return false;
}
}
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
sa.resetTargets();
if (sa.canTarget(ai.getOpponent())) {
sa.getTargets().add(ai.getOpponent());
} else {
return false;
}
}
if (sa.hasParam("AILogic")) {
final Game game = ai.getGame();
if (sa.getParam("AILogic").equals("NeedsPrevention")) {
if (!game.getStack().isEmpty()) {
final SpellAbility topStack = game.getStack().peekAbility();
if (sa.hasParam("Choices") && !topStack.getHostCard().isValid(sa.getParam("Choices"), ai, source)) {
return false;
}
final ApiType threatApi = topStack.getApi();
if (threatApi != ApiType.DealDamage && threatApi != ApiType.DamageAll) {
return false;
}
final Card threatSource = topStack.getHostCard();
List<? extends GameObject> objects = getTargets(topStack);
if (!topStack.usesTargeting() && topStack.hasParam("ValidPlayers") && !topStack.hasParam("Defined")) {
objects = AbilityUtils.getDefinedPlayers(threatSource, topStack.getParam("ValidPlayers"), topStack);
}
if (!objects.contains(ai) || topStack.hasParam("NoPrevention")) {
return false;
}
int dmg = AbilityUtils.calculateAmount(threatSource, topStack.getParam("NumDmg"), topStack);
if (ComputerUtilCombat.predictDamageTo(ai, dmg, threatSource, false) <= 0) {
return false;
}
return true;
}
if (game.getPhaseHandler().getPhase() != PhaseType.COMBAT_DECLARE_BLOCKERS) {
return false;
}
CardCollectionView choices = game.getCardsIn(ZoneType.Battlefield);
if (sa.hasParam("Choices")) {
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), host.getController(), host);
}
final Combat combat = game.getCombat();
choices = CardLists.filter(choices, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
if (combat == null || !combat.isAttacking(c, ai) || !combat.isUnblocked(c)) {
return false;
}
return ComputerUtilCombat.damageIfUnblocked(c, ai, combat, true) > 0;
}
});
if (choices.isEmpty()) {
return false;
}
}
}
return true;
}
@Override
public Card chooseSingleCard(final Player aiChoser, SpellAbility sa, Iterable<Card> options, boolean isOptional, Player targetedPlayer) {
if ("NeedsPrevention".equals(sa.getParam("AILogic"))) {
final Player ai = sa.getActivatingPlayer();
final Game game = ai.getGame();
if (!game.getStack().isEmpty()) {
Card choseCard = chooseCardOnStack(sa, ai, game);
if (choseCard != null) {
return choseCard;
}
}
final Combat combat = game.getCombat();
List<Card> permanentSources = CardLists.filter(options, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
if (c == null || c.getZone() == null || c.getZone().getZoneType() != ZoneType.Battlefield
|| combat == null || !combat.isAttacking(c, ai) || !combat.isUnblocked(c)) {
return false;
}
return ComputerUtilCombat.damageIfUnblocked(c, ai, combat, true) > 0;
}
});
return ComputerUtilCard.getBestCreatureAI(permanentSources);
} else {
return ComputerUtilCard.getBestAI(options);
}
}
private Card chooseCardOnStack(SpellAbility sa, Player ai, Game game) {
for (SpellAbilityStackInstance si : game.getStack()) {
final Card source = si.getSourceCard();
final SpellAbility abilityOnStack = si.getSpellAbility(true);
if (sa.hasParam("Choices") && !abilityOnStack.getHostCard().isValid(sa.getParam("Choices"), ai, sa.getHostCard())) {
continue;
}
final ApiType threatApi = abilityOnStack.getApi();
if (threatApi != ApiType.DealDamage && threatApi != ApiType.DamageAll) {
continue;
}
List<? extends GameObject> objects = getTargets(abilityOnStack);
if (!abilityOnStack.usesTargeting() && !abilityOnStack.hasParam("Defined") && abilityOnStack.hasParam("ValidPlayers"))
objects = AbilityUtils.getDefinedPlayers(source, abilityOnStack.getParam("ValidPlayers"), abilityOnStack);
if (!objects.contains(ai) || abilityOnStack.hasParam("NoPrevention")) {
continue;
}
int dmg = AbilityUtils.calculateAmount(source, abilityOnStack.getParam("NumDmg"), abilityOnStack);
if (ComputerUtilCombat.predictDamageTo(ai, dmg, source, false) <= 0) {
continue;
}
return source;
}
return null;
}
}

View File

@@ -0,0 +1,33 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
public class ChooseTypeAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
if (!sa.hasParam("AILogic")) {
return false;
}
return doTriggerAINoCost(aiPlayer, sa, false);
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
if (sa.usesTargeting()) {
sa.resetTargets();
sa.getTargets().add(ai);
} else {
for (final Player p : AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Defined"), sa)) {
if (p.isOpponentOf(ai) && !mandatory) {
return false;
}
}
}
return true;
}
}

View File

@@ -0,0 +1,36 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
public class ClashAi extends SpellAbilityAi {
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#doTriggerAINoCost(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility, boolean)
*/
@Override
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
return true;
}
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Player opp = ai.getOpponent();
if (tgt != null) {
if (!sa.canTarget(opp)) {
return false;
}
sa.resetTargets();
sa.getTargets().add(opp);
}
return true;
}
}

View File

@@ -1,23 +1,24 @@
package forge.card.ability.ai;
package forge.ai.ability;
import java.util.List;
import forge.Card;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import java.util.List;
public class CloneAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Target tgt = sa.getTarget();
final Card source = sa.getSourceCard();
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
final Game game = source.getGame();
boolean useAbility = true;
@@ -45,9 +46,7 @@ public class CloneAi extends SpellAbilityAi {
// don't use instant speed clone abilities outside humans
// Combat_Declare_Attackers_InstantAbility step
if ((!phase.is(PhaseType.COMBAT_DECLARE_ATTACKERS)
|| game.getCombat().getAttackers().isEmpty())
&& !phase.isPlayerTurn(ai)) {
if (!phase.is(PhaseType.COMBAT_DECLARE_ATTACKERS) || phase.isPlayerTurn(ai) || game.getCombat().getAttackers().isEmpty()) {
return false;
}
@@ -85,7 +84,7 @@ public class CloneAi extends SpellAbilityAi {
return false;
}
} else {
tgt.resetTargets();
sa.resetTargets();
useAbility &= cloneTgtAI(sa);
}
@@ -97,7 +96,7 @@ public class CloneAi extends SpellAbilityAi {
// AI should only activate this during Human's turn
boolean chance = true;
if (sa.getTarget() != null) {
if (sa.usesTargeting()) {
chance = cloneTgtAI(sa);
}
@@ -110,7 +109,7 @@ public class CloneAi extends SpellAbilityAi {
boolean chance = true;
if (sa.getTarget() != null) {
if (sa.usesTargeting()) {
chance = cloneTgtAI(sa);
}
@@ -130,9 +129,9 @@ public class CloneAi extends SpellAbilityAi {
* </p>
*
* @param af
* a {@link forge.card.ability.AbilityFactory} object.
* a {@link forge.game.ability.AbilityFactory} object.
* @param sa
* a {@link forge.card.spellability.SpellAbility} object.
* a {@link forge.game.spellability.SpellAbility} object.
* @return a boolean.
*/
private boolean cloneTgtAI(final SpellAbility sa) {
@@ -143,5 +142,14 @@ public class CloneAi extends SpellAbilityAi {
// good job of picking a good target
return false;
}
/* (non-Javadoc)
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.game.player.Player, forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
*/
@Override
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
// Didn't confirm in the original code
return false;
}
}

View File

@@ -0,0 +1,88 @@
package forge.ai.ability;
import com.google.common.base.Predicate;
import forge.ai.ComputerUtilCard;
import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.List;
import java.util.Map;
public class ControlExchangeAi extends SpellAbilityAi {
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player ai, final SpellAbility sa) {
Card object1 = null;
Card object2 = null;
final TargetRestrictions tgt = sa.getTargetRestrictions();
sa.resetTargets();
List<Card> list =
CardLists.getValidCards(ai.getOpponent().getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, sa.getHostCard());
// AI won't try to grab cards that are filtered out of AI decks on
// purpose
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
final Map<String, String> vars = c.getSVars();
return !vars.containsKey("RemAIDeck") && c.canBeTargetedBy(sa);
}
});
object1 = ComputerUtilCard.getBestAI(list);
if (sa.hasParam("Defined")) {
object2 = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa).get(0);
} else if (tgt.getMinTargets(sa.getHostCard(), sa) > 1) {
CardCollectionView list2 = ai.getCardsIn(ZoneType.Battlefield);
list2 = CardLists.getValidCards(list2, tgt.getValidTgts(), ai, sa.getHostCard());
object2 = ComputerUtilCard.getWorstAI(list2);
sa.getTargets().add(object2);
}
if (object1 == null || object2 == null) {
return false;
}
if (ComputerUtilCard.evaluateCreature(object1) > ComputerUtilCard.evaluateCreature(object2) + 40) {
sa.getTargets().add(object1);
return MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
}
return false;
}
@Override
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt == null) {
if (mandatory) {
return true;
}
} else {
if (mandatory) {
CardCollection list2 = CardLists.getValidCards(aiPlayer.getGame().getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), aiPlayer, sa.getHostCard());
while (!list2.isEmpty()) {
Card best = ComputerUtilCard.getBestAI(list2);
if (sa.canTarget(best)) {
sa.getTargets().add(best);
return true;
}
list2.remove(best);
}
return false;
} else {
return canPlayAI(aiPlayer, sa);
}
}
return true;
}
}

View File

@@ -0,0 +1,254 @@
/*
* 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.ai.ability;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.ai.AiCardMemory;
import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCombat;
import forge.ai.PlayerControllerAi;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.Aggregates;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
//AB:GainControl|ValidTgts$Creature|TgtPrompt$Select target legendary creature|LoseControl$Untap,LoseControl|SpellDescription$Gain control of target xxxxxxx
//GainControl specific sa:
// LoseControl - the lose control conditions (as a comma separated list)
// -Untap - source card becomes untapped
// -LoseControl - you lose control of source card
// -LeavesPlay - source card leaves the battlefield
// -PowerGT - (not implemented yet for Old Man of the Sea)
// AddKWs - Keywords to add to the controlled card
// (as a "&"-separated list; like Haste, Sacrifice CARDNAME at EOT, any standard keyword)
// OppChoice - set to True if opponent chooses creature (for Preacher) - not implemented yet
// Untap - set to True if target card should untap when control is taken
// DestroyTgt - actions upon which the tgt should be destroyed. same list as LoseControl
// NoRegen - set if destroyed creature can't be regenerated. used only with DestroyTgt
/**
* <p>
* AbilityFactory_GainControl class.
* </p>
*
* @author Forge
* @version $Id: AbilityFactoryGainControl.java 17764 2012-10-29 11:04:18Z Sloth $
*/
public class ControlGainAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(final Player ai, final SpellAbility sa) {
boolean hasCreature = false;
boolean hasArtifact = false;
boolean hasEnchantment = false;
boolean hasLand = false;
final List<String> lose = sa.hasParam("LoseControl") ? Arrays.asList(sa.getParam("LoseControl").split(",")) : null;
final TargetRestrictions tgt = sa.getTargetRestrictions();
Player opp = ai.getOpponent();
// if Defined, then don't worry about targeting
if (tgt == null) {
if (sa.hasParam("AllValid")) {
CardCollectionView tgtCards = ai.getOpponent().getCardsIn(ZoneType.Battlefield);
tgtCards = AbilityUtils.filterListByType(tgtCards, sa.getParam("AllValid"), sa);
if (tgtCards.isEmpty()) {
return false;
}
}
return true;
} else {
sa.resetTargets();
if (sa.hasParam("TargetingPlayer")) {
Player targetingPlayer = AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("TargetingPlayer"), sa).get(0);
sa.setTargetingPlayer(targetingPlayer);
return targetingPlayer.getController().chooseTargetsFor(sa);
}
if (tgt.canOnlyTgtOpponent()) {
if (!opp.canBeTargetedBy(sa)) {
return false;
}
if (tgt.isRandomTarget()) {
sa.getTargets().add(Aggregates.random(tgt.getAllCandidates(sa, false)));
} else {
sa.getTargets().add(opp);
}
}
}
// Don't steal something if I can't Attack without, or prevent it from
// blocking at least
if (lose != null && lose.contains("EOT")
&& ai.getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)
&& !sa.isTrigger()) {
return false;
}
CardCollection list =
CardLists.getValidCards(opp.getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getHostCard());
// AI won't try to grab cards that are filtered out of AI decks on purpose
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
final Map<String, String> vars = c.getSVars();
if (!c.canBeTargetedBy(sa)) {
return false;
}
if (sa.isTrigger()) {
return true;
}
if (c.isCreature() && (!ComputerUtilCombat.canAttackNextTurn(c, ai.getOpponent()) || c.getNetCombatDamage() == 0)) {
return false;
}
return !vars.containsKey("RemAIDeck");
}
});
if (list.isEmpty()) {
return false;
}
while (sa.getTargets().getNumTargeted() < tgt.getMaxTargets(sa.getHostCard(), sa)) {
Card t = null;
for (final Card c : list) {
if (c.isCreature()) {
hasCreature = true;
}
if (c.isArtifact()) {
hasArtifact = true;
}
if (c.isLand()) {
hasLand = true;
}
if (c.isEnchantment()) {
hasEnchantment = true;
}
}
if (list.isEmpty()) {
if ((sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) || (sa.getTargets().getNumTargeted() == 0)) {
sa.resetTargets();
return false;
} else {
// TODO is this good enough? for up to amounts?
break;
}
}
if (hasCreature) {
t = ComputerUtilCard.getBestCreatureAI(list);
if (lose != null && lose.contains("EOT")) {
// Remember to always attack with this creature since it'll bounce back to its owner at end of turn anyway
((PlayerControllerAi)ai.getController()).getAi().getCardMemory().rememberCard(t, AiCardMemory.MemorySet.MANDATORY_ATTACKERS);
}
} else if (hasArtifact) {
t = ComputerUtilCard.getBestArtifactAI(list);
} else if (hasLand) {
t = ComputerUtilCard.getBestLandAI(list);
} else if (hasEnchantment) {
t = ComputerUtilCard.getBestEnchantmentAI(list, sa, true);
} else {
t = ComputerUtilCard.getMostExpensivePermanentAI(list, sa, true);
}
sa.getTargets().add(t);
list.remove(t);
hasCreature = false;
hasArtifact = false;
hasLand = false;
hasEnchantment = false;
}
return true;
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
if (sa.getTargetRestrictions() == null) {
if (mandatory) {
return true;
}
} else {
if(sa.hasParam("TargetingPlayer") || (!this.canPlayAI(ai, sa) && mandatory)) {
List<Card> list = CardLists.getTargetableCards(ai.getCardsIn(ZoneType.Battlefield), sa);
if (list.isEmpty()) {
return false;
} else {
sa.getTargets().add(ComputerUtilCard.getWorstAI(list));
}
}
}
return true;
}
@Override
public boolean chkAIDrawback(SpellAbility sa, final Player ai) {
final Game game = ai.getGame();
if ((sa.getTargetRestrictions() == null) || !sa.getTargetRestrictions().doesTarget()) {
if (sa.hasParam("AllValid")) {
CardCollectionView tgtCards = CardLists.filterControlledBy(game.getCardsIn(ZoneType.Battlefield), ai.getOpponent());
tgtCards = AbilityUtils.filterListByType(tgtCards, sa.getParam("AllValid"), sa);
if (tgtCards.isEmpty()) {
return false;
}
}
final List<String> lose = sa.hasParam("LoseControl") ? Arrays.asList(sa.getParam("LoseControl").split(",")) : null;
if ((lose != null) && lose.contains("EOT")
&& game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
return false;
}
} else {
return this.canPlayAI(ai, sa);
}
return true;
} // pumpDrawbackAI()
@Override
protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options) {
final List<Card> cards = new ArrayList<Card>();
for (Player p : options) {
cards.addAll(p.getCreaturesInPlay());
}
Card chosen = ComputerUtilCard.getBestCreatureAI(cards);
return chosen != null ? chosen.getController() : Iterables.getFirst(options, null);
}
}

View File

@@ -0,0 +1,147 @@
package forge.ai.ability;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilCard;
import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates.Presets;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class CopyPermanentAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
// Card source = sa.getHostCard();
// TODO - I'm sure someone can do this AI better
if (ComputerUtil.preventRunAwayActivations(sa)) {
return false;
}
if (sa.hasParam("AtEOT") && !aiPlayer.getGame().getPhaseHandler().is(PhaseType.MAIN1)) {
return false;
} else {
if (sa.getTargetRestrictions() != null && sa.hasParam("TargetingPlayer")) {
sa.resetTargets();
Player targetingPlayer = AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("TargetingPlayer"), sa).get(0);
sa.setTargetingPlayer(targetingPlayer);
return targetingPlayer.getController().chooseTargetsFor(sa);
} else {
return this.doTriggerAINoCost(aiPlayer, sa, false);
}
}
}
@Override
protected boolean doTriggerAINoCost(final Player aiPlayer, SpellAbility sa, boolean mandatory) {
final Card source = sa.getHostCard();
// ////
// Targeting
final TargetRestrictions abTgt = sa.getTargetRestrictions();
if (abTgt != null) {
sa.resetTargets();
CardCollection list = CardLists.getValidCards(aiPlayer.getGame().getCardsIn(ZoneType.Battlefield), abTgt.getValidTgts(), source.getController(), source);
list = CardLists.getTargetableCards(list, sa);
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
final Map<String, String> vars = c.getSVars();
return !vars.containsKey("RemAIDeck");
}
});
// target loop
while (sa.getTargets().getNumTargeted() < abTgt.getMaxTargets(sa.getHostCard(), sa)) {
if (list.isEmpty()) {
if ((sa.getTargets().getNumTargeted() < abTgt.getMinTargets(sa.getHostCard(), sa))
|| (sa.getTargets().getNumTargeted() == 0)) {
sa.resetTargets();
return false;
} else {
// TODO is this good enough? for up to amounts?
break;
}
}
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return !c.getType().isLegendary() || c.getController().isOpponentOf(aiPlayer);
}
});
Card choice;
if (!CardLists.filter(list, Presets.CREATURES).isEmpty()) {
if (sa.hasParam("TargetingPlayer")) {
choice = ComputerUtilCard.getWorstCreatureAI(list);
} else {
choice = ComputerUtilCard.getBestCreatureAI(list);
}
} else {
choice = ComputerUtilCard.getMostExpensivePermanentAI(list, sa, true);
}
if (choice == null) { // can't find anything left
if ((sa.getTargets().getNumTargeted() < abTgt.getMinTargets(sa.getHostCard(), sa))
|| (sa.getTargets().getNumTargeted() == 0)) {
sa.resetTargets();
return false;
} else {
// TODO is this good enough? for up to amounts?
break;
}
}
list.remove(choice);
sa.getTargets().add(choice);
}
} else {
// if no targeting, it should always be ok
}
return true;
}
/* (non-Javadoc)
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.game.player.Player, forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
*/
@Override
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
//TODO: add logic here
return true;
}
/* (non-Javadoc)
* @see forge.card.ability.SpellAbilityAi#chooseSingleCard(forge.game.player.Player, forge.card.spellability.SpellAbility, java.util.List, boolean)
*/
@Override
public Card chooseSingleCard(Player ai, SpellAbility sa, Iterable<Card> options, boolean isOptional, Player targetedPlayer) {
// Select a card to attach to
return ComputerUtilCard.getBestAI(options);
}
@Override
protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options) {
final List<Card> cards = new ArrayList<Card>();
for (Player p : options) {
cards.addAll(p.getCreaturesInPlay());
}
Card chosen = ComputerUtilCard.getBestCreatureAI(cards);
return chosen != null ? chosen.getController() : Iterables.getFirst(options, null);
}
}

View File

@@ -1,16 +1,16 @@
package forge.card.ability.ai;
package forge.ai.ability;
import forge.Card;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.ai.ComputerUtilCost;
import forge.ai.ComputerUtilMana;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardFactoryUtil;
import forge.game.cost.Cost;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom;
public class CounterAi extends SpellAbilityAi {
@@ -19,7 +19,7 @@ public class CounterAi extends SpellAbilityAi {
protected boolean canPlayAI(Player ai, SpellAbility sa) {
boolean toReturn = true;
final Cost abCost = sa.getPayCosts();
final Card source = sa.getSourceCard();
final Card source = sa.getHostCard();
final Game game = ai.getGame();
if (game.getStack().isEmpty()) {
return false;
@@ -35,22 +35,27 @@ public class CounterAi extends SpellAbilityAi {
}
}
final Target tgt = sa.getTarget();
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
final SpellAbility topSA = game.getStack().peekAbility();
if (!CardFactoryUtil.isCounterableBy(topSA.getSourceCard(), sa) || topSA.getActivatingPlayer() == ai) {
if (!CardFactoryUtil.isCounterableBy(topSA.getHostCard(), sa) || topSA.getActivatingPlayer() == ai
|| ai.getAllies().contains(topSA.getActivatingPlayer())) {
// might as well check for player's friendliness
return false;
}
if (sa.hasParam("AITgts") && (topSA.getSourceCard() == null
|| !topSA.getSourceCard().isValid(sa.getParam("AITgts"), sa.getActivatingPlayer(), source))) {
if (sa.hasParam("AITgts") && (topSA.getHostCard() == null
|| !topSA.getHostCard().isValid(sa.getParam("AITgts"), sa.getActivatingPlayer(), source))) {
return false;
}
tgt.resetTargets();
if (sa.hasParam("CounterNoManaSpell") && topSA.getTotalManaSpent() == 0) {
return false;
}
sa.resetTargets();
if (sa.canTargetSpellAbility(topSA)) {
tgt.addTarget(topSA);
sa.getTargets().add(topSA);
} else {
return false;
}
@@ -108,27 +113,27 @@ public class CounterAi extends SpellAbilityAi {
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final Target tgt = sa.getTarget();
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
final Game game = ai.getGame();
if (game.getStack().isEmpty()) {
return false;
}
final SpellAbility topSA = game.getStack().peekAbility();
if (!CardFactoryUtil.isCounterableBy(topSA.getSourceCard(), sa) || topSA.getActivatingPlayer() == ai) {
if (!CardFactoryUtil.isCounterableBy(topSA.getHostCard(), sa) || topSA.getActivatingPlayer() == ai) {
return false;
}
tgt.resetTargets();
sa.resetTargets();
if (sa.canTargetSpellAbility(topSA)) {
tgt.addTarget(topSA);
sa.getTargets().add(topSA);
} else {
return false;
}
String unlessCost = sa.hasParam("UnlessCost") ? sa.getParam("UnlessCost").trim() : null;
final Card source = sa.getSourceCard();
final Card source = sa.getHostCard();
if (unlessCost != null) {
// Is this Usable Mana Sources? Or Total Available Mana?
final int usableManaSources = ComputerUtilMana.getAvailableMana(ai.getOpponent(), true).size();

View File

@@ -15,18 +15,20 @@
* 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.ability.ai;
import java.util.List;
package forge.ai.ability;
import com.google.common.base.Predicate;
import forge.Card;
import forge.CardLists;
import forge.CounterType;
import forge.game.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCard;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CounterType;
import forge.util.Aggregates;
import java.util.List;
/**
* <p>
@@ -50,16 +52,16 @@ public abstract class CountersAi {
* a {@link java.lang.String} object.
* @param amount
* a int.
* @return a {@link forge.Card} object.
* @return a {@link forge.game.card.Card} object.
*/
public static Card chooseCursedTarget(final List<Card> list, final String type, final int amount) {
public static Card chooseCursedTarget(final CardCollectionView list, final String type, final int amount) {
Card choice;
if (type.equals("M1M1")) {
// try to kill the best killable creature, or reduce the best one
final List<Card> killable = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.getNetDefense() <= amount;
return c.getNetToughness() <= amount;
}
});
if (killable.size() > 0) {
@@ -83,14 +85,14 @@ public abstract class CountersAi {
* a {@link forge.CardList} object.
* @param type
* a {@link java.lang.String} object.
* @return a {@link forge.Card} object.
* @return a {@link forge.game.card.Card} object.
*/
public static Card chooseBoonTarget(final List<Card> list, final String type) {
public static Card chooseBoonTarget(final CardCollectionView list, final String type) {
Card choice;
if (type.equals("P1P1")) {
choice = ComputerUtilCard.getBestCreatureAI(list);
} else if (type.equals("DIVINITY")) {
final List<Card> boon = CardLists.filter(list, new Predicate<Card>() {
final CardCollection boon = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.getCounters(CounterType.DIVINITY) == 0;

View File

@@ -0,0 +1,129 @@
package forge.ai.ability;
import forge.ai.ComputerUtilCard;
import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CounterType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.Aggregates;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class CountersMoveAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
// AI needs to be expanded, since this function can be pretty complex
// based on what
// the expected targets could be
final Random r = MyRandom.getRandom();
final String amountStr = sa.getParam("CounterNum");
// TODO handle proper calculation of X values based on Cost
int amount = 0;
if (!sa.getParam("CounterNum").equals("All")) {
amount = AbilityUtils.calculateAmount(sa.getHostCard(), amountStr, sa);
}
// don't use it if no counters to add
if (amount <= 0) {
return false;
}
// prevent run-away activations - first time will always return true
boolean chance = false;
if (SpellAbilityAi.playReusable(ai, sa)) {
return chance;
}
return ((r.nextFloat() < .6667) && chance);
} // moveCounterCanPlayAI
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final Card host = sa.getHostCard();
final TargetRestrictions abTgt = sa.getTargetRestrictions();
final String type = sa.getParam("CounterType");
final String amountStr = sa.getParam("CounterNum");
int amount = 0;
if (!sa.getParam("CounterNum").equals("All")) {
amount = AbilityUtils.calculateAmount(sa.getHostCard(), amountStr, sa);
}
boolean chance = false;
boolean preferred = true;
final CounterType cType = CounterType.valueOf(sa.getParam("CounterType"));
final List<Card> srcCards = AbilityUtils.getDefinedCards(host, sa.getParam("Source"), sa);
final List<Card> destCards = AbilityUtils.getDefinedCards(host, sa.getParam("Defined"), sa);
if ((srcCards.size() > 0 && sa.getParam("CounterNum").equals("All"))) {
amount = srcCards.get(0).getCounters(cType);
}
if (abTgt == null) {
if ((srcCards.size() > 0)
&& cType.equals(CounterType.P1P1) // move +1/+1 counters away
// from
// permanents that cannot use
// them
&& (destCards.size() > 0) && destCards.get(0).getController() == ai
&& (!srcCards.get(0).isCreature() || srcCards.get(0).hasStartOfKeyword("CARDNAME can't attack"))) {
chance = true;
}
} else { // targeted
final Player player = sa.isCurse() ? ai.getOpponent() : ai;
CardCollectionView list = CardLists.getTargetableCards(player.getCardsIn(ZoneType.Battlefield), sa);
list = CardLists.getValidCards(list, abTgt.getValidTgts(), host.getController(), host);
if (list.isEmpty() && mandatory) {
// If there isn't any prefered cards to target, gotta choose
// non-preferred ones
list = CardLists.getTargetableCards(player.getOpponent().getCardsIn(ZoneType.Battlefield), sa);
list = CardLists.getValidCards(list, abTgt.getValidTgts(), host.getController(), host);
preferred = false;
}
// Not mandatory, or the the list was regenerated and is still
// empty,
// so return false since there are no targets
if (list.isEmpty()) {
return false;
}
Card choice = null;
// Choose targets here:
if (sa.isCurse()) {
if (preferred) {
choice = CountersAi.chooseCursedTarget(list, type, amount);
}
else if (type.equals("M1M1")) {
choice = ComputerUtilCard.getWorstCreatureAI(list);
}
else {
choice = Aggregates.random(list);
}
}
else {
if (preferred) {
choice = CountersAi.chooseBoonTarget(list, type);
}
else if (type.equals("P1P1")) {
choice = ComputerUtilCard.getWorstCreatureAI(list);
}
else {
choice = Aggregates.random(list);
}
}
// TODO - I think choice can be null here. Is that ok for
// addTarget()?
sa.getTargets().add(choice);
}
return chance;
}
}

View File

@@ -0,0 +1,68 @@
package forge.ai.ability;
import com.google.common.base.Predicate;
import forge.ai.ComputerUtil;
import forge.ai.SpellAbilityAi;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.card.CounterType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import java.util.List;
public class CountersProliferateAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
boolean chance = true;
List<Card> cperms = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), new Predicate<Card>() {
@Override
public boolean apply(final Card crd) {
for (final CounterType c1 : CounterType.values()) {
if (crd.getCounters(c1) != 0 && !ComputerUtil.isNegativeCounter(c1, crd)) {
return true;
}
}
return false;
}
});
List<Card> hperms = CardLists.filter(ai.getOpponent().getCardsIn(ZoneType.Battlefield), new Predicate<Card>() {
@Override
public boolean apply(final Card crd) {
for (final CounterType c1 : CounterType.values()) {
if (crd.getCounters(c1) != 0 && ComputerUtil.isNegativeCounter(c1, crd)) {
return true;
}
}
return false;
}
});
if (cperms.isEmpty() && hperms.isEmpty() && ai.getOpponent().getPoisonCounters() == 0) {
return false;
}
return chance;
}
@Override
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
boolean chance = true;
// TODO Make sure Human has poison counters or there are some counters
// we want to proliferate
return chance;
}
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#chkAIDrawback(java.util.Map, forge.card.spellability.SpellAbility, forge.game.player.Player)
*/
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
return canPlayAI(ai, sa);
}
}

View File

@@ -0,0 +1,520 @@
package forge.ai.ability;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.ai.*;
import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityUtils;
import forge.game.card.*;
import forge.game.combat.CombatUtil;
import forge.game.cost.Cost;
import forge.game.cost.CostPart;
import forge.game.cost.CostRemoveCounter;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.Aggregates;
import forge.util.MyRandom;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class CountersPutAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, final SpellAbility sa) {
// AI needs to be expanded, since this function can be pretty complex
// based on
// what the expected targets could be
final Random r = MyRandom.getRandom();
final Cost abCost = sa.getPayCosts();
final TargetRestrictions abTgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
CardCollection list;
Card choice = null;
final String type = sa.getParam("CounterType");
final String amountStr = sa.getParam("CounterNum");
final boolean divided = sa.hasParam("DividedAsYouChoose");
final Player player = sa.isCurse() ? ai.getOpponent() : ai;
if (ComputerUtil.preventRunAwayActivations(sa)) {
return false;
}
if ("Never".equals(sa.getParam("AILogic"))) {
return false;
}
if (abCost != null) {
// AI currently disabled for these costs
if (!ComputerUtilCost.checkLifeCost(ai, abCost, source, 4, null)) {
return false;
}
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
return false;
}
// disable moving counters
for (final CostPart part : abCost.getCostParts()) {
if (part instanceof CostRemoveCounter) {
final CostRemoveCounter remCounter = (CostRemoveCounter) part;
final CounterType counterType = remCounter.counter;
if (counterType.name().equals(type)) {
return false;
}
if (!part.payCostFromSource()) {
if (counterType.name().equals("P1P1")) {
return false;
}
continue;
}
//don't kill the creature
if (counterType.name().equals("P1P1") && source.getLethalDamage() <= 1) {
return false;
}
}
}
}
if (sa.hasParam("Bolster")) {
CardCollection creatsYouCtrl = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
CardCollection leastToughness = new CardCollection(Aggregates.listWithMin(creatsYouCtrl, CardPredicates.Accessors.fnGetDefense));
if (leastToughness.isEmpty()) {
return false;
}
// TODO If Creature that would be Bolstered for some reason is useless, also return False
}
if (sa.hasParam("Monstrosity") && source.isMonstrous()) {
return false;
}
if (sa.hasParam("LevelUp")) {
// creatures enchanted by curse auras have low priority
if (source.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)) {
for (Card aura : source.getEnchantedBy(false)) {
if (aura.getController().isOpponentOf(ai)) {
return false;
}
}
}
int maxLevel = Integer.parseInt(sa.getParam("MaxLevel"));
return source.getCounters(CounterType.LEVEL) < maxLevel;
}
// TODO handle proper calculation of X values based on Cost
int amount = AbilityUtils.calculateAmount(source, amountStr, sa);
if ("Fight".equals(sa.getParam("AILogic"))) {
int nPump = 0;
if (type.equals("P1P1")) {
nPump = amount;
}
final AbilitySub tgtFight = sa.getSubAbility();
CardCollection aiCreatures = ai.getCreaturesInPlay();
aiCreatures = CardLists.getTargetableCards(aiCreatures, sa);
aiCreatures = ComputerUtil.getSafeTargets(ai, sa, aiCreatures);
ComputerUtilCard.sortByEvaluateCreature(aiCreatures);
CardCollection humCreatures = ai.getOpponent().getCreaturesInPlay();
humCreatures = CardLists.getTargetableCards(humCreatures, tgtFight);
ComputerUtilCard.sortByEvaluateCreature(humCreatures);
if (humCreatures.isEmpty() || aiCreatures.isEmpty()) {
return false;
}
for (Card humanCreature : humCreatures) {
for (Card aiCreature : aiCreatures) {
if (sa.isSpell()) { //heroic triggers adding counters
for (Trigger t : aiCreature.getTriggers()) {
if (t.getMode() == TriggerType.SpellCast) {
final Map<String, String> params = t.getMapParams();
if ("Card.Self".equals(params.get("TargetsValid")) && "You".equals(params.get("ValidActivatingPlayer"))
&& params.containsKey("Execute")) {
SpellAbility heroic = AbilityFactory.getAbility(aiCreature.getSVar(params.get("Execute")),aiCreature);
if ("Self".equals(heroic.getParam("Defined")) && "P1P1".equals(heroic.getParam("CounterType"))) {
int n = AbilityUtils.calculateAmount(aiCreature, heroic.getParam("CounterNum"), heroic);
nPump += n;
}
break;
}
}
}
}
if (FightAi.shouldFight(aiCreature, humanCreature, nPump, nPump)) {
sa.getTargets().add(aiCreature);
tgtFight.getTargets().add(humanCreature);
return true;
}
}
}
}
if (amountStr.equals("X") && source.getSVar(amountStr).equals("Count$xPaid")) {
// Set PayX here to maximum value.
amount = ComputerUtilMana.determineLeftoverMana(sa, ai);
source.setSVar("PayX", Integer.toString(amount));
}
// don't use it if no counters to add
if (amount <= 0) {
return false;
}
if ("Polukranos".equals(sa.getParam("AILogic"))) {
CardCollection humCreatures = ai.getOpponent().getCreaturesInPlay();
final CardCollection targets = CardLists.filter(humCreatures, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return !(c.hasProtectionFrom(source) || c.hasKeyword("Shroud") || c.hasKeyword("Hexproof"));
}
});
if (!targets.isEmpty()){
boolean canSurvive = false;
for (Card humanCreature : targets) {
if (!FightAi.canKill(humanCreature, source, 0)){
canSurvive = true;
}
}
if (!canSurvive){
return false;
}
}
}
PhaseHandler ph = ai.getGame().getPhaseHandler();
if (sa.isOutlast()) {
if (ph.is(PhaseType.MAIN2, ai)) { //applicable to non-attackers only
float chance = 0.8f;
if (ComputerUtilCard.doesSpecifiedCreatureBlock(ai, source)) {
return false;
}
return chance > r.nextFloat();
} else {
return false;
}
}
// Targeting
if (abTgt != null) {
sa.resetTargets();
final boolean sacSelf = ComputerUtilCost.isSacrificeSelfCost(abCost);
list = CardLists.filter(player.getCardsIn(ZoneType.Battlefield), new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
// don't put the counter on the dead creature
if (sacSelf && c.equals(source)) {
return false;
}
return c.canBeTargetedBy(sa) && c.canReceiveCounters(CounterType.valueOf(type));
}
});
list = CardLists.getValidCards(list, abTgt.getValidTgts(), source.getController(), source);
if (list.size() < abTgt.getMinTargets(source, sa)) {
return false;
}
// target loop
while (sa.getTargets().getNumTargeted() < abTgt.getMaxTargets(sa.getHostCard(), sa)) {
if (list.isEmpty()) {
if ((sa.getTargets().getNumTargeted() < abTgt.getMinTargets(sa.getHostCard(), sa))
|| (sa.getTargets().getNumTargeted() == 0)) {
sa.resetTargets();
return false;
} else {
// TODO is this good enough? for up to amounts?
break;
}
}
if (sa.isCurse()) {
choice = CountersAi.chooseCursedTarget(list, type, amount);
} else {
choice = CountersAi.chooseBoonTarget(list, type);
}
if (choice == null) { // can't find anything left
if (sa.getTargets().getNumTargeted() < abTgt.getMinTargets(sa.getHostCard(), sa)
|| sa.getTargets().getNumTargeted() == 0) {
sa.resetTargets();
return false;
} else {
// TODO is this good enough? for up to amounts?
break;
}
}
list.remove(choice);
sa.getTargets().add(choice);
if (divided) {
abTgt.addDividedAllocation(choice, amount);
break;
}
}
if (sa.getTargets().isEmpty()) {
return false;
}
} else {
final List<Card> cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
// Don't activate Curse abilities on my cards and non-curse abilites
// on my opponents
if (cards.isEmpty() || !cards.get(0).getController().equals(player)) {
return false;
}
final int currCounters = cards.get(0).getCounters(CounterType.valueOf(type));
// each non +1/+1 counter on the card is a 10% chance of not
// activating this ability.
if (!(type.equals("P1P1") || type.equals("M1M1") || type.equals("ICE")) && (r.nextFloat() < (.1 * currCounters))) {
return false;
}
}
boolean immediately = ComputerUtil.playImmediately(ai, sa);
if (abCost != null && !ComputerUtilCost.checkSacrificeCost(ai, abCost, source, immediately)) {
return false;
}
if (immediately) {
return true;
}
if (!type.equals("P1P1") && !type.equals("M1M1") && !sa.hasParam("ActivationPhases")) {
// Don't use non P1P1/M1M1 counters before main 2 if possible
if (ph.getPhase().isBefore(PhaseType.MAIN2)
&& !ComputerUtil.castSpellInMain1(ai, sa)) {
return false;
}
if (ph.isPlayerTurn(ai) && !isSorcerySpeed(sa)) {
return false;
}
}
if (ComputerUtil.waitForBlocking(sa)) {
return false;
}
return true;
}
@Override
public boolean chkAIDrawback(final SpellAbility sa, Player ai) {
boolean chance = true;
final TargetRestrictions abTgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
Card choice = null;
final String type = sa.getParam("CounterType");
final String amountStr = sa.getParam("CounterNum");
final boolean divided = sa.hasParam("DividedAsYouChoose");
final int amount = AbilityUtils.calculateAmount(sa.getHostCard(), amountStr, sa);
final Player player = sa.isCurse() ? ai.getOpponent() : ai;
if (abTgt != null) {
CardCollection list =
CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), abTgt.getValidTgts(), source.getController(), source);
if (list.size() == 0) {
return false;
}
sa.resetTargets();
// target loop
while (sa.getTargets().getNumTargeted() < abTgt.getMaxTargets(sa.getHostCard(), sa)) {
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return sa.canTarget(c);
}
});
if (list.size() == 0) {
if ((sa.getTargets().getNumTargeted() < abTgt.getMinTargets(sa.getHostCard(), sa))
|| (sa.getTargets().getNumTargeted() == 0)) {
sa.resetTargets();
return false;
} else {
break;
}
}
if (sa.isCurse()) {
choice = CountersAi.chooseCursedTarget(list, type, amount);
} else {
choice = CountersAi.chooseBoonTarget(list, type);
}
if (choice == null) { // can't find anything left
if ((sa.getTargets().getNumTargeted() < abTgt.getMinTargets(sa.getHostCard(), sa))
|| (sa.getTargets().getNumTargeted() == 0)) {
sa.resetTargets();
return false;
} else {
// TODO is this good enough? for up to amounts?
break;
}
}
list.remove(choice);
sa.getTargets().add(choice);
if (divided) {
abTgt.addDividedAllocation(choice, amount);
break;
}
}
}
return chance;
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final TargetRestrictions abTgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
// boolean chance = true;
boolean preferred = true;
CardCollection list;
boolean isCurse = sa.isCurse();
final Player player = isCurse ? ai.getOpponent() : ai;
final String type = sa.getParam("CounterType");
final String amountStr = sa.getParam("CounterNum");
final boolean divided = sa.hasParam("DividedAsYouChoose");
final int amount = AbilityUtils.calculateAmount(sa.getHostCard(), amountStr, sa);
if (abTgt == null) {
// No target. So must be defined
list = new CardCollection(AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa));
if (amountStr.equals("X") && ((sa.hasParam(amountStr) && sa.getSVar(amountStr).equals("Count$xPaid")) || source.getSVar(amountStr).equals("Count$xPaid") )) {
// Spend all remaining mana to add X counters (eg. Hero of Leina Tower)
source.setSVar("PayX", Integer.toString(ComputerUtilMana.determineLeftoverMana(sa, ai)));
}
if (!mandatory) {
// TODO - If Trigger isn't mandatory, when wouldn't we want to
// put a counter?
// things like Powder Keg, which are way too complex for the AI
}
} else {
list = CardLists.getTargetableCards(player.getCardsIn(ZoneType.Battlefield), sa);
list = CardLists.getValidCards(list, abTgt.getValidTgts(), source.getController(), source);
if (list.isEmpty() && mandatory) {
// If there isn't any prefered cards to target, gotta choose
// non-preferred ones
list = CardLists.getTargetableCards(player.getOpponent().getCardsIn(ZoneType.Battlefield), sa);
list = CardLists.getValidCards(list, abTgt.getValidTgts(), source.getController(), source);
preferred = false;
}
// Not mandatory, or the the list was regenerated and is still
// empty,
// so return false since there are no targets
if (list.isEmpty()) {
return false;
}
Card choice = null;
// Choose targets here:
if (isCurse) {
if (preferred) {
choice = CountersAi.chooseCursedTarget(list, type, amount);
}
else {
if (type.equals("M1M1")) {
choice = ComputerUtilCard.getWorstCreatureAI(list);
} else {
choice = Aggregates.random(list);
}
}
}
else {
if (preferred) {
choice = CountersAi.chooseBoonTarget(list, type);
}
else {
if (type.equals("P1P1")) {
choice = ComputerUtilCard.getWorstCreatureAI(list);
} else {
choice = Aggregates.random(list);
}
}
if (choice != null && divided) {
abTgt.addDividedAllocation(choice, amount);
}
}
// TODO - I think choice can be null here. Is that ok for
// addTarget()?
sa.getTargets().add(choice);
}
return true;
}
@Override
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
final Card source = sa.getHostCard();
if (mode == PlayerActionConfirmMode.Tribute) {
// add counter if that opponent has a giant creature
final List<Card> creats = player.getCreaturesInPlay();
final int tributeAmount = source.getKeywordMagnitude("Tribute");
final boolean isHaste = source.hasKeyword("Haste");
List<Card> threatening = CardLists.filter(creats, new Predicate<Card>() {
@Override
public boolean apply(Card c) {
return CombatUtil.canBlock(source, c, !isHaste)
&& (c.getNetToughness() > source.getNetPower() + tributeAmount || c.hasKeyword("DeathTouch"));
}
});
if (!threatening.isEmpty()) {
return true;
}
if (source.hasSVar("TributeAILogic")) {
final String logic = source.getSVar("TributeAILogic");
if (logic.equals("Always")) {
return true;
} else if (logic.equals("Never")) {
return false;
} else if (logic.equals("CanBlockThisTurn")) {
// pump haste
List<Card> canBlock = CardLists.filter(creats, new Predicate<Card>() {
@Override
public boolean apply(Card c) {
return CombatUtil.canBlock(source, c) && (c.getNetToughness() > source.getNetPower() || c.hasKeyword("DeathTouch"));
}
});
if (!canBlock.isEmpty()) {
return false;
}
} else if (logic.equals("DontControlCreatures")) {
return !creats.isEmpty();
} else if (logic.equals("OppHasCardsInHand")) {
return !player.getOpponent().getCardsIn(ZoneType.Hand).isEmpty();
}
}
}
return MyRandom.getRandom().nextBoolean();
}
@Override
public Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options) {
// logic?
return Iterables.getFirst(options, null);
}
}

View File

@@ -1,26 +1,26 @@
package forge.card.ability.ai;
import java.util.List;
import java.util.Random;
package forge.ai.ability;
import com.google.common.base.Predicate;
import forge.Card;
import forge.CardLists;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi;
import forge.card.cost.Cost;
import forge.card.spellability.AbilitySub;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana;
import forge.ai.ComputerUtilCost;
import forge.ai.ComputerUtilMana;
import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.cost.Cost;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class CountersPutAllAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
@@ -29,14 +29,14 @@ public class CountersPutAllAi extends SpellAbilityAi {
// the expected targets could be
final Random r = MyRandom.getRandom();
final Cost abCost = sa.getPayCosts();
final Card source = sa.getSourceCard();
final Card source = sa.getHostCard();
List<Card> hList;
List<Card> cList;
final String type = sa.getParam("CounterType");
final String amountStr = sa.getParam("CounterNum");
final String valid = sa.getParam("ValidCards");
final boolean curse = sa.isCurse();
final Target tgt = sa.getTarget();
final TargetRestrictions tgt = sa.getTargetRestrictions();
hList = CardLists.getValidCards(ai.getOpponent().getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
cList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
@@ -58,7 +58,7 @@ public class CountersPutAllAi extends SpellAbilityAi {
if (tgt != null) {
Player pl = curse ? ai.getOpponent() : ai;
tgt.addTarget(pl);
sa.getTargets().add(pl);
hList = CardLists.filterControlledBy(hList, pl);
cList = CardLists.filterControlledBy(cList, pl);
@@ -72,7 +72,7 @@ public class CountersPutAllAi extends SpellAbilityAi {
amount = ComputerUtilMana.determineLeftoverMana(sa, ai);
source.setSVar("PayX", Integer.toString(amount));
} else {
amount = AbilityUtils.calculateAmount(sa.getSourceCard(), amountStr, sa);
amount = AbilityUtils.calculateAmount(sa.getHostCard(), amountStr, sa);
}
// prevent run-away activations - first time will always return true
@@ -83,7 +83,7 @@ public class CountersPutAllAi extends SpellAbilityAi {
final List<Card> killable = CardLists.filter(hList, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.getNetDefense() <= amount;
return c.getNetToughness() <= amount;
}
});
if (!(killable.size() > 2)) {
@@ -133,4 +133,11 @@ public class CountersPutAllAi extends SpellAbilityAi {
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
return canPlayAI(ai, sa);
}
/* (non-Javadoc)
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.game.player.Player, forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
*/
@Override
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
return player.getCreaturesInPlay().size() >= player.getOpponent().getCreaturesInPlay().size();
}
}

View File

@@ -0,0 +1,92 @@
/*
* 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.ai.ability;
import com.google.common.base.Predicate;
import forge.ai.SpellAbilityAi;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.List;
/**
* <p>
* AbilityFactory_PutOrRemoveCountersAi class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class CountersPutOrRemoveAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
return doTriggerAINoCost(ai, sa, false);
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
// if Defined, don't worry about targeting
List<ZoneType> zones = ZoneType.listValueOf(sa.getParamOrDefault("TgtZones", "Battlefield"));
List<Card> validCards = CardLists.getValidCards(ai.getGame().getCardsIn(zones),
tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getHostCard());
if (validCards.isEmpty()) {
return false;
}
List<Card> cWithCounters = CardLists.filter(validCards, new Predicate<Card>() {
@Override
public boolean apply(final Card crd) {
return crd.hasCounters();
}
});
if (cWithCounters.isEmpty()) {
if (mandatory) {
cWithCounters = validCards;
} else {
return false;
}
}
while (sa.getTargets().getNumTargeted() < tgt.getMaxTargets(sa.getHostCard(), sa)) {
Card targetCard = null;
if (cWithCounters.isEmpty() && ((sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa))
|| (sa.getTargets().getNumTargeted() == 0))) {
sa.resetTargets();
return false;
}
int random = MyRandom.getRandom().nextInt(cWithCounters.size());
targetCard = cWithCounters.get(random);
sa.getTargets().add(targetCard);
cWithCounters.remove(targetCard);
}
return true;
}
}

View File

@@ -1,15 +1,15 @@
package forge.card.ability.ai;
package forge.ai.ability;
import forge.Card;
import forge.CounterType;
import forge.card.ability.SpellAbilityAi;
import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCost;
import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilCost;
import forge.ai.SpellAbilityAi;
import forge.game.card.Card;
import forge.game.card.CounterType;
import forge.game.cost.Cost;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
public class CountersRemoveAi extends SpellAbilityAi {
@@ -19,8 +19,8 @@ public class CountersRemoveAi extends SpellAbilityAi {
// based on what
// the expected targets could be
final Cost abCost = sa.getPayCosts();
Target abTgt = sa.getTarget();
final Card source = sa.getSourceCard();
TargetRestrictions abTgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
// List<Card> list;
// Card choice = null;
@@ -59,7 +59,7 @@ public class CountersRemoveAi extends SpellAbilityAi {
}
// TODO handle proper calculation of X values based on Cost
// final int amount = calculateAmount(sa.getSourceCard(), amountStr, sa);
// final int amount = calculateAmount(sa.getHostCard(), amountStr, sa);
if (ComputerUtil.preventRunAwayActivations(sa)) {
return false;
@@ -77,7 +77,7 @@ public class CountersRemoveAi extends SpellAbilityAi {
}
if (!type.matches("Any")) {
final int currCounters = sa.getSourceCard().getCounters(CounterType.valueOf(type));
final int currCounters = sa.getHostCard().getCounters(CounterType.valueOf(type));
if (currCounters < 1) {
return false;
}

View File

@@ -0,0 +1,64 @@
package forge.ai.ability;
import com.google.common.collect.Iterables;
import forge.ai.ComputerUtilCombat;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.card.CardCollectionView;
import forge.game.card.CardPredicates;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
public abstract class DamageAiBase extends SpellAbilityAi {
protected boolean shouldTgtP(final Player comp, final SpellAbility sa, final int d, final boolean noPrevention) {
int restDamage = d;
final Game game = comp.getGame();
final Player enemy = comp.getOpponent();
if (!sa.canTarget(enemy)) {
return false;
}
if (sa.getTargets() != null && sa.getTargets().getTargets().contains(enemy)) {
return false;
}
// burn Planeswalkers
if (Iterables.any(enemy.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.PLANEWALKERS)) {
return true;
}
if (!noPrevention) {
restDamage = ComputerUtilCombat.predictDamageTo(enemy, restDamage, sa.getHostCard(), false);
} else {
restDamage = enemy.staticReplaceDamage(restDamage, sa.getHostCard(), false);
}
if (restDamage == 0) {
return false;
}
if (!enemy.canLoseLife()) {
return false;
}
final CardCollectionView hand = comp.getCardsIn(ZoneType.Hand);
if (sa.isSpell()) {
// If this is a spell, cast it instead of discarding
if ((game.getPhaseHandler().is(PhaseType.END_OF_TURN) || game.getPhaseHandler().is(PhaseType.MAIN2))
&& game.getPhaseHandler().isPlayerTurn(comp) && (hand.size() > comp.getMaxHandSize())) {
return true;
}
}
if ((enemy.getLife() - restDamage) < 5) {
// drop the human to less than 5
// life
return true;
}
return false;
}
}

View File

@@ -0,0 +1,241 @@
package forge.ai.ability;
import com.google.common.base.Predicate;
import forge.ai.*;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.cost.Cost;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.Random;
public class DamageAllAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
// AI needs to be expanded, since this function can be pretty complex
// based on what the expected targets could be
final Random r = MyRandom.getRandom();
final Cost abCost = sa.getPayCosts();
final Card source = sa.getHostCard();
String validP = "";
final String damage = sa.getParam("NumDmg");
int dmg = AbilityUtils.calculateAmount(sa.getHostCard(), damage, sa);
if (damage.equals("X") && sa.getSVar(damage).equals("Count$xPaid")) {
// Set PayX here to maximum value.
dmg = ComputerUtilMana.determineLeftoverMana(sa, ai);
source.setSVar("PayX", Integer.toString(dmg));
}
if (sa.hasParam("ValidPlayers")) {
validP = sa.getParam("ValidPlayers");
}
Player opp = ai.getOpponent();
final CardCollection humanList = getKillableCreatures(sa, opp, dmg);
CardCollection computerList = getKillableCreatures(sa, ai, dmg);
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null && sa.canTarget(opp)) {
sa.resetTargets();
sa.getTargets().add(opp);
computerList.clear();
}
// abCost stuff that should probably be centralized...
if (abCost != null) {
// AI currently disabled for some costs
if (!ComputerUtilCost.checkLifeCost(ai, abCost, source, 4, null)) {
return false;
}
}
// TODO: if damage is dependant on mana paid, maybe have X be human's max life
// Don't kill yourself
if (validP.contains("Each") && (ai.getLife() <= ComputerUtilCombat.predictDamageTo(ai, dmg, source, false))) {
return false;
}
// prevent run-away activations - first time will always return true
if (r.nextFloat() > Math.pow(.9, sa.getActivationsThisTurn())) {
return false;
}
// if we can kill human, do it
if ((validP.contains("Each") || validP.contains("EachOpponent"))
&& (opp.getLife() <= ComputerUtilCombat.predictDamageTo(opp, dmg, source, false))) {
return true;
}
// wait until stack is empty (prevents duplicate kills)
if (!ai.getGame().getStack().isEmpty()) {
return false;
}
int minGain = 200; // The minimum gain in destroyed creatures
if (sa.getPayCosts() != null && sa.getPayCosts().isReusuableResource()) {
if (computerList.isEmpty()) {
minGain = 10; // nothing to lose
} else {
minGain = 100; // safety for errors in evaluate creature
}
} else if (sa.getSubAbility() != null && ai.getGame().getPhaseHandler().isPreCombatMain() && computerList.isEmpty()
&& opp.getCreaturesInPlay().size() > 1 && !ai.getCreaturesInPlay().isEmpty()) {
minGain = 126; // prepare for attack
}
// evaluate both lists and pass only if human creatures are more valuable
if ((ComputerUtilCard.evaluateCreatureList(computerList) + minGain) >= ComputerUtilCard
.evaluateCreatureList(humanList)) {
return false;
}
return true;
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
final Card source = sa.getHostCard();
String validP = "";
final String damage = sa.getParam("NumDmg");
int dmg = AbilityUtils.calculateAmount(sa.getHostCard(), damage, sa);
if (damage.equals("X") && sa.getSVar(damage).equals("Count$xPaid")) {
// Set PayX here to maximum value.
dmg = ComputerUtilMana.determineLeftoverMana(sa, ai);
source.setSVar("PayX", Integer.toString(dmg));
}
if (sa.hasParam("ValidPlayers")) {
validP = sa.getParam("ValidPlayers");
}
// Evaluate creatures getting killed
Player enemy = ai.getOpponent();
final CardCollection humanList = getKillableCreatures(sa, enemy, dmg);
CardCollection computerList = getKillableCreatures(sa, ai, dmg);
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null && sa.canTarget(enemy)) {
sa.resetTargets();
sa.getTargets().add(enemy);
computerList.clear();
}
// Don't get yourself killed
if (validP.contains("Each") && (ai.getLife() <= ComputerUtilCombat.predictDamageTo(ai, dmg, source, false))) {
return false;
}
// if we can kill human, do it
if ((validP.contains("Each") || validP.contains("EachOpponent") || validP.contains("Targeted"))
&& (enemy.getLife() <= ComputerUtilCombat.predictDamageTo(enemy, dmg, source, false))) {
return true;
}
if (!computerList.isEmpty() && ComputerUtilCard.evaluateCreatureList(computerList) > ComputerUtilCard
.evaluateCreatureList(humanList)) {
return false;
}
return true;
}
/**
* <p>
* getKillableCreatures.
* </p>
*
* @param af
* a {@link forge.game.ability.AbilityFactory} object.
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @param player
* a {@link forge.game.player.Player} object.
* @param dmg
* a int.
* @return a {@link forge.CardList} object.
*/
private CardCollection getKillableCreatures(final SpellAbility sa, final Player player, final int dmg) {
final Card source = sa.getHostCard();
String validC = sa.hasParam("ValidCards") ? sa.getParam("ValidCards") : "";
// TODO: X may be something different than X paid
CardCollection list =
CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), validC.split(","), source.getController(), source);
final Predicate<Card> filterKillable = new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return (ComputerUtilCombat.predictDamageTo(c, dmg, source, false) >= ComputerUtilCombat.getDamageToKill(c));
}
};
list = CardLists.getNotKeyword(list, "Indestructible");
list = CardLists.filter(list, filterKillable);
return list;
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final Card source = sa.getHostCard();
String validP = "";
final String damage = sa.getParam("NumDmg");
int dmg = AbilityUtils.calculateAmount(sa.getHostCard(), damage, sa);
if (damage.equals("X") && sa.getSVar(damage).equals("Count$xPaid")) {
// Set PayX here to maximum value.
dmg = ComputerUtilMana.determineLeftoverMana(sa, ai);
source.setSVar("PayX", Integer.toString(dmg));
}
if (sa.hasParam("ValidPlayers")) {
validP = sa.getParam("ValidPlayers");
}
// Evaluate creatures getting killed
Player enemy = ai.getOpponent();
final CardCollection humanList = getKillableCreatures(sa, enemy, dmg);
CardCollection computerList = getKillableCreatures(sa, ai, dmg);
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null && sa.canTarget(enemy)) {
sa.resetTargets();
sa.getTargets().add(enemy);
computerList.clear();
}
// If it's not mandatory check a few things
if (mandatory) {
return true;
}
// Don't get yourself killed
if (validP.contains("Each") && (ai.getLife() <= ComputerUtilCombat.predictDamageTo(ai, dmg, source, false))) {
return false;
}
// if we can kill human, do it
if ((validP.contains("Each") || validP.contains("EachOpponent") || validP.contains("Targeted"))
&& (enemy.getLife() <= ComputerUtilCombat.predictDamageTo(enemy, dmg, source, false))) {
return true;
}
if (!computerList.isEmpty() && ComputerUtilCard.evaluateCreatureList(computerList) + 50 >= ComputerUtilCard
.evaluateCreatureList(humanList)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,613 @@
package forge.ai.ability;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import forge.ai.*;
import forge.game.Game;
import forge.game.GameObject;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.cost.Cost;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetChoices;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.Aggregates;
import java.util.List;
public class DamageDealAi extends DamageAiBase {
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
final String damage = sa.getParam("NumDmg");
int dmg = AbilityUtils.calculateAmount(sa.getHostCard(), damage, sa);
final Card source = sa.getHostCard();
if (damage.equals("X") && sa.getSVar(damage).equals("Count$xPaid")) {
// Set PayX here to maximum value.
dmg = ComputerUtilMana.determineLeftoverMana(sa, ai);
source.setSVar("PayX", Integer.toString(dmg));
}
if (!this.damageTargetAI(ai, sa, dmg)) {
return false;
}
return true;
}
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Cost abCost = sa.getPayCosts();
final Card source = sa.getHostCard();
final String damage = sa.getParam("NumDmg");
int dmg = AbilityUtils.calculateAmount(sa.getHostCard(), damage, sa);
if ((damage.equals("X") && sa.getSVar(damage).equals("Count$xPaid") ||
sa.getHostCard().getName().equals("Crater's Claws"))) {
// Set PayX here to maximum value.
dmg = ComputerUtilMana.determineLeftoverMana(sa, ai);
source.setSVar("PayX", Integer.toString(dmg));
}
if (sa.getHostCard().getName().equals("Crater's Claws") && ai.hasFerocious()) {
dmg += 2;
}
String logic = sa.getParam("AILogic");
if ("DiscardLands".equals(logic)) {
dmg = 2;
} else if ("WildHunt".equals(logic)) {
// This dummy ability will just deal 0 damage, but holds the logic for the AI for Master of Wild Hunt
List<Card> wolves = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), "Creature.Wolf+untapped+YouCtrl+Other", ai, source);
dmg = Aggregates.sum(wolves, CardPredicates.Accessors.fnGetNetPower);
}
if (dmg <= 0) {
return false;
}
// temporarily disabled until better AI
if (!ComputerUtilCost.checkLifeCost(ai, abCost, source, 4, null)) {
return false;
}
if (!ComputerUtilCost.checkSacrificeCost(ai, abCost, source)) {
return false;
}
if (!ComputerUtilCost.checkRemoveCounterCost(abCost, source)) {
return false;
}
if ("DiscardLands".equals(sa.getParam("AILogic")) && !ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
return false;
}
if (ComputerUtil.preventRunAwayActivations(sa)) {
return false;
}
if (!this.damageTargetAI(ai, sa, dmg)) {
return false;
}
if ((damage.equals("X") && source.getSVar(damage).equals("Count$xPaid")) ||
sa.getHostCard().getName().equals("Crater's Claws")){
// If I can kill my target by paying less mana, do it
if (sa.usesTargeting() && !sa.getTargets().isTargetingAnyPlayer() && !sa.hasParam("DividedAsYouChoose")) {
int actualPay = 0;
final boolean noPrevention = sa.hasParam("NoPrevention");
for (final Card c : sa.getTargets().getTargetCards()) {
final int adjDamage = ComputerUtilCombat.getEnoughDamageToKill(c, dmg, source, false, noPrevention);
if ((adjDamage > actualPay) && (adjDamage <= dmg)) {
actualPay = adjDamage;
}
}
if (sa.getHostCard().getName().equals("Crater's Claws") && ai.hasFerocious()) {
actualPay = actualPay > 2 ? actualPay - 2 : 0;
}
source.setSVar("PayX", Integer.toString(actualPay));
}
}
return true;
}
/**
* <p>
* dealDamageChooseTgtC.
* </p>
*
* @param d
* a int.
* @param noPrevention
* a boolean.
* @param pl
* a {@link forge.game.player.Player} object.
* @param mandatory
* a boolean.
* @return a {@link forge.game.card.Card} object.
*/
private Card dealDamageChooseTgtC(final Player ai, final SpellAbility sa, final int d, final boolean noPrevention,
final Player pl, final boolean mandatory) {
// wait until stack is empty (prevents duplicate kills)
if (!sa.isTrigger() && !ai.getGame().getStack().isEmpty()) {
//TODO:all removal APIs require a check to prevent duplicate kill/bounce/exile/etc.
// The original code is a blunt instrument that also blocks all use of removal as interrupts. The issue is
// with the AI not having code to consider what occurred previously in the stack thus it has no memory of
// removing a target already if something else is placed on top of the stack. A better solution is to place
// the checking mechanism after the target is chosen and determine if the topstack invalidates the earlier
// removal (shroud effect, pump against damage) so a new removal can/should be applied if possible.
//return null;
}
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
List<Card> hPlay = CardLists.getValidCards(pl.getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, source);
final List<GameObject> objects = Lists.newArrayList(sa.getTargets().getTargets());
if (sa.hasParam("TargetUnique")) {
objects.addAll(sa.getUniqueTargets());
}
for (final Object o : objects) {
if (o instanceof Card) {
final Card c = (Card) o;
if (hPlay.contains(c)) {
hPlay.remove(c);
}
}
}
hPlay = CardLists.getTargetableCards(hPlay, sa);
final List<Card> killables = CardLists.filter(hPlay, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return (ComputerUtilCombat.getEnoughDamageToKill(c, d, source, false, noPrevention) <= d) && !ComputerUtil.canRegenerate(ai, c)
&& !(c.getSVar("SacMe").length() > 0);
}
});
Card targetCard;
if (pl.isOpponentOf(ai) && !killables.isEmpty()) {
targetCard = ComputerUtilCard.getBestCreatureAI(killables);
return targetCard;
}
if (!mandatory) {
return null;
}
if (!hPlay.isEmpty()) {
if (pl.isOpponentOf(ai)) {
targetCard = ComputerUtilCard.getBestCreatureAI(hPlay);
} else {
targetCard = ComputerUtilCard.getWorstCreatureAI(hPlay);
}
return targetCard;
}
return null;
}
/**
* <p>
* damageTargetAI.
* </p>
*
* @param saMe
* a {@link forge.game.spellability.SpellAbility} object.
* @param dmg
* a int.
* @return a boolean.
*/
private boolean damageTargetAI(final Player ai, final SpellAbility saMe, final int dmg) {
final TargetRestrictions tgt = saMe.getTargetRestrictions();
if (tgt == null) {
return this.damageChooseNontargeted(ai, saMe, dmg);
}
if (tgt.isRandomTarget()) {
return false;
}
return this.damageChoosingTargets(ai, saMe, tgt, dmg, false, false);
}
/**
* <p>
* damageChoosingTargets.
* </p>
*
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @param tgt
* a {@link forge.game.spellability.TargetRestrictions} object.
* @param dmg
* a int.
* @param mandatory
* a boolean.
* @return a boolean.
*/
private boolean damageChoosingTargets(final Player ai, final SpellAbility sa, final TargetRestrictions tgt, int dmg,
final boolean isTrigger, final boolean mandatory) {
final Card source = sa.getHostCard();
final boolean noPrevention = sa.hasParam("NoPrevention");
final Game game = source.getGame();
final PhaseHandler phase = game.getPhaseHandler();
final boolean divided = sa.hasParam("DividedAsYouChoose");
final boolean oppTargetsChoice = sa.hasParam("TargetingPlayer");
Player enemy = ai.getOpponent();
if ("PowerDmg".equals(sa.getParam("AILogic"))) {
// check if it is better to target the player instead, the original target is already set in PumpAi.pumpTgtAI()
if (tgt.canTgtCreatureAndPlayer() && this.shouldTgtP(ai, sa, dmg, noPrevention)){
sa.resetTargets();
sa.getTargets().add(enemy);
}
return true;
}
sa.resetTargets();
// target loop
TargetChoices tcs = sa.getTargets();
if (tgt.getMaxTargets(source, sa) <= 0) {
return false;
}
if ("ChoiceBurn".equals(sa.getParam("AILogic"))) {
// do not waste burns on player if other choices are present
if (this.shouldTgtP(ai, sa, dmg, noPrevention)) {
tcs.add(enemy);
return true;
} else {
return false;
}
}
if ("Polukranos".equals(sa.getParam("AILogic"))) {
int dmgTaken = 0;
CardCollection humCreatures = ai.getOpponent().getCreaturesInPlay();
Card lastTgt = null;
humCreatures = CardLists.getTargetableCards(humCreatures, sa);
ComputerUtilCard.sortByEvaluateCreature(humCreatures);
// try to kill things without dying
for (Card humanCreature : humCreatures) {
if (FightAi.canKill(humanCreature, source, dmgTaken)) {
continue;
}
final int assignedDamage = ComputerUtilCombat.getEnoughDamageToKill(humanCreature, dmg, source, false, noPrevention);
if (assignedDamage <= dmg
&& humanCreature.getShieldCount() == 0 && !ComputerUtil.canRegenerate(humanCreature.getController(), humanCreature)) {
tcs.add(humanCreature);
tgt.addDividedAllocation(humanCreature, assignedDamage);
lastTgt = humanCreature;
dmg -= assignedDamage;
}
if (!source.hasProtectionFrom(humanCreature)) {
dmgTaken += humanCreature.getNetPower();
}
if (dmg == 0) {
return true;
}
}
if (dmg > 0 && lastTgt != null) {
tgt.addDividedAllocation(lastTgt, tgt.getDividedValue(lastTgt) + dmg);
dmg = 0;
return true;
}
// get safe target to dump damage
for (Card humanCreature : humCreatures) {
if (FightAi.canKill(humanCreature, source, 0)) {
continue;
}
tcs.add(humanCreature);
tgt.addDividedAllocation(humanCreature, dmg);
dmg = 0;
return true;
}
}
while (tcs.getNumTargeted() < tgt.getMaxTargets(source, sa)) {
if (oppTargetsChoice && sa.getActivatingPlayer().equals(ai) && !sa.isTrigger()) {
// canPlayAI (sa activated by ai)
Player targetingPlayer = AbilityUtils.getDefinedPlayers(source, sa.getParam("TargetingPlayer"), sa).get(0);
sa.setTargetingPlayer(targetingPlayer);
return targetingPlayer.getController().chooseTargetsFor(sa);
}
if (tgt.canTgtCreatureAndPlayer()) {
if (this.shouldTgtP(ai, sa, dmg, noPrevention)) {
tcs.add(enemy);
if (divided) {
tgt.addDividedAllocation(enemy, dmg);
break;
}
continue;
}
final Card c = this.dealDamageChooseTgtC(ai, sa, dmg, noPrevention, enemy, false);
if (c != null) {
//option to hold removal instead only applies for single targeted removal
if (sa.isSpell() && tgt.getMaxTargets(sa.getHostCard(), sa) == 1 && !divided) {
if (!ComputerUtilCard.useRemovalNow(sa, c, dmg, ZoneType.Graveyard)) {
return false;
}
}
tcs.add(c);
if (divided) {
final int assignedDamage = ComputerUtilCombat.getEnoughDamageToKill(c, dmg, source, false, noPrevention);
if (assignedDamage <= dmg) {
tgt.addDividedAllocation(c, assignedDamage);
}
dmg = dmg - assignedDamage;
if (dmg <= 0) {
break;
}
}
continue;
}
// When giving priority to targeting Creatures for mandatory
// triggers
// feel free to add the Human after we run out of good targets
// TODO: add check here if card is about to die from something
// on the stack
// or from taking combat damage
if (!source.isSpell()){
boolean freePing = isTrigger || sa.getPayCosts() == null || sa.getTargets().getNumTargeted() > 0
|| ComputerUtil.playImmediately(ai, sa);
if (phase.is(PhaseType.END_OF_TURN) && sa.isAbility()) {
if (phase.getNextTurn().equals(ai))
freePing = true;
}
if (phase.is(PhaseType.MAIN2) && sa.isAbility()) {
if (sa.getRestrictions().isPwAbility() || source.hasSVar("EndOfTurnLeavePlay"))
freePing = true;
}
if (freePing && sa.canTarget(enemy)) {
tcs.add(enemy);
if (divided) {
tgt.addDividedAllocation(enemy, dmg);
break;
}
}
}
} else if (tgt.canTgtCreature()) {
final Card c = this.dealDamageChooseTgtC(ai, sa, dmg, noPrevention, enemy, mandatory);
if (c != null) {
//option to hold removal instead only applies for single targeted removal
if (!sa.isTrigger() && tgt.getMaxTargets(sa.getHostCard(), sa) == 1 && !divided) {
if (!ComputerUtilCard.useRemovalNow(sa, c, dmg, ZoneType.Graveyard)) {
return false;
}
}
tcs.add(c);
if (divided) {
final int assignedDamage = ComputerUtilCombat.getEnoughDamageToKill(c, dmg, source, false, noPrevention);
if (assignedDamage <= dmg) {
tgt.addDividedAllocation(c, assignedDamage);
} else {
tgt.addDividedAllocation(c, dmg);
}
dmg = dmg - assignedDamage;
if (dmg <= 0) {
break;
}
}
continue;
}
} else if ("OppAtTenLife".equals(sa.getParam("AILogic"))) {
for (final Player p : ai.getOpponents()) {
if (sa.canTarget(p) && p.getLife() == 10 && tcs.getNumTargeted() < tgt.getMaxTargets(source, sa)) {
tcs.add(p);
}
}
}
// TODO: Improve Damage, we shouldn't just target the player just
// because we can
else if (sa.canTarget(enemy)) {
if ((phase.is(PhaseType.END_OF_TURN) && phase.getNextTurn().equals(ai))
|| (SpellAbilityAi.isSorcerySpeed(sa) && phase.is(PhaseType.MAIN2))
|| sa.getPayCosts() == null || isTrigger
|| this.shouldTgtP(ai, sa, dmg, noPrevention)) {
sa.getTargets().add(enemy);
if (divided) {
tgt.addDividedAllocation(enemy, dmg);
break;
}
continue;
}
}
// fell through all the choices, no targets left?
if (sa.getTargets().getNumTargeted() < tgt.getMinTargets(source, sa) || sa.getTargets().getNumTargeted() == 0) {
if (!mandatory) {
sa.resetTargets();
return false;
} else {
// If the trigger is mandatory, gotta choose my own stuff now
return this.damageChooseRequiredTargets(ai, sa, tgt, dmg, mandatory);
}
} else {
// TODO is this good enough? for up to amounts?
break;
}
}
return true;
}
/**
* <p>
* damageChooseNontargeted.
* </p>
* @param ai
*
* @param saMe
* a {@link forge.game.spellability.SpellAbility} object.
* @param dmg
* a int.
* @return a boolean.
*/
private boolean damageChooseNontargeted(Player ai, final SpellAbility saMe, final int dmg) {
// TODO: Improve circumstances where the Defined Damage is unwanted
final List<GameObject> objects = AbilityUtils.getDefinedObjects(saMe.getHostCard(), saMe.getParam("Defined"), saMe);
boolean urgent = false; // can it wait?
boolean positive = false;
for (final Object o : objects) {
if (o instanceof Card) {
Card c = (Card) o;
final int restDamage = ComputerUtilCombat.predictDamageTo(c, dmg, saMe.getHostCard(), false);
if (!c.hasKeyword("Indestructible") && ComputerUtilCombat.getDamageToKill(c) <= restDamage) {
if (c.getController().equals(ai)) {
return false;
} else {
urgent = true;
}
}
if (c.getController().isOpponentOf(ai) ^ c.getName().equals("Stuffy Doll")) {
positive = true;
}
} else if (o instanceof Player) {
final Player p = (Player) o;
final int restDamage = ComputerUtilCombat.predictDamageTo(p, dmg, saMe.getHostCard(), false);
if (!p.isOpponentOf(ai) && p.canLoseLife() && restDamage + 3 >= p.getLife() && restDamage > 0) {
// from this spell will kill me
return false;
}
if (p.isOpponentOf(ai) && p.canLoseLife()) {
positive = true;
if (p.getLife() + 3 <= restDamage) {
urgent = true;
}
}
}
}
if (!positive && !(saMe instanceof AbilitySub)) {
return false;
}
if (!urgent && !SpellAbilityAi.playReusable(ai, saMe)) {
return false;
}
return true;
}
/**
* <p>
* damageChooseRequiredTargets.
* </p>
*
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @param tgt
* a {@link forge.game.spellability.TargetRestrictions} object.
* @param dmg
* a int.
* @param mandatory
* a boolean.
* @return a boolean.
*/
private boolean damageChooseRequiredTargets(final Player ai, final SpellAbility sa, final TargetRestrictions tgt, final int dmg,
final boolean mandatory) {
// this is for Triggered targets that are mandatory
final boolean noPrevention = sa.hasParam("NoPrevention");
final boolean divided = sa.hasParam("DividedAsYouChoose");
while (sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) {
// TODO: Consider targeting the planeswalker
if (tgt.canTgtCreature()) {
final Card c = this.dealDamageChooseTgtC(ai, sa, dmg, noPrevention, ai, mandatory);
if (c != null) {
sa.getTargets().add(c);
if (divided) {
tgt.addDividedAllocation(c, dmg);
break;
}
continue;
}
}
if (sa.canTarget(ai)) {
if (sa.getTargets().add(ai)) {
if (divided) {
tgt.addDividedAllocation(ai, dmg);
break;
}
continue;
}
}
// if we get here then there isn't enough targets, this is the only
// time we can return false
return false;
}
return true;
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final Card source = sa.getHostCard();
final String damage = sa.getParam("NumDmg");
int dmg = AbilityUtils.calculateAmount(source, damage, sa);
// Remove all damage
if (sa.hasParam("Remove")) {
return true;
}
if (damage.equals("X") && sa.getSVar(damage).equals("Count$xPaid")) {
// Set PayX here to maximum value.
dmg = ComputerUtilMana.determineLeftoverMana(sa, ai);
source.setSVar("PayX", Integer.toString(dmg));
}
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt == null) {
// If it's not mandatory check a few things
if (!mandatory && !this.damageChooseNontargeted(ai, sa, dmg)) {
return false;
}
} else {
if (!this.damageChoosingTargets(ai, sa, tgt, dmg, true, mandatory) && !mandatory) {
return false;
}
if (damage.equals("X") && source.getSVar(damage).equals("Count$xPaid") && !sa.hasParam("DividedAsYouChoose")) {
// If I can kill my target by paying less mana, do it
int actualPay = 0;
final boolean noPrevention = sa.hasParam("NoPrevention");
//target is a player
if (!sa.getTargets().isTargetingAnyCard()) {
actualPay = dmg;
}
for (final Card c : sa.getTargets().getTargetCards()) {
final int adjDamage = ComputerUtilCombat.getEnoughDamageToKill(c, dmg, source, false, noPrevention);
if (adjDamage > actualPay) {
actualPay = adjDamage;
}
}
source.setSVar("PayX", Integer.toString(actualPay));
}
}
return true;
}
}

View File

@@ -0,0 +1,43 @@
package forge.ai.ability;
import forge.game.ability.AbilityUtils;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
public class DamageEachAi extends DamageAiBase {
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null && sa.canTarget(ai.getOpponent())) {
sa.resetTargets();
sa.getTargets().add(ai.getOpponent());
}
final String damage = sa.getParam("NumDmg");
final int iDmg = AbilityUtils.calculateAmount(sa.getHostCard(), damage, sa);
return this.shouldTgtP(ai, sa, iDmg, false);
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player aiPlayer) {
// check AI life before playing this drawback?
return true;
}
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#doTriggerAINoCost(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility, boolean)
*/
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
return canPlayAI(ai, sa);
}
}

View File

@@ -0,0 +1,226 @@
package forge.ai.ability;
import forge.ai.*;
import forge.game.Game;
import forge.game.GameObject;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.combat.Combat;
import forge.game.cost.Cost;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetChoices;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import java.util.ArrayList;
import java.util.List;
public class DamagePreventAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Card hostCard = sa.getHostCard();
final Game game = ai.getGame();
final Combat combat = game.getCombat();
boolean chance = false;
final Cost cost = sa.getPayCosts();
// temporarily disabled until better AI
if (!ComputerUtilCost.checkLifeCost(ai, cost, hostCard, 4, null)) {
return false;
}
if (!ComputerUtilCost.checkDiscardCost(ai, cost, hostCard)) {
return false;
}
if (!ComputerUtilCost.checkSacrificeCost(ai, cost, hostCard)) {
return false;
}
if (!ComputerUtilCost.checkRemoveCounterCost(cost, hostCard)) {
return false;
}
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt == null) {
// As far as I can tell these Defined Cards will only have one of
// them
final List<GameObject> objects = AbilityUtils.getDefinedObjects(sa.getHostCard(), sa.getParam("Defined"), sa);
// react to threats on the stack
if (!game.getStack().isEmpty()) {
final List<GameObject> threatenedObjects = ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), sa);
for (final Object o : objects) {
if (threatenedObjects.contains(o)) {
chance = true;
}
}
} else {
PhaseHandler handler = game.getPhaseHandler();
if (handler.is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
boolean flag = false;
for (final Object o : objects) {
if (o instanceof Card) {
flag |= ComputerUtilCombat.combatantWouldBeDestroyed(ai, (Card) o, combat);
} else if (o instanceof Player) {
// Don't need to worry about Combat Damage during AI's turn
final Player p = (Player) o;
if (!handler.isPlayerTurn(p)) {
flag |= (p == ai && ((ComputerUtilCombat.wouldLoseLife(ai, combat) && sa
.isAbility()) || ComputerUtilCombat.lifeInDanger(ai, combat)));
}
}
}
chance = flag;
} else { // if nothing on the stack, and it's not declare
// blockers. no need to prevent
return false;
}
}
} // non-targeted
// react to threats on the stack
else if (!game.getStack().isEmpty()) {
sa.resetTargets();
final TargetChoices tcs = sa.getTargets();
// check stack for something on the stack will kill anything i control
final List<GameObject> objects = ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), sa);
if (objects.contains(ai)) {
tcs.add(ai);
chance = true;
}
final List<Card> threatenedTargets = new ArrayList<Card>();
// filter AIs battlefield by what I can target
List<Card> targetables = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, hostCard);
targetables = CardLists.getTargetableCards(targetables, sa);
for (final Card c : targetables) {
if (objects.contains(c)) {
threatenedTargets.add(c);
}
}
if (!threatenedTargets.isEmpty()) {
// Choose "best" of the remaining to save
tcs.add(ComputerUtilCard.getBestCreatureAI(threatenedTargets));
chance = true;
}
} // Protect combatants
else if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
sa.resetTargets();
final TargetChoices tcs = sa.getTargets();
if (sa.canTarget(ai) && ComputerUtilCombat.wouldLoseLife(ai, combat)
&& (ComputerUtilCombat.lifeInDanger(ai, combat) || sa.isAbility() || sa.isTrigger())
&& game.getPhaseHandler().getPlayerTurn().isOpponentOf(ai)) {
tcs.add(ai);
chance = true;
} else {
// filter AIs battlefield by what I can target
CardCollectionView targetables = ai.getCardsIn(ZoneType.Battlefield);
targetables = CardLists.getValidCards(targetables, tgt.getValidTgts(), ai, hostCard);
targetables = CardLists.getTargetableCards(targetables, sa);
if (targetables.isEmpty()) {
return false;
}
final CardCollection combatants = CardLists.filter(targetables, CardPredicates.Presets.CREATURES);
ComputerUtilCard.sortByEvaluateCreature(combatants);
for (final Card c : combatants) {
if (ComputerUtilCombat.combatantWouldBeDestroyed(ai, c, combat) && tcs.getNumTargeted() < tgt.getMaxTargets(hostCard, sa)) {
tcs.add(c);
chance = true;
}
}
}
}
if (sa.hasParam("DividedAsYouChoose") && sa.getTargets() != null && !sa.getTargets().getTargets().isEmpty()) {
tgt.addDividedAllocation(sa.getTargets().getTargets().get(0), AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("Amount"), sa));
}
return chance;
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
boolean chance = false;
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt == null) {
// If there's no target on the trigger, just say yes.
chance = true;
} else {
chance = preventDamageMandatoryTarget(ai, sa, mandatory);
}
return chance;
}
/**
* <p>
* preventDamageMandatoryTarget.
* </p>
*
* @param af
* a {@link forge.game.ability.AbilityFactory} object.
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @param mandatory
* a boolean.
* @return a boolean.
*/
private boolean preventDamageMandatoryTarget(final Player ai, final SpellAbility sa, final boolean mandatory) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
sa.resetTargets();
// filter AIs battlefield by what I can target
final Game game = ai.getGame();
CardCollectionView targetables = game.getCardsIn(ZoneType.Battlefield);
targetables = CardLists.getValidCards(targetables, tgt.getValidTgts(), ai, sa.getHostCard());
final List<Card> compTargetables = CardLists.filterControlledBy(targetables, ai);
Card target = null;
if (targetables.isEmpty()) {
return false;
}
if (!mandatory && compTargetables.isEmpty()) {
return false;
}
if (!compTargetables.isEmpty()) {
final CardCollection combatants = CardLists.filter(compTargetables, CardPredicates.Presets.CREATURES);
ComputerUtilCard.sortByEvaluateCreature(combatants);
if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
Combat combat = game.getCombat();
for (final Card c : combatants) {
if (ComputerUtilCombat.combatantWouldBeDestroyed(ai, c, combat)) {
target = c;
break;
}
}
}
if (target == null) {
target = combatants.get(0);
}
} else {
target = ComputerUtilCard.getCheapestPermanentAI(targetables, sa, true);
}
sa.getTargets().add(target);
if (sa.hasParam("DividedAsYouChoose")) {
tgt.addDividedAllocation(target, AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("Amount"), sa));
}
return true;
}
}

View File

@@ -1,13 +1,13 @@
package forge.card.ability.ai;
package forge.ai.ability;
import forge.Card;
import forge.card.ability.SpellAbilityAi;
import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility;
import forge.game.ai.ComputerUtilCost;
import forge.ai.ComputerUtilCost;
import forge.ai.SpellAbilityAi;
import forge.game.card.Card;
import forge.game.cost.Cost;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
public class DamagePreventAllAi extends SpellAbilityAi {
@@ -16,7 +16,7 @@ public class DamagePreventAllAi extends SpellAbilityAi {
*/
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Card hostCard = sa.getSourceCard();
final Card hostCard = sa.getHostCard();
boolean chance = false;
final Cost cost = sa.getPayCosts();

View File

@@ -0,0 +1,287 @@
package forge.ai.ability;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCost;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.combat.Combat;
import forge.game.cost.Cost;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class DebuffAi extends SpellAbilityAi {
// *************************************************************************
// ***************************** Debuff ************************************
// *************************************************************************
@Override
protected boolean canPlayAI(final Player ai, final SpellAbility sa) {
// if there is no target and host card isn't in play, don't activate
final Card source = sa.getHostCard();
final Game game = ai.getGame();
if ((sa.getTargetRestrictions() == null) && !source.isInPlay()) {
return false;
}
final Cost cost = sa.getPayCosts();
// temporarily disabled until AI is improved
if (!ComputerUtilCost.checkCreatureSacrificeCost(ai, cost, source)) {
return false;
}
if (!ComputerUtilCost.checkLifeCost(ai, cost, source, 40, null)) {
return false;
}
if (!ComputerUtilCost.checkRemoveCounterCost(cost, source)) {
return false;
}
final PhaseHandler ph = game.getPhaseHandler();
// Phase Restrictions
if (ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)
|| !game.getStack().isEmpty()) {
// Instant-speed pumps should not be cast outside of combat when the
// stack is empty
if (!SpellAbilityAi.isSorcerySpeed(sa)) {
return false;
}
}
if (!sa.usesTargeting() || !sa.getTargetRestrictions().doesTarget()) {
List<Card> cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
final Combat combat = game.getCombat();
return Iterables.any(cards, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
if (c.getController().equals(sa.getActivatingPlayer()) || combat == null)
return false;
if (!combat.isBlocking(c) && !combat.isAttacking(c)) {
return false;
}
// don't add duplicate negative keywords
return sa.hasParam("Keywords") && c.hasAnyKeyword(Arrays.asList(sa.getParam("Keywords").split(" & ")));
}
});
} else {
return debuffTgtAI(ai, sa, sa.hasParam("Keywords") ? Arrays.asList(sa.getParam("Keywords").split(" & ")) : null, false);
}
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
if ((sa.getTargetRestrictions() == null) || !sa.getTargetRestrictions().doesTarget()) {
// TODO - copied from AF_Pump.pumpDrawbackAI() - what should be
// here?
} else {
return debuffTgtAI(ai, sa, sa.hasParam("Keywords") ? Arrays.asList(sa.getParam("Keywords").split(" & ")) : null, false);
}
return true;
} // debuffDrawbackAI()
/**
* <p>
* debuffTgtAI.
* </p>
*
* @param af
* a {@link forge.game.ability.AbilityFactory} object.
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @param kws
* a {@link java.util.ArrayList} object.
* @param mandatory
* a boolean.
* @return a boolean.
*/
private boolean debuffTgtAI(final Player ai, final SpellAbility sa, final List<String> kws, final boolean mandatory) {
// this would be for evasive things like Flying, Unblockable, etc
if (!mandatory && ai.getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
return false;
}
final TargetRestrictions tgt = sa.getTargetRestrictions();
sa.resetTargets();
CardCollection list = getCurseCreatures(ai, sa, kws == null ? Lists.<String>newArrayList() : kws);
list = CardLists.getValidCards(list, tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getHostCard());
// several uses here:
// 1. make human creatures lose evasion when they are attacking
// 2. make human creatures lose Flying/Horsemanship/Shadow/etc. when
// Comp is attacking
// 3. remove Indestructible keyword so it can be destroyed?
// 3a. remove Persist?
if (list.isEmpty()) {
return mandatory && debuffMandatoryTarget(ai, sa, mandatory);
}
while (sa.getTargets().getNumTargeted() < tgt.getMaxTargets(sa.getHostCard(), sa)) {
Card t = null;
// boolean goodt = false;
if (list.isEmpty()) {
if ((sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) || (sa.getTargets().getNumTargeted() == 0)) {
if (mandatory) {
return debuffMandatoryTarget(ai, sa, mandatory);
}
sa.resetTargets();
return false;
} else {
// TODO is this good enough? for up to amounts?
break;
}
}
t = ComputerUtilCard.getBestCreatureAI(list);
sa.getTargets().add(t);
list.remove(t);
}
return true;
} // pumpTgtAI()
/**
* <p>
* getCurseCreatures.
* </p>
*
* @param af
* a {@link forge.game.ability.AbilityFactory} object.
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @param kws
* a {@link java.util.ArrayList} object.
* @return a {@link forge.CardList} object.
*/
private CardCollection getCurseCreatures(final Player ai, final SpellAbility sa, final List<String> kws) {
final Player opp = ai.getOpponent();
CardCollection list = CardLists.getTargetableCards(opp.getCreaturesInPlay(), sa);
if (!list.isEmpty()) {
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.hasAnyKeyword(kws); // don't add duplicate negative
// keywords
}
});
}
return list;
} // getCurseCreatures()
/**
* <p>
* debuffMandatoryTarget.
* </p>
*
* @param af
* a {@link forge.game.ability.AbilityFactory} object.
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @param mandatory
* a boolean.
* @return a boolean.
*/
private boolean debuffMandatoryTarget(final Player ai, final SpellAbility sa, final boolean mandatory) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
CardCollection list = CardLists.getValidCards(ai.getGame().getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getHostCard());
if (list.size() < tgt.getMinTargets(sa.getHostCard(), sa)) {
sa.resetTargets();
return false;
}
// Remove anything that's already been targeted
for (final Card c : sa.getTargets().getTargetCards()) {
list.remove(c);
}
final CardCollection pref = CardLists.filterControlledBy(list, ai.getOpponent());
final CardCollection forced = CardLists.filterControlledBy(list, ai);
final Card source = sa.getHostCard();
while (sa.getTargets().getNumTargeted() < tgt.getMaxTargets(source, sa)) {
if (pref.isEmpty()) {
break;
}
Card c;
if (CardLists.getNotType(pref, "Creature").size() == 0) {
c = ComputerUtilCard.getBestCreatureAI(pref);
} else {
c = ComputerUtilCard.getMostExpensivePermanentAI(pref, sa, true);
}
pref.remove(c);
sa.getTargets().add(c);
}
while (sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) {
if (forced.isEmpty()) {
break;
}
// TODO - if forced targeting, just pick something without the given
// keyword
Card c;
if (CardLists.getNotType(forced, "Creature").size() == 0) {
c = ComputerUtilCard.getWorstCreatureAI(forced);
} else {
c = ComputerUtilCard.getCheapestPermanentAI(forced, sa, true);
}
forced.remove(c);
sa.getTargets().add(c);
}
if (sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) {
sa.resetTargets();
return false;
}
return true;
} // pumpMandatoryTarget()
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final List<String> kws = sa.hasParam("Keywords") ? Arrays.asList(sa.getParam("Keywords").split(" & ")) : new ArrayList<String>();
if (sa.getTargetRestrictions() == null) {
if (mandatory) {
return true;
}
} else {
return debuffTgtAI(ai, sa, kws, mandatory);
}
return true;
}
}

View File

@@ -0,0 +1,54 @@
package forge.ai.ability;
import forge.ai.AiController;
import forge.ai.AiPlayDecision;
import forge.ai.PlayerControllerAi;
import forge.ai.SpellAbilityAi;
import forge.ai.SpellApiToAi;
import forge.game.ability.AbilityFactory;
import forge.game.player.Player;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
public class DelayedTriggerAi extends SpellAbilityAi {
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
if ("Always".equals(sa.getParam("AILogic"))) {
// TODO: improve ai
return true;
}
final String svarName = sa.getParam("Execute");
final SpellAbility trigsa = AbilityFactory.getAbility(sa.getHostCard().getSVar(svarName), sa.getHostCard());
trigsa.setActivatingPlayer(ai);
if (trigsa instanceof AbilitySub) {
return SpellApiToAi.Converter.get(((AbilitySub) trigsa).getApi()).chkDrawbackWithSubs(ai, (AbilitySub)trigsa);
} else {
return AiPlayDecision.WillPlay == ((PlayerControllerAi)ai.getController()).getAi().canPlaySa(trigsa);
}
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final String svarName = sa.getParam("Execute");
final SpellAbility trigsa = AbilityFactory.getAbility(sa.getHostCard().getSVar(svarName), sa.getHostCard());
AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
trigsa.setActivatingPlayer(ai);
if (!sa.hasParam("OptionalDecider")) {
return aic.doTrigger(trigsa, true);
} else {
return aic.doTrigger(trigsa, !sa.getParam("OptionalDecider").equals("You"));
}
}
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final String svarName = sa.getParam("Execute");
final SpellAbility trigsa = AbilityFactory.getAbility(sa.getSVar(svarName), sa.getHostCard());
trigsa.setActivatingPlayer(ai);
return AiPlayDecision.WillPlay == ((PlayerControllerAi)ai.getController()).getAi().canPlaySa(trigsa);
}
}

View File

@@ -0,0 +1,339 @@
package forge.ai.ability;
import com.google.common.base.Predicate;
import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCost;
import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.card.CounterType;
import forge.game.cost.Cost;
import forge.game.cost.CostPart;
import forge.game.cost.CostSacrifice;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
public class DestroyAi extends SpellAbilityAi {
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
return canPlayAI(ai, sa);
}
@Override
protected boolean canPlayAI(final Player ai, SpellAbility sa) {
// AI needs to be expanded, since this function can be pretty complex
// based on what the expected targets could be
final Cost abCost = sa.getPayCosts();
final TargetRestrictions abTgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
final boolean noRegen = sa.hasParam("NoRegen");
final String logic = sa.getParam("AILogic");
CardCollection list;
if (abCost != null) {
if (!ComputerUtilCost.checkSacrificeCost(ai, abCost, source)) {
return false;
}
if (!ComputerUtilCost.checkLifeCost(ai, abCost, source, 4, null)) {
return false;
}
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
return false;
}
}
if (ComputerUtil.preventRunAwayActivations(sa)) {
return false;
}
// Targeting
if (abTgt != null) {
sa.resetTargets();
if (sa.hasParam("TargetingPlayer")) {
Player targetingPlayer = AbilityUtils.getDefinedPlayers(source, sa.getParam("TargetingPlayer"), sa).get(0);
sa.setTargetingPlayer(targetingPlayer);
return targetingPlayer.getController().chooseTargetsFor(sa);
}
list = CardLists.getTargetableCards(ai.getOpponent().getCardsIn(ZoneType.Battlefield), sa);
list = CardLists.getValidCards(list, abTgt.getValidTgts(), source.getController(), source);
if (sa.hasParam("AITgts")) {
if (sa.getParam("AITgts").equals("BetterThanSource")) {
if (source.isEnchanted()) {
if (source.getEnchantedBy(false).get(0).getController().equals(ai)) {
return false;
}
} else {
final int value = ComputerUtilCard.evaluateCreature(source);
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return ComputerUtilCard.evaluateCreature(c) > value + 30;
}
});
}
} else {
list = CardLists.getValidCards(list, sa.getParam("AITgts"), sa.getActivatingPlayer(), source);
}
}
list = CardLists.getNotKeyword(list, "Indestructible");
if (!SpellAbilityAi.playReusable(ai, sa)) {
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
//Check for cards that can be sacrificed in response
for (final SpellAbility ability : c.getAllSpellAbilities()) {
if (ability.isAbility()) {
final Cost cost = ability.getPayCosts();
for (final CostPart part : cost.getCostParts()) {
if (!(part instanceof CostSacrifice)) {
continue;
}
CostSacrifice sacCost = (CostSacrifice) part;
if (sacCost.payCostFromSource() && ComputerUtilCost.canPayCost(ability, c.getController())) {
return false;
}
}
}
}
if (c.hasSVar("SacMe")) {
return false;
}
//Check for undying
return (!c.hasKeyword("Undying") || c.getCounters(CounterType.P1P1) > 0);
}
});
}
// If NoRegen is not set, filter out creatures that have a
// regeneration shield
if (!noRegen) {
// TODO filter out things that might be tougher?
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return (c.getShieldCount() == 0 && !ComputerUtil.canRegenerate(ai, c));
}
});
}
if (list.isEmpty()) {
return false;
}
// target loop
while (sa.getTargets().getNumTargeted() < abTgt.getMaxTargets(sa.getHostCard(), sa)) {
if (list.size() == 0) {
if ((sa.getTargets().getNumTargeted() < abTgt.getMinTargets(sa.getHostCard(), sa))
|| (sa.getTargets().getNumTargeted() == 0)) {
sa.resetTargets();
return false;
} else {
// TODO is this good enough? for up to amounts?
break;
}
}
Card choice = null;
// If the targets are only of one type, take the best
if (CardLists.getNotType(list, "Creature").isEmpty()) {
choice = ComputerUtilCard.getBestCreatureAI(list);
if ("OppDestroyYours".equals(logic)) {
Card aiBest = ComputerUtilCard.getBestCreatureAI(ai.getCreaturesInPlay());
if (ComputerUtilCard.evaluateCreature(aiBest) > ComputerUtilCard.evaluateCreature(choice) - 40) {
return false;
}
}
if ("Pongify".equals(logic)) {
Card token = TokenAi.spawnToken(ai.getOpponent(), sa.getSubAbility());
if (source.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS) || //prevent surprise combatant
ComputerUtilCard.evaluateCreature(choice) < 1.5 * ComputerUtilCard.evaluateCreature(token)) {
return false;
}
}
}
else if (CardLists.getNotType(list, "Land").isEmpty()) {
choice = ComputerUtilCard.getBestLandAI(list);
}
else {
choice = ComputerUtilCard.getMostExpensivePermanentAI(list, sa, true);
}
//option to hold removal instead only applies for single targeted removal
if (!sa.isTrigger() && abTgt.getMaxTargets(sa.getHostCard(), sa) == 1) {
if (!ComputerUtilCard.useRemovalNow(sa, choice, 0, ZoneType.Graveyard)) {
return false;
}
}
if (choice == null) { // can't find anything left
if ((sa.getTargets().getNumTargeted() < abTgt.getMinTargets(sa.getHostCard(), sa))
|| (sa.getTargets().getNumTargeted() == 0)) {
sa.resetTargets();
return false;
} else {
// TODO is this good enough? for up to amounts?
break;
}
} else {
// Don't destroy stolen permanents when the stealing aura can be destroyed
if (choice.getOwner() == ai) {
for (Card aura : choice.getEnchantedBy(false)) {
SpellAbility sp = aura.getFirstSpellAbility();
if (sp != null && "GainControl".equals(sp.getParam("AILogic"))
&& aura.getController() != ai && sa.canTarget(aura)) {
choice = aura;
}
}
}
}
list.remove(choice);
sa.getTargets().add(choice);
}
}
else if (sa.hasParam("Defined")) {
list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa);
if ("WillSkipTurn".equals(logic) && (sa.getHostCard().getController().equals(ai)
|| ai.getCreaturesInPlay().size() < ai.getOpponent().getCreaturesInPlay().size()
|| !source.getGame().getPhaseHandler().isPlayerTurn(ai)
|| ai.getLife() <= 5)) {
// Basic ai logic for Lethal Vapors
return false;
}
if (list.isEmpty()
|| !CardLists.filterControlledBy(list, ai).isEmpty()
|| CardLists.getNotKeyword(list, "Indestructible").isEmpty()) {
return false;
}
}
return true;
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
final boolean noRegen = sa.hasParam("NoRegen");
if (tgt != null) {
sa.resetTargets();
CardCollection list = CardLists.getTargetableCards(ai.getGame().getCardsIn(ZoneType.Battlefield), sa);
list = CardLists.getValidCards(list, tgt.getValidTgts(), source.getController(), source);
if (list.isEmpty() || list.size() < tgt.getMinTargets(sa.getHostCard(), sa)) {
return false;
}
CardCollection preferred = CardLists.getNotKeyword(list, "Indestructible");
preferred = CardLists.filterControlledBy(preferred, ai.getOpponents());
// If NoRegen is not set, filter out creatures that have a
// regeneration shield
if (!noRegen) {
// TODO filter out things that could regenerate in response?
// might be tougher?
preferred = CardLists.filter(preferred, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.getShieldCount() == 0;
}
});
}
if (sa.hasParam("AITgts")) {
if (sa.getParam("AITgts").equals("BetterThanSource")) {
if (source.isEnchanted()) {
if (source.getEnchantedBy(false).get(0).getController().equals(ai)) {
preferred.clear();
}
} else {
final int value = ComputerUtilCard.evaluateCreature(source);
preferred = CardLists.filter(preferred, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return ComputerUtilCard.evaluateCreature(c) > value + 30;
}
});
}
} else {
preferred = CardLists.getValidCards(preferred, sa.getParam("AITgts"), sa.getActivatingPlayer(), source);
}
}
for (final Card c : preferred) {
list.remove(c);
}
if (preferred.isEmpty() && !mandatory) {
return false;
}
while (sa.getTargets().getNumTargeted() < tgt.getMaxTargets(sa.getHostCard(), sa)) {
if (preferred.isEmpty()) {
if (sa.getTargets().getNumTargeted() == 0
|| sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) {
if (!mandatory) {
sa.resetTargets();
return false;
} else {
break;
}
} else {
break;
}
} else {
Card c;
if (CardLists.getNotType(preferred, "Creature").isEmpty()) {
c = ComputerUtilCard.getBestCreatureAI(preferred);
} else if (CardLists.getNotType(preferred, "Land").isEmpty()) {
c = ComputerUtilCard.getBestLandAI(preferred);
} else {
c = ComputerUtilCard.getMostExpensivePermanentAI(preferred, sa, false);
}
sa.getTargets().add(c);
preferred.remove(c);
}
}
while (sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) {
if (list.isEmpty()) {
break;
} else {
Card c;
if (CardLists.getNotType(list, "Creature").isEmpty()) {
if (!sa.getUniqueTargets().isEmpty() && sa.getParent().getApi() == ApiType.Destroy
&& sa.getUniqueTargets().get(0) instanceof Card) {
// basic ai for Diaochan
c = (Card) sa.getUniqueTargets().get(0);
} else {
c = ComputerUtilCard.getWorstCreatureAI(list);
}
} else {
c = ComputerUtilCard.getCheapestPermanentAI(list, sa, false);
}
sa.getTargets().add(c);
list.remove(c);
}
}
if (sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) {
return false;
}
} else {
if (!mandatory) {
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,157 @@
package forge.ai.ability;
import com.google.common.base.Predicate;
import forge.ai.*;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.cost.Cost;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.game.combat.Combat;
public class DestroyAllAi extends SpellAbilityAi {
private static final Predicate<Card> predicate = new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return !(c.hasKeyword("Indestructible") || c.getSVar("SacMe").length() > 0);
}
};
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#doTriggerAINoCost(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility, boolean)
*/
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final Card source = sa.getHostCard();
String valid = "";
if (mandatory) {
return true;
}
if (sa.hasParam("ValidCards")) {
valid = sa.getParam("ValidCards");
}
CardCollection humanlist = CardLists.getValidCards(ai.getOpponent().getCardsIn(ZoneType.Battlefield), valid.split(","), source.getController(), source);
CardCollection computerlist = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid.split(","), source.getController(), source);
if (sa.usesTargeting()) {
sa.resetTargets();
sa.getTargets().add(ai.getOpponent());
computerlist.clear();
}
humanlist = CardLists.filter(humanlist, predicate);
computerlist = CardLists.filter(computerlist, predicate);
if (humanlist.isEmpty() && !computerlist.isEmpty()) {
return false;
}
// if only creatures are affected evaluate both lists and pass only if
// human creatures are more valuable
if ((CardLists.getNotType(humanlist, "Creature").size() == 0) && (CardLists.getNotType(computerlist, "Creature").size() == 0)) {
if (ComputerUtilCard.evaluateCreatureList(computerlist) >= ComputerUtilCard.evaluateCreatureList(humanlist)
&& !computerlist.isEmpty()) {
return false;
}
} // otherwise evaluate both lists by CMC and pass only if human
// permanents are more valuable
else if (ComputerUtilCard.evaluatePermanentList(computerlist) >= ComputerUtilCard.evaluatePermanentList(humanlist)) {
return false;
}
return true;
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player aiPlayer) {
//TODO: Check for bad outcome
return true;
}
@Override
protected boolean canPlayAI(final Player ai, SpellAbility sa) {
// AI needs to be expanded, since this function can be pretty complex
// based on what the expected targets could be
final Cost abCost = sa.getPayCosts();
final Card source = sa.getHostCard();
String valid = "";
if (sa.hasParam("ValidCards")) {
valid = sa.getParam("ValidCards");
}
if (valid.contains("X") && source.getSVar("X").equals("Count$xPaid")) {
// Set PayX here to maximum value.
final int xPay = ComputerUtilMana.determineLeftoverMana(sa, ai);
source.setSVar("PayX", Integer.toString(xPay));
valid = valid.replace("X", Integer.toString(xPay));
}
CardCollection humanlist = CardLists.getValidCards(ai.getOpponent().getCardsIn(ZoneType.Battlefield), valid.split(","), source.getController(), source);
CardCollection computerlist = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid.split(","), source.getController(), source);
if (sa.usesTargeting()) {
sa.resetTargets();
sa.getTargets().add(ai.getOpponent());
computerlist.clear();
}
humanlist = CardLists.filter(humanlist, predicate);
computerlist = CardLists.filter(computerlist, predicate);
if (abCost != null) {
// AI currently disabled for some costs
if (!ComputerUtilCost.checkLifeCost(ai, abCost, source, 4, null)) {
return false;
}
}
// prevent run-away activations - first time will always return true
if (ComputerUtil.preventRunAwayActivations(sa)) {
return false;
}
// if only creatures are affected evaluate both lists and pass only if
// human creatures are more valuable
if (CardLists.getNotType(humanlist, "Creature").isEmpty() && CardLists.getNotType(computerlist, "Creature").isEmpty()) {
if (ComputerUtilCard.evaluateCreatureList(computerlist) + 200 < ComputerUtilCard.evaluateCreatureList(humanlist)) {
return true;
}
if (ai.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)) {
return false;
}
// test whether the human can kill the ai next turn
Combat combat = new Combat(ai.getOpponent());
for (Card att : ai.getOpponent().getCreaturesInPlay()) {
combat.addAttacker(att, ai);
}
AiBlockController block = new AiBlockController(ai);
block.assignBlockersForCombat(combat);
if (ComputerUtilCombat.lifeInSeriousDanger(ai, combat)) {
return true;
}
return false;
} // only lands involved
else if (CardLists.getNotType(humanlist, "Land").isEmpty() && CardLists.getNotType(computerlist, "Land").isEmpty()) {
if (ai.isCardInPlay("Crucible of Worlds") && !ai.getOpponent().isCardInPlay("Crucible of Worlds") && !humanlist.isEmpty()) {
return true;
}
if (ComputerUtilCard.evaluatePermanentList(computerlist) + 1 >= ComputerUtilCard.evaluatePermanentList(humanlist)) {
return false;
}
} // otherwise evaluate both lists by CMC and pass only if human permanents are more valuable
else if ((ComputerUtilCard.evaluatePermanentList(computerlist) + 3) >= ComputerUtilCard
.evaluatePermanentList(humanlist)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,108 @@
package forge.ai.ability;
import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilCard;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
public class DigAi extends SpellAbilityAi {
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Game game = ai.getGame();
Player opp = ai.getOpponent();
final Card host = sa.getHostCard();
Player libraryOwner = ai;
if (sa.usesTargeting()) {
sa.resetTargets();
if (!opp.canBeTargetedBy(sa)) {
return false;
} else {
sa.getTargets().add(opp);
}
libraryOwner = opp;
}
// return false if nothing to dig into
if (libraryOwner.getCardsIn(ZoneType.Library).isEmpty()) {
return false;
}
if ("Never".equals(sa.getParam("AILogic"))) {
return false;
}
// don't deck yourself
if (sa.hasParam("DestinationZone2") && !"Library".equals(sa.getParam("DestinationZone2"))) {
int numToDig = AbilityUtils.calculateAmount(host, sa.getParam("DigNum"), sa);
if (libraryOwner == ai && ai.getCardsIn(ZoneType.Library).size() <= numToDig + 2) {
return false;
}
}
// Don't use draw abilities before main 2 if possible
if (game.getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2) && !sa.hasParam("ActivationPhases")
&& !sa.hasParam("DestinationZone") && !ComputerUtil.castSpellInMain1(ai, sa)) {
return false;
}
if (SpellAbilityAi.playReusable(ai, sa)) {
return true;
}
if ((!game.getPhaseHandler().getNextTurn().equals(ai)
|| game.getPhaseHandler().getPhase().isBefore(PhaseType.END_OF_TURN))
&& !sa.hasParam("PlayerTurn") && !SpellAbilityAi.isSorcerySpeed(sa)
&& ai.getCardsIn(ZoneType.Hand).size() > 1
&& !ComputerUtil.activateForCost(sa, ai)) {
return false;
}
return !ComputerUtil.preventRunAwayActivations(sa);
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final Player opp = ai.getOpponent();
if (sa.usesTargeting()) {
sa.resetTargets();
if (mandatory && sa.canTarget(opp)) {
sa.getTargets().add(opp);
} else if (mandatory && sa.canTarget(ai)) {
sa.getTargets().add(ai);
}
}
return true;
}
@Override
public Card chooseSingleCard(Player ai, SpellAbility sa, Iterable<Card> valid, boolean isOptional, Player relatedPlayer) {
Card chosen = ComputerUtilCard.getBestAI(valid);
if (sa.getActivatingPlayer().isOpponentOf(ai) && relatedPlayer.isOpponentOf(ai)) {
return ComputerUtilCard.getWorstAI(valid);
}
return chosen;
}
/* (non-Javadoc)
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
*/
@Override
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
// looks like perfect code for Delver of Secrets, but what about other cards?
Card topc = player.getZone(ZoneType.Library).get(0);
return topc.isInstant() || topc.isSorcery();
}
}

View File

@@ -0,0 +1,117 @@
package forge.ai.ability;
import forge.ai.ComputerUtilMana;
import forge.ai.SpellAbilityAi;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class DigUntilAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
Card source = sa.getHostCard();
double chance = .4; // 40 percent chance with instant speed stuff
if (SpellAbilityAi.isSorcerySpeed(sa)) {
chance = .667; // 66.7% chance for sorcery speed (since it will
// never activate EOT)
}
final Random r = MyRandom.getRandom();
final boolean randomReturn = r.nextFloat() <= Math.pow(chance, sa.getActivationsThisTurn() + 1);
Player libraryOwner = ai;
Player opp = ai.getOpponent();
if (sa.usesTargeting()) {
sa.resetTargets();
if (!sa.canTarget(opp)) {
return false;
} else {
sa.getTargets().add(opp);
}
libraryOwner = opp;
} else {
if (sa.hasParam("Valid")) {
final String valid = sa.getParam("Valid");
if (CardLists.getValidCards(ai.getCardsIn(ZoneType.Library), valid.split(","), source.getController(), source).isEmpty()) {
return false;
}
}
}
final String num = sa.getParam("Amount");
if ((num != null) && num.equals("X") && source.getSVar(num).equals("Count$xPaid")) {
// Set PayX here to maximum value.
if (!(sa instanceof AbilitySub) || source.getSVar("PayX").equals("")) {
int numCards = ComputerUtilMana.determineLeftoverMana(sa, ai);
if (numCards <= 0) {
return false;
}
source.setSVar("PayX", Integer.toString(numCards));
}
}
// return false if nothing to dig into
if (libraryOwner.getCardsIn(ZoneType.Library).isEmpty()) {
return false;
}
return randomReturn;
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
if (sa.usesTargeting()) {
sa.resetTargets();
if (sa.isCurse()) {
for (Player opp : ai.getOpponents()) {
if (sa.canTarget(opp)) {
sa.getTargets().add(opp);
break;
}
}
if (mandatory && sa.getTargets().isEmpty() && sa.canTarget(ai)) {
sa.getTargets().add(ai);
}
} else {
if (sa.canTarget(ai)) {
sa.getTargets().add(ai);
}
}
}
return true;
}
/* (non-Javadoc)
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
*/
@Override
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
if (sa.hasParam("AILogic")) {
final String logic = sa.getParam("AILogic");
if ("OathOfDruids".equals(logic)) {
final List<Card> creaturesInLibrary =
CardLists.filter(player.getCardsIn(ZoneType.Library), CardPredicates.Presets.CREATURES);
final List<Card> creaturesInBattlefield =
CardLists.filter(player.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
// if there are at least 3 creatures in library,
// or none in play with one in library, oath
return creaturesInLibrary.size() > 2
|| (creaturesInBattlefield.size() == 0 && creaturesInLibrary.size() > 0);
}
}
return true;
}
}

View File

@@ -1,29 +1,29 @@
package forge.card.ability.ai;
package forge.ai.ability;
import java.util.List;
import java.util.Random;
import forge.Card;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi;
import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana;
import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilCost;
import forge.ai.ComputerUtilMana;
import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.cost.Cost;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class DiscardAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Target tgt = sa.getTarget();
final Card source = sa.getSourceCard();
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
final Cost abCost = sa.getPayCosts();
if (abCost != null) {
@@ -54,8 +54,7 @@ public class DiscardAi extends SpellAbilityAi {
}
} else {
// TODO: Add appropriate restrictions
final List<Player> players = AbilityUtils.getDefinedPlayers(sa.getSourceCard(),
sa.getParam("Defined"), sa);
final List<Player> players = AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Defined"), sa);
if (players.size() == 1) {
if (players.get(0) == ai) {
@@ -85,7 +84,7 @@ public class DiscardAi extends SpellAbilityAi {
}
source.setSVar("PayX", Integer.toString(cardsToDiscard));
} else {
if (AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("NumCards"), sa) < 1) {
if (AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("NumCards"), sa) < 1) {
return false;
}
}
@@ -113,14 +112,14 @@ public class DiscardAi extends SpellAbilityAi {
} // discardCanPlayAI()
private boolean discardTargetAI(final Player ai, final SpellAbility sa) {
final Target tgt = sa.getTarget();
final TargetRestrictions tgt = sa.getTargetRestrictions();
Player opp = ai.getOpponent();
if (opp.getCardsIn(ZoneType.Hand).isEmpty()) {
if (opp.getCardsIn(ZoneType.Hand).isEmpty() && !ComputerUtil.activateForCost(sa, ai)) {
return false;
}
if (tgt != null) {
if (sa.canTarget(opp)) {
tgt.addTarget(opp);
sa.getTargets().add(opp);
return true;
}
}
@@ -131,24 +130,32 @@ public class DiscardAi extends SpellAbilityAi {
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final Target tgt = sa.getTarget();
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
Player opp = ai.getOpponent();
if (!discardTargetAI(ai, sa)) {
if (mandatory && sa.canTarget(opp)) {
tgt.addTarget(opp);
sa.getTargets().add(opp);
} else if (mandatory && sa.canTarget(ai)) {
tgt.addTarget(ai);
sa.getTargets().add(ai);
} else {
return false;
}
}
} else {
if ("X".equals(sa.getParam("RevealNumber")) && sa.getSourceCard().getSVar("X").equals("Count$xPaid")) {
if (sa.hasParam("AILogic")) {
if ("AtLeast2".equals(sa.getParam("AILogic"))) {
final List<Player> players = AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Defined"), sa);
if (players.isEmpty() || players.get(0).getCardsIn(ZoneType.Hand).size() < 2) {
return false;
}
}
}
if ("X".equals(sa.getParam("RevealNumber")) && sa.getHostCard().getSVar("X").equals("Count$xPaid")) {
// Set PayX here to maximum value.
final int cardsToDiscard = Math.min(ComputerUtilMana.determineLeftoverMana(sa, ai), ai.getOpponent()
.getCardsIn(ZoneType.Hand).size());
sa.getSourceCard().setSVar("PayX", Integer.toString(cardsToDiscard));
sa.getHostCard().setSVar("PayX", Integer.toString(cardsToDiscard));
}
}
@@ -159,7 +166,7 @@ public class DiscardAi extends SpellAbilityAi {
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
// Drawback AI improvements
// if parent draws cards, make sure cards in hand + cards drawn > 0
final Target tgt = sa.getTarget();
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
return discardTargetAI(ai, sa);
}

View File

@@ -0,0 +1,91 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class DrainManaAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
// AI cannot use this properly until he can use SAs during Humans turn
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
final Player opp = ai.getOpponent();
final Random r = MyRandom.getRandom();
boolean randomReturn = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
if (tgt == null) {
// assume we are looking to tap human's stuff
// TODO - check for things with untap abilities, and don't tap
// those.
final List<Player> defined = AbilityUtils.getDefinedPlayers(source, sa.getParam("Defined"), sa);
if (!defined.contains(opp)) {
return false;
}
} else {
sa.resetTargets();
sa.getTargets().add(opp);
}
return randomReturn;
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final Player opp = ai.getOpponent();
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
if (null == tgt) {
if (mandatory) {
return true;
} else {
final List<Player> defined = AbilityUtils.getDefinedPlayers(source, sa.getParam("Defined"), sa);
if (!defined.contains(opp)) {
return false;
}
}
return true;
} else {
sa.resetTargets();
sa.getTargets().add(opp);
}
return true;
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
// AI cannot use this properly until he can use SAs during Humans turn
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
boolean randomReturn = true;
if (tgt == null) {
final List<Player> defined = AbilityUtils.getDefinedPlayers(source, sa.getParam("Defined"), sa);
if (defined.contains(ai)) {
return false;
}
} else {
sa.resetTargets();
sa.getTargets().add(ai.getOpponent());
}
return randomReturn;
}
}

View File

@@ -16,30 +16,23 @@
* 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.ability.ai;
package forge.ai.ability;
import java.util.List;
import java.util.Random;
import forge.Card;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi;
import forge.card.cost.Cost;
import forge.card.cost.CostDiscard;
import forge.card.cost.CostPart;
import forge.card.cost.PaymentDecision;
import forge.card.spellability.AbilitySub;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.ai.*;
import forge.game.Game;
import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.cost.Cost;
import forge.game.cost.CostDiscard;
import forge.game.cost.CostPart;
import forge.game.cost.PaymentDecision;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
public class DrawAi extends SpellAbilityAi {
@@ -53,8 +46,8 @@ public class DrawAi extends SpellAbilityAi {
*/
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Target tgt = sa.getTarget();
final Card source = sa.getSourceCard();
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
final Cost abCost = sa.getPayCosts();
final Game game = ai.getGame();
@@ -69,10 +62,10 @@ public class DrawAi extends SpellAbilityAi {
}
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
AiCostDecision aiDecisions = new AiCostDecision(ai, sa);
for (final CostPart part : abCost.getCostParts()) {
if (part instanceof CostDiscard) {
CostDiscard cd = (CostDiscard) part;
PaymentDecision decision = cd.decideAIPayment(ai, sa, sa.getSourceCard());
PaymentDecision decision = part.accept(aiDecisions);
if ( null == decision )
return false;
for (Card discard : decision.cards) {
@@ -95,12 +88,25 @@ public class DrawAi extends SpellAbilityAi {
}
if (tgt != null) {
final List<Player> players = tgt.getTargetPlayers();
if ((players.size() > 0) && players.get(0).isOpponentOf(ai)) {
final Player player = sa.getTargets().getFirstTargetedPlayer();
if (player != null && player.isOpponentOf(ai)) {
return true;
}
}
// prevent run-away activations - first time will always return true
if (ComputerUtil.preventRunAwayActivations(sa)) {
return false;
}
if (ComputerUtil.playImmediately(ai, sa)) {
return true;
}
if (sa.getConditions() != null && !sa.getConditions().areMet(sa) && sa.getSubAbility() == null) {
return false;
}
// Don't use draw abilities before main 2 if possible
if (game.getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)
&& !sa.hasParam("ActivationPhases") && !ComputerUtil.castSpellInMain1(ai, sa)) {
@@ -110,7 +116,7 @@ public class DrawAi extends SpellAbilityAi {
|| game.getPhaseHandler().getPhase().isBefore(PhaseType.END_OF_TURN))
&& !sa.hasParam("PlayerTurn") && !SpellAbilityAi.isSorcerySpeed(sa)
&& ai.getCardsIn(ZoneType.Hand).size() > 1
&& !ComputerUtil.ActivateForSacCost(sa, ai)) {
&& !ComputerUtil.activateForCost(sa, ai)) {
return false;
}
@@ -119,28 +125,12 @@ public class DrawAi extends SpellAbilityAi {
return false;
}
double chance = .4; // 40 percent chance of drawing with instant speed
// stuff
final Random r = MyRandom.getRandom();
boolean randomReturn = r.nextFloat() <= Math.pow(chance, sa.getActivationsThisTurn() + 1);
if (SpellAbilityAi.isSorcerySpeed(sa)) {
randomReturn = true;
}
if ((game.getPhaseHandler().is(PhaseType.END_OF_TURN)
&& game.getPhaseHandler().getNextTurn().equals(ai))) {
randomReturn = true;
}
if (SpellAbilityAi.playReusable(ai, sa)) {
randomReturn = true;
}
return randomReturn;
return true;
}
private boolean targetAI(final Player ai, final SpellAbility sa, final boolean mandatory) {
final Target tgt = sa.getTarget();
final Card source = sa.getSourceCard();
final TargetRestrictions tgt = sa.getTargetRestrictions();
final Card source = sa.getHostCard();
final boolean drawback = (sa instanceof AbilitySub);
final Game game = ai.getGame();
Player opp = ai.getOpponent();
@@ -157,7 +147,7 @@ public class DrawAi extends SpellAbilityAi {
int numCards = 1;
if (sa.hasParam("NumCards")) {
numCards = AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("NumCards"), sa);
numCards = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("NumCards"), sa);
}
boolean xPaid = false;
@@ -175,12 +165,11 @@ public class DrawAi extends SpellAbilityAi {
//if (n)
// TODO: if xPaid and one of the below reasons would fail, instead of
// bailing
// reduce toPay amount to acceptable level
// bailing reduce toPay amount to acceptable level
if (tgt != null) {
// ability is targeted
tgt.resetTargets();
sa.resetTargets();
final boolean canTgtHuman = sa.canTarget(opp);
final boolean canTgtComp = sa.canTarget(ai);
@@ -192,7 +181,7 @@ public class DrawAi extends SpellAbilityAi {
if (canTgtHuman && !opp.cantLose() && numCards >= humanLibrarySize) {
// Deck the Human? DO IT!
tgt.addTarget(opp);
sa.getTargets().add(opp);
return true;
}
@@ -228,9 +217,9 @@ public class DrawAi extends SpellAbilityAi {
}
if ((!tgtHuman || !canTgtHuman) && canTgtComp) {
tgt.addTarget(ai);
sa.getTargets().add(ai);
} else if (mandatory && canTgtHuman) {
tgt.addTarget(opp);
sa.getTargets().add(opp);
} else {
return false;
}
@@ -275,7 +264,7 @@ public class DrawAi extends SpellAbilityAi {
*/
@Override
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
int numCards = sa.hasParam("NumCards") ? AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("NumCards"), sa) : 1;
int numCards = sa.hasParam("NumCards") ? AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("NumCards"), sa) : 1;
// AI shouldn't mill itself
return numCards < player.getZone(ZoneType.Library).size();
}

View File

@@ -0,0 +1,231 @@
package forge.ai.ability;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCombat;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.combat.CombatUtil;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance;
import forge.game.spellability.TargetRestrictions;
import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.MyRandom;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class EffectAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Game game = ai.getGame();
final Random r = MyRandom.getRandom();
boolean randomReturn = r.nextFloat() <= .6667;
final Player opp = ai.getOpponent();
String logic = "";
if (sa.hasParam("AILogic")) {
logic = sa.getParam("AILogic");
final PhaseHandler phase = game.getPhaseHandler();
if (logic.equals("BeginningOfOppTurn")) {
if (phase.isPlayerTurn(ai) || phase.getPhase().isAfter(PhaseType.DRAW)) {
return false;
}
randomReturn = true;
} else if (logic.equals("EndOfOppTurn")) {
if (phase.isPlayerTurn(ai) || phase.getPhase().isBefore(PhaseType.END_OF_TURN)) {
return false;
}
randomReturn = true;
} else if (logic.equals("Fog")) {
if (game.getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer())) {
return false;
}
if (!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
return false;
}
if (!game.getStack().isEmpty()) {
return false;
}
if (game.getPhaseHandler().isPreventCombatDamageThisTurn()) {
return false;
}
if (!ComputerUtilCombat.lifeInDanger(ai, game.getCombat())) {
return false;
}
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
sa.resetTargets();
List<Card> list = game.getCombat().getAttackers();
list = CardLists.getValidCards(list, tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getHostCard());
list = CardLists.getTargetableCards(list, sa);
Card target = ComputerUtilCard.getBestCreatureAI(list);
if (target == null) {
return false;
}
sa.getTargets().add(target);
}
randomReturn = true;
} else if (logic.equals("ChainVeil")) {
if (!phase.isPlayerTurn(ai) || !phase.getPhase().equals(PhaseType.MAIN2)
|| CardLists.getType(ai.getCardsIn(ZoneType.Battlefield), "Planeswalker").isEmpty()) {
return false;
}
randomReturn = true;
} else if (logic.equals("Always")) {
randomReturn = true;
} else if (logic.equals("Main2")) {
if (phase.getPhase().isBefore(PhaseType.MAIN2)) {
return false;
}
randomReturn = true;
} else if (logic.equals("Evasion")) {
if (!phase.isPlayerTurn(ai)) {
return false;
}
List<Card> comp = ai.getCreaturesInPlay();
List<Card> human = opp.getCreaturesInPlay();
// only count creatures that can attack or block
comp = CardLists.filter(comp, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return CombatUtil.canAttack(c, opp);
}
});
if (comp.size() < 2) {
return false;
}
final List<Card> attackers = comp;
human = CardLists.filter(human, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return CombatUtil.canBlockAtLeastOne(c, attackers);
}
});
if (human.isEmpty()) {
return false;
}
} else if (logic.equals("RedirectSpellDamageFromPlayer")) {
if (game.getStack().isEmpty()) {
return false;
}
boolean threatened = false;
for (final SpellAbilityStackInstance stackInst : game.getStack()) {
if (!stackInst.isSpell()) { continue; }
SpellAbility stackSpellAbility = stackInst.getSpellAbility(true);
if (stackSpellAbility.getApi() == ApiType.DealDamage) {
final SpellAbility saTargeting = stackSpellAbility.getSATargetingPlayer();
if (saTargeting != null && Iterables.contains(saTargeting.getTargets().getTargetPlayers(), ai)) {
threatened = true;
}
}
}
randomReturn = threatened;
}
else if (logic.equals("Fight")) {
CardCollection humCreatures = ai.getOpponent().getCreaturesInPlay();
humCreatures = CardLists.getTargetableCards(humCreatures, sa);
ComputerUtilCard.sortByEvaluateCreature(humCreatures);
final AbilitySub tgtFight = sa.getSubAbility();
CardCollection aiCreatures = ai.getCreaturesInPlay();
aiCreatures = CardLists.getTargetableCards(aiCreatures, tgtFight);
aiCreatures = ComputerUtil.getSafeTargets(ai, tgtFight, aiCreatures);
ComputerUtilCard.sortByEvaluateCreature(aiCreatures);
if (humCreatures.isEmpty() || aiCreatures.isEmpty()) {
return false;
}
int buffedAtk = 0, buffedDef = 0;
for (Card humanCreature : humCreatures) {
for (Card aiCreature : aiCreatures) {
if (sa.isSpell()) { //heroic triggers adding counters
for (Trigger t : aiCreature.getTriggers()) {
if (t.getMode() == TriggerType.SpellCast) {
final Map<String, String> params = t.getMapParams();
if ("Card.Self".equals(params.get("TargetsValid")) && "You".equals(params.get("ValidActivatingPlayer"))
&& params.containsKey("Execute")) {
SpellAbility heroic = AbilityFactory.getAbility(aiCreature.getSVar(params.get("Execute")),aiCreature);
if ("Self".equals(heroic.getParam("Defined")) && "P1P1".equals(heroic.getParam("CounterType"))) {
int amount = AbilityUtils.calculateAmount(aiCreature, heroic.getParam("CounterNum"), heroic);
buffedAtk += amount;
buffedDef += amount;
}
break;
}
}
}
}
if (FightAi.shouldFight(aiCreature, humanCreature, buffedAtk, buffedDef)) {
tgtFight.getTargets().add(aiCreature);
sa.getTargets().add(humanCreature);
return true;
} else {
return false;
}
}
}
}
} else { //no AILogic
return false;
}
if ("False".equals(sa.getParam("Stackable"))) {
String name = sa.getParam("Name");
if (name == null) {
name = sa.getHostCard().getName() + "'s Effect";
}
if (sa.getActivatingPlayer().isCardInCommand(name)) {
return false;
}
}
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null && tgt.canTgtPlayer()) {
sa.resetTargets();
if (tgt.canOnlyTgtOpponent() || logic.equals("BeginningOfOppTurn")) {
sa.getTargets().add(ai.getOpponent());
} else {
sa.getTargets().add(ai);
}
}
return randomReturn;
}
@Override
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
final Player opp = aiPlayer.getOpponent();
if (sa.usesTargeting()) {
sa.resetTargets();
if (mandatory && sa.canTarget(opp)) {
sa.getTargets().add(opp);
} else if (mandatory && sa.canTarget(aiPlayer)) {
sa.getTargets().add(aiPlayer);
}
}
return true;
}
}

View File

@@ -0,0 +1,101 @@
/*
* 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.ai.ability;
import com.google.common.base.Predicate;
import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCombat;
import forge.ai.SpellAbilityAi;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.combat.CombatUtil;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.SpellAbility;
import java.util.List;
/**
* <p>
* AbilityFactoryBond class.
* </p>
*
* @author Forge
* @version $Id: AbilityFactoryBond.java 15090 2012-04-07 12:50:31Z Max mtg $
*/
public final class EncodeAi extends SpellAbilityAi {
/**
* <p>
* bondCanPlayAI.
* </p>
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @param af
* a {@link forge.game.ability.AbilityFactory} object.
*
* @return a boolean.
*/
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
return true;
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
return true;
}
@Override
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
return true;
}
/* (non-Javadoc)
* @see forge.card.ability.SpellAbilityAi#chooseSingleCard(forge.game.player.Player, forge.card.spellability.SpellAbility, java.util.List, boolean)
*/
@Override
public Card chooseSingleCard(final Player ai, SpellAbility sa, Iterable<Card> options, boolean isOptional, Player targetedPlayer) {
Card choice = null;
// final String logic = sa.getParam("AILogic");
// if (logic == null) {
final List<Card> attackers = CardLists.filter(options, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return ComputerUtilCombat.canAttackNextTurn(c);
}
});
final List<Card> unblockables = CardLists.filter(attackers, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return !CombatUtil.canBeBlocked(c, ai.getOpponent());
}
});
if (!unblockables.isEmpty()) {
choice = ComputerUtilCard.getBestAI(unblockables);
} else if (!attackers.isEmpty()) {
choice = ComputerUtilCard.getBestAI(attackers);
} else {
choice = ComputerUtilCard.getBestAI(options);
}
// }
return choice;
}
}

View File

@@ -1,9 +1,9 @@
package forge.card.ability.ai;
package forge.ai.ability;
import forge.card.ability.SpellAbilityAi;
import forge.card.spellability.SpellAbility;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
/**
* TODO: Write javadoc for this type.

View File

@@ -0,0 +1,160 @@
package forge.ai.ability;
import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCombat;
import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.util.MyRandom;
import java.util.List;
import java.util.Random;
public class FightAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
sa.resetTargets();
final Card source = sa.getHostCard();
CardCollectionView aiCreatures = ai.getCreaturesInPlay();
aiCreatures = CardLists.getTargetableCards(aiCreatures, sa);
aiCreatures = ComputerUtil.getSafeTargets(ai, sa, aiCreatures);
List<Card> humCreatures = ai.getOpponent().getCreaturesInPlay();
humCreatures = CardLists.getTargetableCards(humCreatures, sa);
final Random r = MyRandom.getRandom();
if (r.nextFloat() > Math.pow(.6667, sa.getActivationsThisTurn())) {
return false;
}
if (sa.hasParam("FightWithToughness")) {
// TODO: add ailogic
return false;
}
//assumes the triggered card belongs to the ai
if (sa.hasParam("Defined")) {
Card fighter1 = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa).get(0);
for (Card humanCreature : humCreatures) {
if (ComputerUtilCombat.getDamageToKill(humanCreature) <= fighter1.getNetPower()
&& humanCreature.getNetPower() < ComputerUtilCombat.getDamageToKill(fighter1)) {
// todo: check min/max targets; see if we picked the best matchup
sa.getTargets().add(humanCreature);
return true;
} else if (humanCreature.getSVar("Targeting").equals("Dies")) {
sa.getTargets().add(humanCreature);
return true;
}
}
}
if (sa.hasParam("TargetsFromDifferentZone")) {
if (!(humCreatures.isEmpty() && aiCreatures.isEmpty())) {
for (Card humanCreature : humCreatures) {
for (Card aiCreature : aiCreatures) {
if (ComputerUtilCombat.getDamageToKill(humanCreature) <= aiCreature.getNetPower()
&& humanCreature.getNetPower() < ComputerUtilCombat.getDamageToKill(aiCreature)) {
// todo: check min/max targets; see if we picked the best matchup
sa.getTargets().add(humanCreature);
sa.getTargets().add(aiCreature);
return true;
} else if (humanCreature.getSVar("Targeting").equals("Dies")) {
sa.getTargets().add(humanCreature);
sa.getTargets().add(aiCreature);
return true;
}
}
}
}
return false;
}
for (Card creature1 : humCreatures) {
for (Card creature2 : humCreatures) {
if (creature1.equals(creature2)) {
continue;
}
if (sa.hasParam("TargetsWithoutSameCreatureType")
&& creature1.sharesCreatureTypeWith(creature2)) {
continue;
}
if (ComputerUtilCombat.getDamageToKill(creature1) <= creature2.getNetPower()
&& creature1.getNetPower() >= ComputerUtilCombat.getDamageToKill(creature2)) {
// todo: check min/max targets; see if we picked the best matchup
sa.getTargets().add(creature1);
sa.getTargets().add(creature2);
return true;
}
}
}
return false;
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
if (canPlayAI(ai, sa)) {
return true;
}
if (!mandatory) {
return false;
}
//try to make a good trade or no trade
final Card source = sa.getHostCard();
List<Card> humCreatures = ai.getOpponent().getCreaturesInPlay();
humCreatures = CardLists.getTargetableCards(humCreatures, sa);
if (humCreatures.isEmpty()) {
return false;
}
//assumes the triggered card belongs to the ai
if (sa.hasParam("Defined")) {
Card aiCreature = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa).get(0);
for (Card humanCreature : humCreatures) {
if (ComputerUtilCombat.getDamageToKill(humanCreature) <= aiCreature.getNetPower()
&& ComputerUtilCard.evaluateCreature(humanCreature) > ComputerUtilCard.evaluateCreature(aiCreature)) {
sa.getTargets().add(humanCreature);
return true;
}
}
for (Card humanCreature : humCreatures) {
if (ComputerUtilCombat.getDamageToKill(aiCreature) > humanCreature.getNetPower()) {
sa.getTargets().add(humanCreature);
return true;
}
}
sa.getTargets().add(humCreatures.get(0));
return true;
}
return true;
}
public static boolean shouldFight(Card fighter, Card opponent, int pumpAttack, int pumpDefense) {
if (canKill(fighter, opponent, pumpAttack)) {
if (!canKill(opponent, fighter, -pumpDefense)) {
return true;
} else {
final Random r = MyRandom.getRandom();
if (r.nextInt(20)<(opponent.getCMC() - fighter.getCMC())) {
return true;
}
}
}
return false;
}
public static boolean canKill(Card fighter, Card opponent, int pumpAttack) {
if (opponent.getSVar("Targeting").equals("Dies")) {
return true;
}
if (opponent.hasProtectionFrom(fighter) || !opponent.canBeDestroyed()
|| opponent.getShieldCount() > 0 || ComputerUtil.canRegenerate(opponent.getController(), opponent)) {
return false;
}
if (fighter.hasKeyword("Deathtouch") || ComputerUtilCombat.getDamageToKill(opponent) <= fighter.getNetPower() + pumpAttack) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,47 @@
package forge.ai.ability;
import forge.ai.ComputerUtil;
import forge.ai.SpellAbilityAi;
import forge.game.card.Card;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
public class FlipACoinAi extends SpellAbilityAi {
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
if (sa.hasParam("AILogic")) {
String AILogic = sa.getParam("AILogic");
if (AILogic.equals("Never")) {
return false;
} else if (AILogic.equals("PhaseOut")) {
if (!ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), sa).contains(sa.getHostCard())) {
return false;
}
} else if (AILogic.equals("KillOrcs")) {
if (ai.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.END_OF_TURN) ) {
return false;
}
sa.resetTargets();
for (Card c : ai.getOpponent().getCreaturesInPlay()) {
if (sa.canTarget(c)) {
sa.getTargets().add(c);
return true;
}
}
return false;
}
}
return true;
}
@Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
return canPlayAI(ai, sa);
}
}

View File

@@ -1,12 +1,12 @@
package forge.card.ability.ai;
package forge.ai.ability;
import forge.card.ability.SpellAbilityAi;
import forge.card.spellability.SpellAbility;
import forge.ai.ComputerUtilCombat;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.ai.ComputerUtilCombat;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
public class FogAi extends SpellAbilityAi {

View File

@@ -0,0 +1,49 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
public class GameLossAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(Player ai, SpellAbility sa) {
final Player opp = ai.getOpponent();
if (opp.cantLose()) {
return false;
}
// Only one SA Lose the Game card right now, which is Door to
// Nothingness
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
sa.resetTargets();
sa.getTargets().add(opp);
}
// In general, don't return true.
// But this card wins the game, I can make an exception for that
return true;
}
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
// Phage the Untouchable
// (Final Fortune would need to attach it's delayed trigger to a
// specific turn, which can't be done yet)
if (!mandatory && ai.getOpponent().cantLose()) {
return false;
}
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
sa.resetTargets();
sa.getTargets().add(ai.getOpponent());
}
return true;
}
}

View File

@@ -1,9 +1,9 @@
package forge.card.ability.ai;
package forge.ai.ability;
import forge.card.ability.SpellAbilityAi;
import forge.card.spellability.SpellAbility;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
public class GameWinAi extends SpellAbilityAi {
/* (non-Javadoc)

View File

@@ -0,0 +1,29 @@
package forge.ai.ability;
import forge.ai.ComputerUtilCard;
import forge.ai.SpellAbilityAi;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import java.util.List;
public class HauntAi extends SpellAbilityAi {
/* (non-Javadoc)
* @see forge.card.ability.SpellAbilityAi#canPlayAI(forge.game.player.Player, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
return false; // should not get here
}
@Override
public Card chooseSingleCard(Player ai, SpellAbility sa, Iterable<Card> creats, boolean isOptional, Player targetedPlayer) {
final List<Card> oppCreats = CardLists.filterControlledBy(creats, ai.getOpponents());
return ComputerUtilCard.getWorstCreatureAI(oppCreats.isEmpty() ? creats : oppCreats);
}
}

View File

@@ -0,0 +1,39 @@
package forge.ai.ability;
import com.google.common.collect.Iterables;
import forge.ai.SpellAbilityAi;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
/**
* TODO: Write javadoc for this type.
*
*/
public class LegendaryRuleAi extends SpellAbilityAi {
/* (non-Javadoc)
* @see forge.card.ability.SpellAbilityAi#canPlayAI(forge.game.player.Player, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
return false; // should not get here
}
@Override
public Card chooseSingleCard(Player ai, SpellAbility sa, Iterable<Card> options, boolean isOptional, Player targetedPlayer) {
// Choose a single legendary/planeswalker card to keep
Card firstOption = Iterables.getFirst(options, null);
boolean choosingFromPlanewalkers = firstOption.isPlaneswalker();
if ( choosingFromPlanewalkers ) {
// AI decision making - should AI compare counters?
} else {
// AI decision making - should AI compare damage and debuffs?
}
return firstOption;
}
}

View File

@@ -0,0 +1,93 @@
package forge.ai.ability;
import forge.ai.SpellAbilityAi;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom;
import java.util.Random;
public class LifeExchangeAi extends SpellAbilityAi {
/*
* (non-Javadoc)
*
* @see
* forge.card.abilityfactory.AbilityFactoryAlterLife.SpellAiLogic#canPlayAI
* (forge.game.player.Player, java.util.Map,
* forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
final Random r = MyRandom.getRandom();
final int myLife = aiPlayer.getLife();
Player opponent = aiPlayer.getOpponent();
final int hLife = opponent.getLife();
if (!aiPlayer.canGainLife()) {
return false;
}
// prevent run-away activations - first time will always return true
boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
/*
* TODO - There is one card that takes two targets (Soul Conduit)
* and one card that has a conditional (Psychic Transfer) that are
* not currently handled
*/
final TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt != null) {
sa.resetTargets();
if (opponent.canBeTargetedBy(sa)) {
// never target self, that would be silly for exchange
sa.getTargets().add(opponent);
if (!opponent.canLoseLife()) {
return false;
}
}
}
// if life is in danger, always activate
if ((myLife < 5) && (hLife > myLife)) {
return true;
}
// cost includes sacrifice probably, so make sure it's worth it
chance &= (hLife > (myLife + 8));
return ((r.nextFloat() < .6667) && chance);
}
/**
* <p>
* exchangeLifeDoTriggerAINoCost.
* </p>
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @param mandatory
* a boolean.
* @param af
* a {@link forge.game.ability.AbilityFactory} object.
*
* @return a boolean.
*/
@Override
protected boolean doTriggerAINoCost(final Player ai, final SpellAbility sa,
final boolean mandatory) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
Player opp = ai.getOpponent();
if (tgt != null) {
sa.resetTargets();
if (sa.canTarget(opp) && (mandatory || ai.getLife() < opp.getLife())) {
sa.getTargets().add(opp);
} else {
return false;
}
}
return true;
}
}

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