Monday, January 30, 2012

Browsing Forge’s Source Code

Source code is great. Similar to a the relation between a cooking recipe and a cake, source code “creates” a program. I like the think of source code as the secret internal guts of a program that you never get to see. I have not looked at Forge’s source code in a long, long time, so I’m just going to randomly pursue it. (You can view the source code yourself here.)


(A class is just a bunch of related Java statements.)

I’m always drawn to the class Card but I see the class ColorChanger so I’m going to look at that first. ColorChanger is very basic but it lets you change the color of any card. ColorChanger also uses a time stamp to keep track of the color changes. Below is the most important method. I understand most of the code but bIncrease is interesting because it changes the time stamp. I think the time stamp is important because two cards may change all of the other card colors in the game but the card that is played last takes priority and “overrides” any previous cards.
public final long addColorChanges(final String s, final Card c, final boolean addToColors, final boolean bIncrease) 
{
   if (bIncrease) 
   {
      CardColor.increaseTimestamp();
   }

   this.globalColorChanges.add(new CardColor(new ManaCost(s), c, addToColors, false));
   return CardColor.getTimestamp();
}
The Card class is used everywhere in Forge and I have fond memories of creating it from scratch. Currently the Card class is 8,800 lines long (including blank lines) and you can view it here. The most important methods are:

getName() : returns String
isSick() : returns boolean – Does this creature have summoning sickness?

getOwner() : return Player – Who owns this card?
getController() : return Player – Who is currently using this card?

getManaCost(): returns String represent the cost of this card. Even though not every card has a mana cost, most cards do.

One of the longest methods is hasProperty() which covers many additional sources of information like does this card have one color or multiple colors? Is this card double-faced? Is this card a flip card? Is this card enchanted? Is this card haunted by any other cards?

hasProperty(final String property, final Player sourceController, final Card source)

And finally I will look at IPlayerZone, which implements all of the zones in Magic: battlefield, graveyards, exiled, in hand, or in your library. IPlayerZone is technically an interface and just outlines what methods it need and does not contain any working code. IPlayerZone is just a thin wrapper for ArrayList and has the regular, boring methods like add(Card), remove(Card), size(), isEmpty(), and contains(Card) : boolean. I did not directly create IPlayerZone but I indirectly created it. To easily filter cards I created a different, yet similar class named CardList which easily lets you do common task such as find all elves or Forests in play.

Much of Forge has changed since I worked on it and just browsing through the source code, Forge looks very impressive. Just looking at individual classes is just a glimpse of the program’s overall form and structure but it shows just how many details have to be laboriously spelled out so the computer can process them. And yes I do understand that Forge has its share of errors but Forge really is a work of art.

Forge is the best videogame ever created. (Well next to Minecraft…)

Humble scribe,
mtgrares

p.s.
Just in case my previous link doesn't work, you can view Forge's Java source code here.

Tuesday, January 24, 2012

Magarena – Great AI

Magarena is a great, great program. It lets you play Magic against the computer and has almost 2,000 cards. The outstanding feature of Magarena is that the AI is as smart a human opponent. The AI will punish you for mistakes and will play unexpected instants during combat. While Forge’s AI is a nice stroll through the forest, Magarena feels more like all-out war. You can also scale back the AI and limit the time that is had to “think ahead” to only a couple of seconds which makes the AI good but not great.


Magarena also has a great user interface which is skinnable and supports different themes. The cards are artfully displayed so you can easily glance at your hand or the battlefield and see everything. Combat is beautifully handled with a separate combat mode that graphically shows which creatures are attacking and blocking.

Magarena also highlights the cards in your hand that you can play and if you double-click, it has an auto-pay feature. In case you made a mistake, it even has a fabulous undo button. Magarena also highlights cards that have an activated ability that you can use. Also when attacking and blocking, Magarena highlights which creatures you can attack with and block.

Magarena lets you choose between a cheating or non-cheating AI. The difference is that the cheating AI can see the cards in your hand. I randomly play against both cheating and non-cheating opponents and I cannot see a discernable difference. Basically the cheating AI is a little bit better than the non-cheating.

Magarena has a difficult (even grueling) AI and a powerful, candy-covered user interface.

Magarena-1.21.zip (10 MB) (Windows,Linux)

Magarena-1.21.app.zip (10 MB) (Mac)

Magarena Forum

Just a random programmer,
mtgrares

p.s.
--Magarena is written in Java, which I think is very cool. Java (can be) great.

--If I understand Magarena’s docs, the strongest AI is the “monte carlo (cheat)” option. This algorithm is very sophisticated. As I understand monte carlo, it plays many thousands of games using random moves and then chooses the move (branch) that generates the best outcome for the AI and the worst outcome for the opponent. Easy to explain but hard to code.

Saturday, January 21, 2012

Late Again

Robin - "Holy Cheesecake Batman, no new article today."

Batman - "Yes, this seems to be the work of the nefarious Sweet Tooth".

I'll try to post a new article sometime Monday.

p.s.
I just watched an 70's Batman cartoon and it was hilariously bad, though entertaining enough that I watched the whole episode. It even had the mischievous Bat-Mite, who causes more chaos than he solves. The show had horrible puns throughout. It was similar to a really good b-movie and I just couldn't look away.

Tuesday, January 17, 2012

New Version

(Sorry for not publishing anything on Monday.)

New versions of Forge are great and taste like fresh buttered movie popcorn, hmmm… There are 200 new cards and the user interface has gotten a major overhaul. (And yes Forge now has Serum Powder.)

Chris. H. posted:

(Begin quote)

A new UI is being developed and it will take some time before it is finished. Forge is somewhat unstable at this time as the new user interface is a work in progress.

The first step was to update the battlefield window. The second step was to update the New Game window and this section still needs some work. We want to get constructed node and then quest modes working first and will then try to get the draft and sealed modes working again afterwards. While most of this work has now been done there are still a few areas that are not finished and you may discover a bug or two.

Enjoy the new work and be patient as this part of the project moves forward. For now, only "Constructed" mode is far enough along to be considered reasonably stable. Quest mode, Sealed and Draft are somewhat stable and you should be able to use these three modes without too many bugs and issues being noticed. Please report all bugs and issues that you notice.

(End quote)

Working on a new user interface is very complicated. It takes weeks to create a new user interface and mere minutes to criticize. I’m not saying that all criticism is bad but try to balance your criticism with a little bit of praise. A good balance points out the good and as well as the bad.

Listing some positives also helps the author know what he is doing right, which is as important as highlighting the negatives. If you only list negatives, the author will probably just give up out of frustration.

Some of the new cards look very cool.

Bogardan Phoenix (2RRR, 3/3, flying) returns to the battlefield after dying once.

Culling Scales (3, artifact) - "At the beginning of your upkeep, destroy target nonland permanent with the lowest converted mana cost" if there is a tie, target any one of them. This card is just dying to be the center of a creatureless blue control deck.

Doubling Cube (2, artifact) - "3, tap: Double the amount of each type of mana in your mana pool". Deckbuilders, start your engines.

Vish Kal, Blood Arbiter (4WBB, 5/5, flying, lifelink) and some cool an ability to grow larger, if you sacrifice a creature. Everybody loves flying fatties.

Serum Powder (3, artifact) - If you have Serum Powder in you hand, you can exile all of the cards in your hand and then draw the same number of cards, which is an unique ability. In my option, Serum Powder seems like it would improve most decks.

Dreams of TCG videogames,
mtgrares

p.s.
Maybe it was good that I didn't post anything Monday since a new version of Forge was released yesterday. Sometimes being late is a good thing :+)

--------------------------------------------------------------------------------

01-16 is when this version of Forge was first posted to the forums.

Link - Forge 01-16 (Windows, Linux) 33 MB and can be unzipped with Winzip or 7-Zip (free, open source)

Link - Forge 01-16 (Mac) 35 MB and can be unzipped with with Keka

Download - Card Pictures (160 MB) - These are some of the low-quality (LQ) card pictures. 

Java - Forge requires Java in order to run

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

Reporting Bugs:
Forge is always a work-in-progress. Some cards (and card interactions) are more buggy than others. To report a bug, please follow the instructions here.

p.s.
These are the people that make Forge awesome. They donate their time, skill, and patience.

ArsenalNut
Chris H
Dave
DeadSpeak
Doublestrike
Friar Sol
Hellfish
Jeff Wadsworth
Marc
Mark
Slapshot5
Sloth
SoulStorm
Squee1968
Xanbie
ZzzzSleep

Monday, January 9, 2012

Thank You

This post is going to be a little bit different. I don’t have bits of Java code to throw at you. This is just a simple article saying, “Thank you for downloading Forge.”

(Card picture from the set - Duel Decks: Ajani vs. Nicol Bolas)

When I started working on Forge I was at my lowest point and very depressed. My college degree was getting me zero interviews and I had recently got myself into a huge heap of trouble which gave me a little too much time on my hands. I knew that I enjoyed programming so I started working on Forge as a hobby. I thought that more than likely no one else will ever see my work but it would at least give me something to do.

Now other people actually contribute code to Forge and I just blog about it. Most open source)projects don’t ever get off of the ground but with Forge there has always been people wanting to work on it, which is exceptionally rare. For some reason open source videogames are rare and I’m glad that Forge is a shining example.

The current developers have to deal with my design decisions and I say “Thank You” because they have done such a good job programming around Forge’s limitations. I created Forge as well as I could but there were gaping holes in my logic and architecture. I am humbled by the fact that they have added so many more cards to Forge than I would have been able to do as individual programmer. Sometimes the group is smarter than the individual (but not always).

I also want to say thanks to you for reading this blog. Most of my life seems like a failure: no job, no girlfriend and I’m 33, but writing for this blog is very satisfying. I get 200 to 300 hits a day which is very impressive considering that I only post one article a week.

If I would have been able to find a job, Forge probably would have never been written. The same thing probably could be said of J.R. Rowling, author of the Harry Potter series. She began writing because she was nearly homeless and didn’t know what to do with her life.

I enjoy telling people that I started a thriving open source project. Creating and working on Forge have been one of the highlights of my life. I would encourage you to try to do something “big” yourself, even if the odds are stacked against you. Even writing this very geeky, niche blog is very rewarding.

Even if I never get a job programming professionally, Forge has given me confidence in my skills.

Humble programmer and writer,
mtgrares

p.s.

-- I also understand that Forge is far from perfect. I wrote Forge to very flexible but that flexibility makes Forge harder to use. Thanks for powering through and being able to see the beauty of Forge.

--A side note about my recent programming activity. I haven’t written any Java code in three years. I don’t know if it is burnout or just laziness. The main reason that I avoid coding is because it takes so much concentration, which is exhausting. Programming is like doing an extremely, long math problem. If you get the right answer it feels great and when you get the wrong answer, you feel like crap. I try to praise the coders who work on Forge because I know how strenuous it can be. Trying to fix a bug can be like the 3rd circle of hades.

I do enjoy programming and maybe I can prod myself to work on a small project. Trying to tackle a big project is like wrestling with a bear, you might win but it won’t be pretty.

Monday, January 2, 2012

Card Scripting

Card scripting is cool. Instead of having to program cards using Java, which is usually very long and over 100 lines of code, card scripting is shockingly short. Probably 95% of all cards in Forge are scripted.

To look at a specific card’s scripting: first go to the forge folder, then res, then cardsfolder, and unzip “cardsfolder.zip”. Cards like Jace, the Mind Sculptor do not have any scripting and the text file only holds basic information about the card such as its name, cost, card types and starting loyalty.

Shock is always my favorite example.

Name:Shock
ManaCost:R
Types:Instant
Text:no text
A:SP$ DealDamage | Cost$ R | Tgt$ TgtCP | NumDmg$ 2 | SpellDescription$ CARDNAME deals 2 damage to target creature or player.
SVar:Rarity:Common
SVar:Picture:http://www.wizards.com/global/images/magic/general/shock.jpg
SetInfo:8ED|Common|http://magiccards.info/scans/en/8e/222.jpg
SetInfo:7ED|Common|http://magiccards.info/scans/en/7e/219.jpg
SetInfo:STH|Common|http://magiccards.info/scans/en/sh/98.jpg
SetInfo:9ED|Common|http://magiccards.info/scans/en/9e/220.jpg
SetInfo:10E|Common|http://magiccards.info/scans/en/10e/232.jpg
SetInfo:6ED|Common|http://magiccards.info/scans/en/6e/206.jpg
SetInfo:M12|Common|http://magiccards.info/scans/en/m12/154.jpg
SetInfo:ONS|Common|http://magiccards.info/scans/en/on/227.jpg
Oracle:Shock deals 2 damage to target creature or player.
End

Obviously there is a fair about of information here such set information, where each card picture is located as well as its rarity.

A:SP$ DealDamage | Cost$ R | Tgt$ TgtCP | NumDmg$ 2 | SpellDescription$ CARDNAME deals 2 damage to target creature or player.

This is the “scripting” part that creates the card Shock. The scripting restricts the targets to creatures or players, specifies the mana cost, and has some text to show the player.

My 2nd favorite example is Elvish Piper. He isn’t a powerhouse but he is a fun card to use.

Name:Elvish Piper
ManaCost:3 G
Types:Creature Elf Shaman
A:AB$ ChangeZone | Cost$ G T | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature | ChangeNum$ 1 | SpellDescription$ You may put a creature card from your hand onto the battlefield.
PT:1/1
SVar:Rarity:Rare

Elvish Piper’s activated ability is far more complicated than Shock’s. The cost is listed as “G T” which seems to mean “1 green mana” and “tap this card”. “Origin$ Hand” means that the creature card is taken from the player’s hand.

Name:Shivan Dragon
ManaCost:4 R R
Types:Creature Dragon
PT:5/5
K:Flying
A:AB$ Pump | Cost$ R | NumAtt$ +1 | SpellDescription$ CARDNAME gets +1/+0 until end of turn.

Shivan Dragon’s pump ability is a common effect, “R: Shivan Dragon getes +1/+0 until end of turn”. Any card with a similar ability can be scripted as well.

Name:Shivan Meteor
ManaCost:3 R R
Types:Sorcery
A:SP$ DealDamage | Cost$ 3 R R | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 13 | SpellDescription$ CARDNAME deals 13 damage to target creature.
K:Suspend:2:1 R R

Shivan Meteor is fairly straightforward except that it also has suspend. Shivan Meteor regularly costs 3RR but can be suspended (and played) in 2 turns for 1RR. The scripting for suspend is simple since other parts of Forge handle the actual implementation.

Name:Akroma, Angel of Wrath
ManaCost:5 W W W
Types:Legendary Creature Angel
PT:6/6
K:Flying
K:Vigilance
K:First Strike
K:Trample
K:Haste
K:Protection from red
K:Protection from black
SVar:Rarity:Rare

Even though Akroma has a ton of text, all of the text is standard keywords. Cards with activated abilities require more scripting than Akroma.

Name:Day of Judgment
ManaCost:2 W W
Types:Sorcery
A:SP$ DestroyAll | Cost$ 2 W W | ValidCards$ Creature | SpellDescription$ Destroy all creatures.

Name:Wrath of God
ManaCost:2 W W
Types:Sorcery
A:SP$ DestroyAll | Cost$ 2 W W | ValidCards$ Creature | NoRegen$ True | SpellDescription$ Destroy all creatures. They can't be regenerated.

Obviously these two cards are almost clones of each other. Wrath of God is slightly more powerful because creatures can’t regenerate. Obviously Wizards of the Coast thought that Wrath of God was unbalanced and then created Day of Judgment. The Wrath of God scripting includes “NoRegen$ True” which is a minor point but very important. Since Wrath of God is scripted, its mirror Damnation is also scripted and has a different mana cost of 2BB.

Scripting is great and it allows non-programmers to add new cards. The scripting has gotten more complicated and is now a “little language” that does one thing well: create Magic cards.

Average blogger,
mtgrares

p.s.
Eons long ago while I playing Magic Online, I remember using my Elvish Piper to play Darksteel Colossus (11, 11/11, creature, indestructible, trample). Because they were expensive cards, I only had one copy of each card so I was very happy when I actually got to use them. :+)