Monday, May 31, 2010

New Version

The easiest column to write each month is this one. I describe the great features of the latest version of Forge. This version has 259 new cards, which means that it supports a grand total of 3,220 cards. All of the credit goes to Dennis, Chris, Slapshot5, Jim, Snacko, and others who have contributed making Forge the outstanding program that it is today.

There is a lot of new stuff. Now the quest mode has another other option, you can either choose “Realistic” or “Fantasy”. Realistic is the old quest mode where you win cards and can buy cards from the card shop. The fantasy option is similar to an RPG because you build up your stats.

The fantasy mode features a “bazaar” where you can buy upgrades for your character including: buying various creatures that you have at the beginning of each game, buying more life (because you start out with 15 but you can have more than 20), or buying a free mulligan (you mulligan and you draw 7 cards). After 25 wins various other “quests” open up for you that feature harder AI opponents. For a taste of the new fantasy quest mode unzip Forge, click on the “Quest Mode” button, and then click on the “Continue Quest” button.

Another cool feature for both quest modes is that each computer opponent now has a small picture next to its life points. Even though this is just a small change, it really improves the “fun level” since the computer opponents vary from Abraham Lincoln to Lisa Simpson.


Forge is all about the cards, so let me list a few of the new ones. A few cards from Rise of the Eldrazi, like the huge artifacts Artisan of Kozilek and Ulamog's Crusher as well as the level up creature Kargan Dragonlord, Valakut, the Molten Pinnacle and the classic Mana Vault which helps you accelerate your mana.

05-16 Forge (9 MB) - Requires Java and runs on Windows, Mac, Linux, etc... This is the 05-16 version because that is when it was released on the forums.

Download Pictures (78 MB) - The card pictures can be downloaded by the Forge program or you can just grab this file. This includes most but not all of the pictures, it doesn't have the newest 259 card pictures.

Have a great Memorial Day! Cookouts for everybody!!

p.s.
The fantasy mode has one more rule that I want to explain. Usually there is a 500 credit limit for cards that you sell but that limit is removed after you win 50 games. (The correction is that you have to win 50 times, my mistake.)

Wednesday, May 26, 2010

How Forge Processes the Mouse - most boring post ever

(This is probably my least exciting article ever. Processing the mouse is very important but very boring. This post is more likely to be interesting to people who want to write a program like Forge.)

Handling the mouse can become very complicated since a "mouse click" can do many different actions depending on the context: choose targets for a spell or ability, advance to the next phase, or is used to declare attacking creatures. Forge uses the state pattern to process all of the mouse input. Without the state pattern I have no idea what I would have done. I think it works well but it can be tricky to understand.

Below is the Input class that handles the mouse. To better understand the Input class let me briefly explain how Forge implements different phases. Each phase extends Input and shows the name of the phase to the user through showMessage(). Usually a phase will let a user do a specific action like the Main phases allow the user to play any type of card or a land. MainInput.selectCard() handles the processing of playing a card or land.

Input class is also used whenever a spell or ability needs to choose a target. The Input for Shock would use showMessage() to show the user a message like "Select target creature or player to receive 2 damage." If the player clicks on a card, selectCard() checks to see is that card a creature. If the user clicks on a player, selectPlayer() is called.
class Input
{
//showMessage() is always the first method called
public void showMessage()
public void selectCard(Card c, PlayerZone zone)
public void selectPlayer(String player)
public void selectButtonOK()
public void selectButtonCancel()
}
There are a few details that I have left out. First, how does an Input tell the rest of the program that it is done and the next Input should be processed? Forge handles all of the Inputs using a stack and the Input class has a method called stop() which just pops the stack. Second, how do the phases advance? I just hardcoded them, nothing fancy. Main 1 always advances to "Before Declare Attackers". When the Main 1 Input method selectButtonOK() is called, it pops itself and pushes the next Input onto the stack.

Since the method showMessage() is always the first method called, I can put code in there that I would usually put into a constructor. Another trick that I do with showMessage() relates to planeswalkers. Forge was written before planeswalkers were added to Magic so it didn't have the concept of "you can only use one of these abilities once a turn" or loyalty counters but I used showMessage() to fake it. I won't show you the code since it is very crufty and hacked-together even by my standards. Where there is a will, there is a way. :--)

Random quote, “Time is a great teacher, but unfortunately it kills all its pupils.”

p.s.
I lied when I said that "Forge handles all of the Inputs like a stack". In reality Forge doesn't stack inputs. It has a stack but it is only one deep. This can be seen if you play two legendary creatures that have an effect when they go to the graveyard like Keiga, the Tide Star. If you play a 2nd Keiga, you only get to steal one creature. And knowing is half the battle. (Yes, I pretend to be funny even though I'm not.)

p.p.s.
The Input class is also used for mulligans.

Monday, May 24, 2010

Coding with Java and Forge

(This article is only about programming but I don't want to discourage non-programmers from reading it too.)

Transmuting an idea into words can be difficult. (Hey, you have to give me extra credit for using a Magic keyword.) The concept is that Forge's cards are technically in Java but cards must also use the Forge framework. If you only know Java, you won't understand how Forge encodes cards. You have to understand how Forge does things.

Let me throw a quote at you from my favorite book Code Complete. This is talking about high-level code that is written in terms of the problem domain, "Code at this level won't depend much on the specific features of your programming language because you'll have built your own set of tools to work with the problem. Consequently, at this level your code depends more on the tools you've built than on the capabilities of the language you're using."

The idea of using an existing framework usually appears in bigger projects but JUnit is a good example of a smaller program. A framework tries to be "easy for someone else to learn" even though it takes time to really understand the framework. There is a ton of interesting Java libraries but many of them have a steep learning curve. I haven't touched the physics library JBox2d because it seems so complicated. (I want to use JBox2d to program a free version of Fantastic Contraption. I don’t want to ripoff their artwork but maybe I could copy their style?) fantasticcontraption.com

OK, back to Magic. When I was writing Forge I didn't realize that I was writing a framework that combined Java and Magic. Somewhere after I wrote a few cards it hit me that Forge's framework isn't very flexible and there are some cards that it would never support. This is always a scary time because part of you wants to start over and do it better but I forged ahead anyways. ("Forged ahead", I'm a really funny guy, I think.)

The tricky thing when writing a framework is that you don't really know all of its limitations. One day you may think, "Forge will never support Glorious Anthem" but then later you (or someone else) comes up with a nifty little hack and voila, you're using Glorious Anthem in your white weenie deck. You have to use a framework for awhile in order to really understand its limits.

Forge's framework is pretty good. There are obviously some rough spots but overall it works "good enough."

p.s.
Code Complete goes on to say that your high level "code should be somewhat readable by someone who's not a computer-science whiz". Forge tries but doesn't quite get a gold star. Although at least 2 people have learned Java just so they could work on Forge, so at least I did a decent job on the framework. Frequently frameworks come with external documentation so you don't have to understand the details of the code in order to use it. This is the Holy Grail of programming, code reuse.

Writing code that someone can understand is hard. Writing a framework (much longer code) that someone else can understand is much harder.

Monday, May 17, 2010

Forge's Awesome AI

It's been awhile since I've talked about "Forge's awesome AI". Basically Forge's AI is very simple. Each spell and ability has a method called canPlayAI() which returns true if the AI should play it. Royal Assassin's ability is a good example. The AI for Royal Assassin's activated ability checks to see if you have any tapped creatures and then targets the biggest one. Shock does about the same thing, except that the code tries to kill X/2 flyers and 3/1 creatures and avoids plain 2/2.

The biggest flaw of canPlayAI() is that each card and ability is evaluated separately. The computer will never use two Shocks to kill a 4/4. Since each card is evaluated individually it is hard to create decks that the AI can use effectively. Generally the AI is good with creatures and basic, aggro decks. One of the decks that I submitted as a deck for the quest AI had all vampire creatures, it did not include any sorceries or instants. Some of the vampires had effects that trigger when you play them, which acted like sorceries. The AI could use the deck because it only had to play creatures and then attack.

Combat is handled completely separate. The attacking code tries to be aggressive and will usually attack. Sometimes the AI should attack but is too cautious, thus causing the game to stretch out. (I tried to avoid problem of when the AI would attack with everything and then you would attack and win but I accidentally caused this "stalling" problem.)

The blocking code is also very simple. The AI tries to make decent blocking decisions. The blocking code is more complicated than the attacking code since you can have multiple blockers and generally you don't want flyers to block non-flyers.

The attacking and blocking code does not do anything fancy and just uses a "for" loop to generate which creatures will attack or block. Let me explain the "for" loop for the attacking code. The code looks at each of the computer's creatures individually and asks, "Should this creature attack?" The blocking code does to the same thing, it looks at each attacking creature and asks, "Should this creature be blocked?"

Obviously this isn't how a human player attacks or blocks. Players, like myself, attack or block based on the whole combat situation, all of the creatures. So the AI does very little processing when it comes to combat and that explains why it makes so many mistakes in that area. Ideally the AI would do a CPU intensive search to generate better combat decisions.

Forge's biggest snafu is that the AI doesn't play spells during your turn, except for counterspells, or during combat. This was done to simple the code for canPlayAI(). Coding canPlayAI() for "normal" situations is hard, so coding for unusual situations (like other phases) is out of the question.

The biggest strength of Forge's AI is that it plays by the rules, nothing fancy. On paper it sounds easy until you begin coding and then you start pulling you hair out. Making the AI use the same resolve code as the player is very hard. (Forge's early design dictated that I had to code each card twice. One for the player and one of the computer. I knew this was the wrong way to go.)

For awhile Wagic's AI couldn't use activated abilities and I knew exactly how hard I worked on that. (Unfortunately it is hard to help someone because different projects have different UML designs, how everything fits together.)

p.s.
By the way, Wagic is a great project. It has more cards than Forge and a nice user interface. Shoutouts to wololo. (The guy who started Wagic.)

p.p.s.
And as a side issue, Forge still uses the "old combat" rules.

Wednesday, May 12, 2010

Open Source Project - Part 2

Dennis sort of organically took over the project. I never asked him to and he never asked could he, he just did it. Open source projects can become heated debates and anybody can "fork" and start their own project. All you have to do is download the source code and then say, "I wish it had a dancing, purple bear in the background" and voila, you have just forked a project. Forking is generally bad because it splits people's time, which is your most valuable resource, since people are only volunteering their time anyways.

Honestly, the Forge project has been very successful and fulfilling. Now I'm just the "old guy" that started the project and doesn't contribute much these days. Dennis, Rob, and others have "found my vision" and enjoy coding Magic. After awhile programming Magic becomes sort of a "meta-videogame" because coding itself seems like a game because you are constantly challenging yourself.

HuggyBaby and GoblinKing have provided Forge's forum which allows for more interaction between the users and the guys who do the programming. Without the forums, Forge would be a lesser program. The forums is also where "us" developers chat and ask each other questions like, "What in tar-nations does the stupid Input class do?".

(The Input class is handles all mouse input and it can be confusing. I started the forum topic "How to understand the Input class in 4 hours or less". I'm joking about the 4 hours part but I still wrote a thorough explanation.)

And last but not least, you the readers (and downloaders) have made Forge special. Forge was written because I had an itch but other people seem to have the same itch too. I'm also the first to admit that Forge is far from perfect but it is still very fun. I play Forge so much, I have a hard time thinking, "What if Forge never existed?"

p.s.
The Incantus magic project which allows people to play Magic with rules enforcement over the Internet has recently gone "open source". Incantus is written in Python and has a wonderful user interface. The rules enforcement is so good that is probably can implement 95% of all Magic cards in existence.

Incantus Project
Incantus Forum

The Wagic project, which lets you play against the computer and was written for the PSP but can also be run on Windows, is written in C++ and is also open source.

Wagic Project
Screenshots

And I hate to leave anybody out. MagicWars lets people play over the Internet like Incantus and is written in Java. Currently it has 719 cards.

MagicWars Project

Monday, May 10, 2010

Open Source Project - Part 1

Making a program "open source" means that you allow the world the chance to download and peek-and-poke around your source code. (Having someone look at your source code is also very personal because it is easy to criticize someone else's code.) The advantage of this method is that maybe, just maybe you can recruit other people to help do some of the programming. This has happened with Forge. Forge started out as a one man project but now it has 5 or so active programmers.

By the way the current "lead developer" is Dennis and he is a great leader. He donates the most time and I admire his dedication. He also doesn't complain about my code, so he is a good guy in my book. :--)

Most open source project are just lumps of source code lying around with no documentation. Many projects never end up producing any code at all, they are just ideas that never get written, see SourceForge. Now don't get me wrong, there are also lots of productive, useful programs on SourceForge. Writing a program that someone else can use is actually very hard. (And if you wondering if I stole Forge's name from SourceForge, the answer is probably. I didn't sit down and try to think of a name, I just let my fingers type something and Forge just appeared.)

When I say that most open source projects are lump of code lying around with no docs, I mean it. Forge was the same way. Forge's saving grace was that it actually did something, so people could see it in action and get excited and want to contribute code. If a program doesn't do anything, people aren't going to get excited. Showing me some UML is great and all that but UML and other documentation is deadly boring. I mean people would rather hit themselves in the head with a rubber hammer than read UML or specifications. (UML is just line drawings which show how the major parts of a program fit together.)

Another good attribute of Forge is that the program is fun to use. It isn't a boring report generator; it is an actual, fun, interesting videogame. Yes, some people probably love working on the Linux or Apache but they aren't what most people would consider fun.

And truthfully I didn't think anyone else would ever take a second look at Forge's source code. Yes I'm the world 2nd greatest programmer and all that but why would someone actually slog through and read my code? And don't forget, Forge has no documentation. Yes, I tried to give objects and methods good names but it is still hard to figure out what a 500 line object does even if all of the methods are well named.

Open source software also has the "side effect" of being free which makes it popular. :)

Friday, May 7, 2010

Rise of the Eldrazi - High Quality Scans

Magic has wonderful card art. These are high quality scans from the CCGHQ team. They are trying to scan every Magic card printed, including all variations and promos, which is a huge task. They have a forum here.

Rise of the Eldrazi - 37 MB, includes tokens and "tips and tricks" cards