Monday, June 27, 2011

Forge - the Beginning

In the beginning there was no Forge and the world was sad.  The only software available at the time was Shandalar, which ran quite well despite being written in 1997.  The very first part of Forge that I wrote was a simple user interface (ui) because I knew that the whole project was basically a videogame and videogames need to have a good ui. 

My ui skills (and still are) limited and I didn’t know how to show a tapped card.  At the time cards on the battlefield were displayed only as colored boxes, which you can see if Forge cannot find the card picture.  My solution was to stick the word “tapped” inside of the colored box.  In a way it was very ugly but at least the user wouldn’t confuse tapped and untapped cards.

After I got a basic ui working, I knew that I needed a strategy to handle the mouse and it was going to be a pain in the neck.  How was I supposed to restrict targeting possibilities for cards like Terror – no black or artifact creatures or Assissinate – destroy target tapped creature?  And how do I combine the card code and the mouse code?  Thankfully I found the state pattern.  At first the state pattern was a little hard to understand (grok) but after writing some simple code and running it, everything made perfect sense. 

(I wondered how other Magic programs handled the mouse and did they also use the state pattern?  More than likely they didn’t but I have no idea how to handle the mouse without using the state pattern.  You can read more about the state pattern and how I applied it to the mouse here, here and here.)

After I got a basic user interface and mouse working, I added the phases which only consisted of a message stating the phase name.  Just clicking the OK button and watching Forge cycle through the phases was very exciting even though the program didn’t actually do anything yet.  After that I worked on the card class and the “card detail window” which is on the right side and shows all of the card information.  (Ideally the card picture would be created on-the-fly like Magic Online and would have all of correct text information like if your creature was pumped up with Giant Growth.)

Even though the user could see all of the card information, without seeing the actual card picture the user interface was especially bland.  Since I couldn’t display the card picture on the battlefield because I didn’t know how, I had the bright idea to show the card picture in a panel by itself.  While this was only a small step, it really made Forge seem like a real program. 

Tanks for reading,
mtgrares

p.s.
--Actually I did know how to resize the card pictures and put them on the battlefield but I couldn’t figure out how to rotate them.  Thankfully, after a few months somebody sent me a nifty one line fix.

--I tried to use as many design patterns as I could.  “End of turn” effects used the command pattern.  The quest data was saved using the memento pattern.  My advice is to always save data as primitives (ints, Strings) instead of saving whole objects.  That way when you want to change how your data is saved, you can easily read the primitives versus trying to read an older version of an object.

--Forge is probably my 4th iteration at programming Magic.  The first three projects collapsed because of fundamental archetecture problems.

Friday, June 24, 2011

How to Report an Error

1. Go here: http://code.google.com/p/cardforge/issues/list

2. Click "New Issue"

3. If you don't have a Google account, click on the link - "Create an account now".  You don't have to create a new Google email account, you just need a Google username, which is your existing email account like magic_guy@yahoo.com

4. Briefly search for existing open issues with key words from your bug report (e.g. "Sphinx-Bone Wand"). If an issue describing your bug does already exist, you can provide additional information in its comment section.

4. Post your issue by clicking on "new issue". You will receive a template that you can fill out. Under "version", write the release date.  The newest version of Forge that I have posted is 6/24/2011. 

If you downloaded Forge from the forum put the release date of the beta (e.g. "BETA 06/12/2011") or the revision you used to compile your Forge version if you use the SVN (e.g. "Revision 9875"; command: "./svn.exe info forge-svn").

Thanks to UnderFlow for posting these directions.

Friday, June 17, 2011

82,000 Lines of Java


Forge has grown into a big project with 82,000 lines of Java code.  The bigger the project, the harder it is to add to it.  When you are coding a small project, you may code 500 lines a day.  With Forge you probably aren’t adding that many lines of code because the bigger the project, the harder it is to add stuff. 

Adding new features and cards to an existing project is much harder than adding features to a smaller project.  A big project requires you to understand what is going on, which is complicated because of the sheer size of the project.  I am very impressed that a group of developers are still working hard on Forge.  For instance Rob Cashwalker just posted this:

{begin quote}
Following on the success of the Draft mode revisions, I have just completed a rewrite of Sealed Deck mode.

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.

I fixed the main Deck Editor's bad behavior with cards reappearing in the top after clearing the filter. A similar change should be easy to apply to the quest deck editor. I removed the menu options to generate draft and sealed decks, as they are better built from Gui_NewGame. I also added my requested progress bar to the deck editor when loading the full cardpool for constructed mode. I hope to use the progress bar window for during program start-up as well.
{end quote}

(And yes I cut and pasted that just to increase the word count.)

Just played four hours of World of Goo last night.  You can download the demo from here (PC, Mac, Linux).

Stay cool,
mtgrares

p.s.
Cloc was used to count the number of lines of code in Forge.  Cloc says the Forge project has 304 files; 22,000 blank lines (in the source code) and 19,000 lines of comments (more than likely this is old code that was commented out and never removed).

p.p.s.
I’m seeing Kung-Fu Panda 2 right after I get done writing this.  I’m 32 but I still love cartoons.  Just last night I watched Teen Titans, it has great animation.  It is a little creepy when they have adult bad-guys, since they should only have teen villains.  And season 4 that had Raven’s story of becoming the portal for the ultimate evil was very good.  Samurai Jack is great also.

Thursday, June 16, 2011

Nothing New

I didn't post anything new this week.  I'll try to be more on the ball next week.  What topics do you want me to write about?

Monday, June 6, 2011

New Version

(And yes, Forge now has Postmortem Lunge.)

Another great months equals another great version of Forge.  Forge now clocks in with 8,131 cards.  This means that there are 385 new cards, which is insane in the membrane.  There are 117 cards from the New Phyrexia.  There are also a bunch of new white "prevent damage" spells which are always fun to use.

05-31 was the date that this version of Forge was first posted on the forums.  Many thanks to the faithful developers :*)

Link - Forge 05-31 (Windows, Linux) 13 MB

Link - Forge 05-31 (Mac) 8 MB - Use Keka to uncompress 7z files

Link - Quest Opponent Icons - 1 MB - The Mac version needs these pictures, put them in /forge/res/icons/ directory

Download - Card Pictures (160 MB)
These are most of the low-quality (LQ) card pictures.  You can download the rest of the LQ card pictures or the high-quality (HQ) card pictures using the menu on the New Game screen.

Java - in case you need to update or download Java

If you have any questions/comments, please post them to the forum.

-------------------------------------------------------
Below are some of the new cards that were added to Forge.  The nice, large cards pictures are taken from magiccards.info























Many people helped with this version. A special thank you goes out to them:

Sloth
Rob Cashwalker
Slapshot5
Friar Sol
Hellfish
Agetian
Jeff Wadsworth
Jaedayr
SoulStorm
Night Shadow
Chris H
Fnoed
Corwin72
ZzzzSleep
Timmermac
Eidolon
Jhhh

Monday, May 30, 2011

The Magic Stack


I've read countless times that the most confusing part of Magic for beginners to understand is the stack.  When I personally think of a "stack", I picture the little stack of plates at buffet restaurants.  The top is the only place that you can add or remove plates.  Stacks are a common computer programming concept.

When programming Forge I had to decide what type of object would go on the stack?  What information should the stack item store?  I had already created a class called SpellAbility, which represents each spell or ability using the command pattern, which is an abstract execute() method. 

In Forge I put the SpellAbility object on the stack and getSourceCard() which would return the card object that created the spell or ability.  Generally this works very well with Shocks and Giant Growths stacking correctly.  (If I had to do Forge again, I would cheat a little and put Card objects on the stack.  Card.getStackObject() would return a SpellAbility object.  Moving only Card objects around makes some of the programming much easier.)

Obviously as cards become more complicated the stack must become more complicated.  Currently the developer team is redesigning the stack and wrapping SpellAbility with an object called StackItem.  This makes sense because SpellAbility was designed to be added to Card objects and wasn't designed to go on the stack.  By changing Forge's design it will allow more cards to be added.  And hey, everybody loves the smell of fresh cardboard in the morning.

Thanks for reading,
mtgrares

p.s. 
The stack gets very complicated very quickly when you include obscure cases which generate multiple effects which individually go on the stack.  First the active player chooses the order of effects for his cards then the non-active player chooses. 

405.3. If an effect puts two or more objects on the stack at the same time, those controlled by the active player are put on lowest, followed by each other player’s objects in APNAP order (see rule 101.4). If a player controls more than one of these objects, that player chooses their relative order on the stack.

APNAP stands for Active Player, Nonactive Player Order - which means that the active player goes first, then the non-active player.  The active player is "the player whose turn it is" or simply, the player who untapped and drew a card.

Monday, May 23, 2011

Forge Commits

Committing is posting your code from your individual computer to the server where the code is stored.  The Forge project has 50 or more commits a day, which is very impressive.

Every commit is just one small change.  Let's take a look at a few.

The AI will use ZoneAffecting more often at the end of human turn.

This means that the AI will try to use more effects at end of turn.  ZoneAffecting is a scripting keyword which is used to create cards.

Another small step towards Mana Drain script-only.

Harding coding cards is a really big pain, so the more scripting the better.

Fixed Akki Coalflinger. Improved AI of Pyrohemia and Swans of Bryn Argoll.

This commit changed 3 things.  Apparently Akki Coalflinger wasn't working (an update probably broke him) and the AI has a hard time using complex cards like Pyrohemia (which deals damage to all creatures) and Swans of Bryn Argoll, which ignores damage but turns that damage into card drawing (1 damage = 1 card drawn by your opponent).

Doomgape is not correct. It can not be scripted at this time.

I think the comment says it all. 

Converted March of Souls to script. 

March of Souls can be scripted and the java code for the card can be removed.  (I coded March of Souls back in the day because it was so unusual.  It destroys everything like Wrath of God but also creates 1/1 tokens for every creature on the board.  Usually March of Souls was worse than Wrath but in a jam it might help.)

Converted Lorthos the Tidemaker to script.

Always a good thing. 


Added Magus of the Moon and Blood Moon.

Both cards turn non-basic lands into mountains.

Make sure state-based effects are checked when a land is played by either player, not just the computer.

State effects can get very complicated and it is hard to make sure that they are called at the right time.  Basically state effect needs to be called/checked after anything happens in Magic, which is generally when somebody plays a land or an ability/spell is put on the stack or resolved off of the stack.

Forge is composed of literally millions of these small programming changes.  Thanks to the development team for their hard work.