Wednesday, December 30, 2009

How to Conquer the Complexity of Rules - Part 2

The idea of putting all of the rules into one large object, RulesEngine, is very versatile. To begin with I can code simple rules and then update them later as needed. This avoids the problem of overanalyzing the rules because you want to your program completely correct which usually results in "analysis paralysis". This approach doesn't work because the rules are too big and your brain is much too small.

While having one massive object is bad in some aspects, the positives include having all of the rules confined to one location. Internally I can restructure it as often as I need to because the external methods for RulesEngine won't change. Since RulesEngine implements every single rule, I should be able to easily implement new rules and to fix rules that I have misunderstood. I can write a very simple mana pool and then later make it more sophisticated.

The goal is to give RulesEngine all of the information and let it internally implement the rules. The hard point is giving RulesEngine "all of the information" because different Magic cards need to know different pieces of information. There will always be weird cards that require off-the-wall” information like Imperiosaur which has the static ability "Spend only mana produced by basic lands to play Imperiosaur". Or cards that require snow mana or cards that say something like "you can only use this mana to pay for artifacts".

Obviously implementing Magic isn't easy but by putting all of the rules together will make the coding as easy as possible.

Monday, December 28, 2009

How to Conquer the Complexity of Rules - Part 1

Programming Magic's tidal wave of rules is a huge challenge. I did my best with Forge version 1. I got the program "out the door" and working but it only implements a few of the rules. I'm slowly but thoroughly working on Forge version 2 and I'm trying to figure out how to program a few simple rules now and allow for more complex rules implementation later.

My idea is to put all of the rules into one large object which I call the RulesEngine. (An object is just code statements that are related.) You give all of the information to the RulesEngine and let it handle the rules internally. This way you are separating the rules from the rules implementation. In programming it is often useful to separate "tightly knit" systems like separating the user interface from the back-end business logic using the model, view, controller (MVC) pattern.

At the heart of Forge version 1 is the method nextPhase(), which advances the game to the next phase. (And although I know that there is technically a difference between phases and steps, I call everything a "phase".) I plan to use nextPhase() in Forge version 2 also. At first nextPhase() will just advance to the next phase but later on it could do anything number of things: empty the mana pool, move duplicate legendary and planeswalker cards to the graveyard, implement upkeep effects like Juzam Djinn, and check for other state effects.

The idea is to start with a "simple" implementation of Magic's rules and later on you can update your implementation as needed since all of the rules are in one place. Next time I examine more of the pros and cons of this idea.

Friday, December 25, 2009

10 Cards That You Didn’t Know Forge Had

Merry Christmas.

10 – The planeswalkers Ajani Vengeant and Jace Beleren. Ajani is a red-white powerhouse and Jace lets you draw cards or deck your opponent. (Yes, I cheated and mentioned two cards, so sue me :)

9 – Time Walk, yes you abuse the computer with this classic, and costly, card. (Funny note, at first Richard Garfield wrote this card to say “Your opponent losses his next turn”. One player came running up to Richard and said, “I just found this amazing card that lets you win the game” and Richard said, “What card is it?” The guy said, “It says your opponent loses the game.” The guy misunderstood the card to mean that your opponent loses the whole game.

8 – Akroma, Angel of Wrath, yes Forge implements this card 100%. At first Akroma just had flying and haste. As Forge progressed, Akroma slowly gained all of her abilities. Forge also has her red, Planar Chaos sister Akroma, Angel of Fury.

7 – Snow Mana, well you probably noticed this since there is a whole extra mana pool dedicated to snow mana but it is still cool. Be sure to check out snow mana cards like Boreal Griffin, Frost Raptor, Goblin Rimerunner, Phyrexian Snowcrusher, Rimebound Dead, Phyrexian Ironfoot.

6 – Door to Nothingness is a 5 mana artifact that lets you win the game for only WWUUBBRRGG. Johnnies, feel free to go nuts.

5 – Goblin Sharpshooter, is a great way to kill all of your opponents X/1 creatures in play. Works great against elves too!

4 – Equipment, make sure to add these to your favorite decks: No-Dachi (cost 2, equip 3, Equipped creature gets +2/+0 and has first strike) or Loxodon Warhammer (cost 3, equip 3, Equipped creature gets +3/+0 and has lifelink and trample.)

3 – Rukh Egg, an oldie but goodie. Break him out of his egg with Lightning Bolt.

2 – Sol Ring helps out any decks mana curve. For only a cost of 1, you get 2 more mana each turn.

1 – Darksteel Colossus – This is a huge trampling 11/11 creature. Since he is a little bit expensive, 11, feel free to cheat him into play using Elvish Pipe. Colossus can’t be put into the graveyard so you can’t Zombify him. Feel free to think of your own way to play this gigantic card.

That’s it. Merry Christmas.

Wednesday, December 23, 2009

Great Programming Books

I don’t write much about programming itself because….well….programming is as interesting as watching paint dry on the 4th of July. I have read one outstanding book on programming called Code Complete: A Practical Handbook of Software Construction by Steve McConnell. This book is better than all of the books that I bought for my computer college classes. (I majored in Information Science and minored in Computer Science, yeah go me!!)

Code Complete is very interesting even though it talks about computer programming. Specifically the book is aimed at “software construction” but a major part of software construction is computer programming. I re-read this book every year and it is just phenomenal. Amazon.com gives this book a 4.5 star rating with 149 customer reviews, which is a pretty strong recommendation. Feel free to buy the cheaper 1st edition since it has 99% the same stuff as the second edition. (I should know because I’ve practically memorized the 1st edition.)

It is really hard to describe “Joel on Software” written by Joel Spolsky. The book is just really, really good. The book is based on the author’s personal blog, http://www.joelonsoftware.com, but I find the book to be 100% more interesting and insightful than the blog. The book is hard to describe but it covers such computer science topics as “Why Anti-aliased text looks better”, “Network IO doesn’t work like local IO” and “Why there ain’t no such thing as plain text”. Overall the book isn’t technical but the author doesn’t mind diving in sometimes. The book is very humorous and I’ve found myself laughing out loud at it. (Warning your non-technical friends will not understand why the book is so funny.)

One really great essay from “Joel on Software” is the five worlds of computer programming. I’ll briefly go over the article but you can also read it here on his blog. The five worlds are shrinkwrap, internal, embedded, games and throwaway. Often an article or methodology will be talking about one world while the reader deals with a different world and then flame wars erupt. If a book is talking about shrinkwrap and you deal with open source, the book won’t make any sense to you. Each world is separate and doesn’t overlap.

Shrinkwrap – is used by zillions of customers, who often have alternatives. So the user interface needs to be easier than average to be successful. They spend half their time trying to make things even easier for Uncle Leo in Duluth.

Open Source – is often developed without anyone getting paid to develop it, so things that aren’t considered “fun” often don’t get done. (My comment – the user interface is often considered “not fun” and therefore never gets done. Most open source projects have horrible user interfaces that actually inflict pain on the user. And don’t get me started on command line interfaces that are as bad as the Sarlacc pit in Star Wars, i.e. very bad.)

Internal – only has to work in one situation on one company’s computers which makes it a lot easier to develop. You can make lots of assumptions about the environment under which it will run. You can require a particular version of Internet Explorer or Microsoft Office. Sadly lots of internal software sucks pretty badly even while accomplishing what it needs to accomplish. This can be depressing for young enthusiastic developers who need to be persuaded to stop when the software is “good enough.”

Embedded – is unique because it goes into a piece of hardware and in almost every case can never be updated. Even if it can technically be updated, it won’t be. Trust me, nobody downloads EPROM flash upgrades for their microwave ovens. This is a whole different world. The quality requirements are very high because there are no second chances. You may be dealing with a CPU that runs dramatically more slowly than the typical desktop processor, so developers may have to spend a lot of time optimizing and hand-tuning. Fast code is more important than elegant code. The input and output devices available to you will probably be limited.

Games – are unique. The economics of game development are hit-oriented. Some games are hits, many more games are failures, and if you want to make money on game software, you recognize this and make sure that you have a portfolio of games so that the blockbuster hit makes up for the losses on the failures. This is more like movies than software.

Throwaway – This category is included for completeness. This is code that you create temporarily solely for the purpose of obtaining something else, and you never need to use the code gain once you obtain that thing. For example, you might write a little shell script that massages an input file that you got into the format you need it for some other purpose, and this is a onetime operation. (My comment – throwaway code should always be saved for the future because you never know when you need to do “such and such” again. Usually if you need to do something once, you probably need to do it twice but you don’t realize it yet.)

Well after plagiarizing about 500 words you can tell that I really like the book. It is a very good non-technical book (only a few lines of code) that talks about technical subjects. Joel Spolsky wrote two very good books “Joel on Software” and “More Joel on Software”. He also edited the much worse “Best Software Writing I” which I mistakenly bought and it was a very BIG mistake. That book is horrible.

So in conclusion try to find “Code Complete” by Steve McConnell and if you want a good laugh or two read “Joel on Software” or “More Joel on Software” by Joel Spolsky.

Monday, December 21, 2009

Version 2 – A Fresh Beginning

I’m slowly working on Forge version 2. I’ve been sandbagging (i.e. goofing off) for probably a year or so but I’m making slow but steady progress. Like building a house, I’m starting at the foundation, phases. I’m making sure that you or the computer can play first, as well as implementing phase stops like Magic Online.

I have started version 2 multiple times and I have some very good code that I can use but basically I’m starting completely over. Starting over sounds very bad, even to me, but hopefully I can build something that is truly wonderful instead of a program that is held together with duck tape. Duck tape works but it often leads to weird, complicated problems in the future.

To put things into perspective, I probably have 30 lines of code and 10 or so methods. This is a small but promising start on such a big project. Currently Forge has more than 30,000 lines of code. I’m guessing that version 2 with 10 cards and an improved AI will have around 1,000 to 5,000 lines of code, I would like to predict when this will happen but I’ll leave the fortune-telling to gypsies and Las Vegas gamblers.

I consider Forge a complete success because it has more than 2,000 cards and is infinitely replayable. Forge is also a successful open-source project that continues to be updated even without my help. Forge is “computerized heaven” for casual players like myself.

Wednesday, December 16, 2009

The Rules Engine is a Pain in the Neck

We all know that Magic is a great game and one of the reasons why it is so great is because of the complicated (and sometime baffling) rules. And when I’m talking about the rules, I’m not talking about the wimpy basic rulebook that beginner’s use, I’m talking about the monstrous, sometimes incomprehensible comprehensive rulebook.

The comprehensive rulebook is great for answering specific small questions like what is a card’s type and supertype?

204.2a The card types are artifact, creature, enchantment, instant, land, plane, planeswalker, sorcery, tribal, and vanguard.

204.4a A card can also have one or more supertypes. These are printed directly before its card types. The supertypes are basic, legendary, snow, and world.

The comprehensive rules are individually numbered so you can quickly look up the rule again, or just reference it by writing 204.2a (if you have *cough* memorized it).

Obviously you have to know a little about Magic’s rules in order to program them. Some people don’t understand targeted and non-targeted spells and I understand their confusion but if you want to write a program that plays Magic, you have to know the rules as much as I can (without going crazy or getting “analysis paralysis”).

Targeted spells use the word “target” but it gets confusing when a spell affects multiple cards like Wrath of God. It seems like Wrath of God should target all creatures but it doesn’t. And Wrath of God will still destroy cards that have protection from white like Black Knight since protection only protects the creature from being targeted by a spell of that color.

Things get really tricky when you consider Pestilence AND a creature that has protection from black. Protection from black nullifies Pestilence and the creature will not receive any damage. Protection is also another thorny area and is widely misunderstood. Below is taken from this Saturday School article.

Protection from any quality means 4 things, abbreviated D-E-B-T: Damage from that quality is prevented, can’t be Enchanted by enchantments of that quality, can’t be Blocked by creatures of that quality, and can’t be Targeted by spells or effects of that quality. Commander Eesha can’t be blocked by a creature.

Forge supports regular "protection from color" as well as protection from enchantments (Azorius First-Wing), Dragons (Dragonstalker), Goblins (Warren-Scourge Elf), Demons (Baneslayer Angel), everything (Progenitus), artifacts (Nacatl Savage), and creatures (Beloved Chaplain).

My personal mistakes include thinking that Elvish Piper targeted a card in your hand AND that you have to choose the creature that you will put into play when you cast the ability. So I made two mistakes on one simple card. (By the way Elvish Piper is still a little broken because I never fixed it.)

Forge tries to implement as much as the rules as possible but originally Nightmare and Giant Growth didn’t work together. I know Giant Growth is supposed to pump up Nightmare but since creature's power and defense were simple numbers (int), a simple layer system had to be added. (Thanks to Dennis and Rob for the layer system.)

I used to think the hardest part of programming Magic was implementing the cards but I've learned that the rules engine itself is the most complicated part. If you rules engine is sophisticated enough with events and triggers, programming the cards shouldn't be much of a problem.

p.s. The picture for Garruk Wildspeaker is from from the Duel Decks: Garruk vs. Liliana set.

Monday, December 14, 2009

New Version

There is a new, hot-off-the-shelves, kick-your-brothers-butt, version of Forge with a whopping 200 new cards, which means that Forge now has colossal 2,331 cards. (P.S. I love the word whopping.) Probably the biggest change is that now there is a “Before Combat Begins” phase and an “After Attackers” phase, so you can milk those activated abilities and instants even more. I know people have been clamoring for more phases.

There are a ton of exciting new cards that you will you will want to get your hands on like the planeswalkers Ajani Vengeant and Jace Beleren, the insane-in-the-membrane Time Walk, and the put-any-artifact-into-play king Tinker (make sure to use a nice big fatty like Darksteel Colossus).

Other notable potables includes Academy Rector which lets you abuse enchantments, Umezawa's Jitte which is an insane piece of equipment, as well as the how-do-I-use-this-stupid-card Barren Glory (At the beginning of your upkeep, if you control no permanents other than Barren Glory and have no cards in hand, you win the game). Snow mana is now supported and there are also a ton of tiny fixes for individual cards.

The other big change is that Forge now uses a different deck system. Your old decks were all crammed into the file “all-decks2” but now each deck exists as a separate file. This version will import all of your old decks into the new deck system.

Other nice goodies include a deck editor that lets you easily hide colors and card types that you don’t want. You can see a nice screenshot of it here. (Thanks Nantuko!!)

This whole update was coded by the great guys on the forum: Dennis, Rob, Zerker, and Nantuko.

p.s. I added a text file that says that this is Forge version 11-25 because that was when it was released on the forums. On the forums you can cure world hunger, be the next president of the United States, or finish your homework. The forums are a great place to upload your favorite deck or download someone else's.

Download Forge

Wednesday, December 9, 2009

Shock and Royal Assassin – Part 3

Today I’m going to talk about Incantus and MagicWars. Both programs enforce the rules and allow you to play against other people over the Internet. Even though these two projects are completely separate, they encode Magic cards in a similar way. Each card is very short and is written in either Python or Java. Incantus was written in Python while MagicWars uses Java.

Incantus is the current king-of-the-hill when it comes to supporting the most cards. Incantus currently has more than 6,000 cards which is phenomenal. Of all of the freeware Magic programs, Incantus has the best user interface with all of the eye candy that you would ever want. Incantus has very readable, short card code that is written in Python. Currently the source code of Incantus is semi-private. It isn’t an open source project but you can get the source by reading through the Incantus forum.

MagicWars is newer than Incantus and has more than 550 cards including all 145 cards from Alara Reborn, go cascade!! MagicWars uses Groovy to encode Magic cards. The Groovy homepage says that it:

-- Builds upon the strengths of Java but has additional power features inspired by languages like Python, Ruby and Smalltalk.
-- Makes modern programming features available to Java developers with almost-zero learning curve.
--Supports Domain-Specific Languages and other compact syntax so your code becomes easy to read and maintain.

Groovy compiles to Java bytecode, so it can run anywhere that Java can. The MagicWars blog also says that “A Groovy Closure is like a ‘code block’ or a method pointer. It is a piece of code that is defined and then executed at a later point.” So Groovy is short like a domain specific language (see my previous article) and yet powerful enough to be a full-fledged language all by itself. Right now I don’t know anything about Groovy but it seem very interesting.

MagicWars also has a very nice blog that describes how it specifically uses Groovy. The blog encourages non-programmers to learn some syntax and to create their own favorite card.

Incantus:
Screenshot
Forum


MagicWars:
Screenshot - game in progress
Screenshot - deck editor

Download
Forum
Blog

Groovy

Incantus - Royal Assassin
name = 'Royal Assassin' 
cardnum = 0
expansion = ''
types = characteristic('Creature')
supertypes = no_characteristic()
subtypes = characteristic('Assassin', 'Human')
cost = '1BB'
color = characteristic('B')
power = 1
toughness = 1
text = ['T: Destroy target tapped creature.']

play_spell = play_permanent()

#################################

@activated(txt=text[0])
def ability():
def effects(controller, source):
cost = yield TapCost()
target = yield Target(isCreature.with_condition(lambda c: c.tapped))
target.destroy()
yield
return effects
abilities.add(ability)


Incantus - Shock
name = 'Shock'
cardnum = 0
expansion = ''
types = characteristic('Instant')
supertypes = no_characteristic()
subtypes = no_characteristic()
cost = 'R'
color = characteristic('R')
text = ['Shock deals 2 damage to target creature or player.']

#################################

@play_instant()
def effects(controller, source):
cost = yield source.cost
target = yield Target(isCreatureOrPlayer)
source.deal_damage(target, 2)
yield
play_spell = effects



MagicWars – Royal Assassin
name = "Royal Assassin"
types = ["Creature","Human","Assassin"]
manacost = "1 B B"
text = ["{T}: Destroy target tapped creature."]
power = 1
toughness = 1
prints = [
["M10", "R", 191318, 110],
["10E", "R", 129708, 174],
["9E", "R", 83235, 159],
["8E", "R", 45323, 159],
["4E", "R", 2124, 41]
]

script = '''\
addAbilityTap({
destroyTarget($target, $this)
}, "0")

setSpecificTarget("Select target
tapped creature to destroy.",
{
return $permanent.isCreature() &&
$permanent.isTapped()
})'


MagicWars - Shock
name = "Shock"
types = ["Instant"]
manacost = "R"
text = ["Shock deals 2 damage to target creature or player."]
prints = [
["10E", "C", 129732, 232],
["9E", "C", 83261, 220],
["ONS", "C", 39482, 227]
]

script = '''\
addSpell({
dealDamage($target, 2, $this);
})
setTarget("Creature|Player")
'''

Monday, December 7, 2009

Problem Domain Languages

It seems that I have gotten into a discussion of "problem domain languages" which is a language that only relates to a specific area such as controlling a robot. A problem domain language would let you move the robot and would consist of statements such as "go forward 3 feet" and "turn left".

Firemox, Wagic, and Forge have each created their own problem domain language for cards. The problem is "How to efficiently encode a Magic card into a computer programming language?" and the solution is to invent your own "little" computer language. Please note that problem domain languages are the opposite of general purpose languages such as C++ and Java.

All problem domain languages have approximately the same pros and cons. On the plus side the problem domain language will be more precise and shorter than a general purpose language. Problem domain languages can be parsed during runtime which promotes "late binding" and is more flexible than statically compiled code.

The negative side of problem domain languages is that they are hard to write because you have to take into consideration EVERYTHING that you want to do. If you make a mistake when you are creating your problem domain language, you might have to completely change your language and start again.

Creating a problem domain language is often very fun. You can use the Interpreter and Command software patterns to create a nice, little language for yourself. The easiest way is to make your own computer language is to create command objects that implement variable declarations, "if" and "for" statements. Now just put a few command objects together and *voila*, you have just invented your own (crappy) computer language.

Typically you would create a different command object for each part of the problem domain. The problem domain language for a robot would have a TurnLeftCommand and GoForwardCommand.

And what would this world be without Wikipedia? They have a pretty good explanation of problem domain languages here.

Thursday, December 3, 2009

Shock and Royal Assassin – Part 2

Today I'm going to examine how Firemox encodes Shock and Royal Assassin. Firemox allows you to play against other people on the Internet with rules enforcement. Firemox uses Java and currently has 6,041 cards.

Firemox uses XML to represent cards which is much better than using Java itself. On the plus side XML is usually shorter than Java and allows non-programmers to help. Using an "in-between" language like XML allows the programmer greater freedom when changing the code. For example, the damage code could be changed for all of the cards simultaneously because the damage code for each card is generated "on the fly" from the XML.

On the negative side, it hard to create XML code or any "do it yourself" language that is very flexible. The Firemox XML code below has a "colors" property which simply states the color of the card. Usually a card's color is determined by its mana cost but there are a few cards like Transguild Courier that are the exception.

I would hate to have to create an XML schema for Magic cards because it would be a very hard task. It would literally take weeks if not months. I'm sure that many hours of work was spent creating Firemox's XML language.

p.s. When I use the phrase "in-between" or "do it yourself" language, I'm talking about a problem domain language that only applies to a specific problem, like controlling a robot.

Firemox - Royal Assassin
<card> 
<rules-author-comment>By fabdouglas</rules-author-comment>

<init>
<registers>
<register index="colorless" value="1"/>
<register index="black" value="2"/>
<register index="power" value="1"/>
<register index="toughness" value="1"/>
</registers>

<colors>black</colors>
<idcards>creature </idcards>
<properties>assassin</properties>
</init>

<abilities>
<ability ref="cast-spell"/>
<activated-ability playable="instant" name="" zone="play">
<cost>
<action ref="T"/>
<action ref="target-creature">
<test>
<in-zone zone="playANDtapped"/>
</test>
</action>
</cost>

<effects>
<action ref="destroy"/>
</effects>
</activated-ability>
</abilities>


Firemox - Shock
<card>
<rules-author-comment>riclas</rules-author-comment>

<init>
<registers>
<register index='red' value='1'/>
</registers>
<colors>red </colors>
<idcards>instant </idcards>
</init>

<abilities>
<activated-ability playable='this' name='' zone='hand'>
<cost>
<pay-mana value='manacost'/>
<action ref='target-dealtable'/>
</cost>

<effects>
<assign-damage value='2' type='damage-normal'/>
<action ref='finish-spell'/>
</effects>
</activated-ability>
</abilities>

</card>

Monday, November 30, 2009

Shock and Royal Assassin – Part 1

When I first started working on Forge, I could only find two other Magic programs Firemox and Magma. Now there are programs such as Incantus, MagicWars, and Wagic which were inspired by this blog. (On a side note Incantus, MagicWars, and Firemox are like Magic Online and let you play against other people on the Internet with rules enforcement. Wagic and Magma let you play against the computer.)

All of these Magic programs, including my own (Forge), encode cards differently. Today I’m going to show how Forge and Wagic encode two familiar cards: Shock and Royal Assassin. Forge takes the direct route and shoehorns cards into Java while Wagic uses its own scripting language which is very short and concise.

Of the five programs mentioned I believe that Forge’s cards are the longest and Wagic’s are the shortest. Having short cards is a big advantage since it means less code is required for each card and hopefully less debugging. In Forge if you wanted to change the damage code, you would have to update each card that dealt damage, while Wagic would only have to tweak the damage code that is used for all the cards, which is a big improvement.

(This is a contrived example but it is generally true. Cards in Forge always a global static method to deal damage, so the damage code could be updated easily but other aspects of cards such as targeting do not always use a global static method.)

On a side note, usually Forge’s cards are very long but I forgot about the scripting code that people like Rob Cashwalker has been writing. (Since Forge is an open source project, letting other people do some of the “hard stuff” is truly wonderful.) Forge’s Shock is only 5 lines, which is great, and probably wins the title of “shortest Shock code”. So in reality some of Forge’s cards are very long like Royal Assassin and some of the cards are very short like Shock.

Wagic – Royal Assassin
[card]
text={T}: Destroy target tapped creature.
id=129708
auto={T}:destroy target(creature[tapped])
name=Royal Assassin
rarity=R
type=Creature
mana={1}{B}{B}
power=1
subtype=Human Assassin
toughness=1
[/card]

Wagic – Shock
[card]
text=Shock deals 2 damage to target creature or player.
target=creature,player
auto=Damage:2
id=129732
name=Shock
rarity=C
type=Instant
mana={R}
[/card]
Forge - Shock
Shock
R
Instant
no text
spDamageCP:2

Forge – Royal Assassin
if(cardName.equals("Royal Assassin"))
{
final Ability_Tap ability = new Ability_Tap(card)
{

public boolean canPlayAI()
{
CardList human =
CardFactoryUtil.AI_getHumanCreature(card, true);
human = human.filter(new CardListFilter()
{
public boolean addCard(Card c)
{return c.isTapped();}
});

CardListUtil.sortAttack(human);
CardListUtil.sortFlying(human);

if(0 < human.size())
setTargetCard(human.get(0));

return 0 < human.size();
}
public void resolve()
{
Card c = getTargetCard();

if(AllZone.GameAction.isCardInPlay(c) &&
c.isTapped() && CardFactoryUtil.canTarget(card, c) )
{
AllZone.GameAction.destroy(c);
}
}//resolve()
};//SpellAbility

Input target = new Input()
{
public void showMessage()
{
AllZone.Display.showMessage("Select
target tapped creature to destroy");
ButtonUtil.enableOnlyCancel();
}
public void selectButtonCancel() {stop();}
public void selectCard(Card c, PlayerZone zone)
{
if(!CardFactoryUtil.canTarget(card, c)){
AllZone.Display.showMessage(
"Cannot target this card (Shroud? Protection?).");
}
else if(c.isCreature() &&
zone.is(Constant.Zone.Play) && c.isTapped())
{
//tap ability
card.tap();

ability.setTargetCard(c);
AllZone.Stack.add(ability);
stop();
}
}//selectCard()
};//Input

card.addSpellAbility(ability);
ability.setDescription("tap: Destroy target
tapped creature.");
ability.setBeforePayMana(target);
}

Friday, November 27, 2009

Forge is the new official name

The name "MTG Forge" appears to attract Wizard's lawyers like flies to Aunt's Mays apple pie. Having the initials "mtg" seems to be the reason for the cease and desist letter about my original Sourceforge.net site. The name "Forge" sounds a little weird and empty to me but it is good enough. (And everybody by now should know that I am a firm believer in “good enough”.) The official name of this project is "Forge" and my official nickname is "mtgrares".

I tried calling myself forge but it is a little bit confusing having the same name for both a person and a project.

Wednesday, November 25, 2009

Forge's Architecture

The architecture for a computer program is very important since everything else in that program relies on it. Computer architecture is very similar to constructing a physical building. The program's architecture is the concrete foundation that you build on. If the foundation is cracked or broken, then you have a BIG problem. (I hope you understand that a program's architecture is very important even though you cannot see it.)

Forge's architecture restricts which cards are supported. Some cards cannot be added because the architecture isn't flexible enough. Cards like planeswalkers aren't really supported but were added by using elaborate hacks. The same thing applies to cards like Hypnotic Specter and Glorious Anthem. Even activated abilities that tap a card like Royal Assassin have to be "hacked" a little.

All of these "little hacks" add up and causes something later that "should work", not to work. Protection was a major update that required all of the targeting code for all of the cards to be changed. I didn't think about protection when I was creating Forge so all of the cards have to be changed one at a time in order to support protection.

Dennis, Rob, Zerker and others from the forums have donated weeks of their time toward Forge. And although I created Forge, these are the guys that keep it going.

Monday, November 23, 2009

Forge Is Not a One Man Project

Sorry for the long title but I couldn't think of a shorter one. The title is trying to say that many people have contributed to Forge. One person improved the card download and added a cool looking progress bar. Another person compiled a list of cards that could be added to "cards.txt". Someone else coded a few new cards.

This is article is also a big THANK YOU for everyone that has contributed to Forge. Forge really is a group project.

To view a complete list of people and their contributions, see the forum here. Below is a summary.

DennisBergkamp - is currently the lead developer and has the unpleasant job of making sure that everything doesn't fall apart. (Everything will fall apart, it is just a matter of when.) This is the guy that rewrote all of Forge's targeting code in order to support protection.

Rob Cashwalker - has transformed cards.txt from a simple file into keyword madness. He spearheaded the movement to add more and more "keywords" like drawing card and dealing damage to cards.txt. One of his earliest contributions was landwalk.

Thanks to Slightlymagic.net and Huggybaby for providing Forge with its very own forum.

Silly Freak created the "resizable game option" which allows Forge to be resized. He also wrote the "central error code" that shows the nice reports as well as divided up Forge's files into convenient directories.

Zerker has done a great job adding the mana pool and other cards.
Nantuko84 gave me the code that shows the card pictures in play as well as added several cards and added filters to the deck editor.

Mr. Chaos was one of my first, exuberant fans that sent me more than enough error reports.

Apthaven helped to spread the word of Forge far and wide as well as posting bug reports.

Chris. H. has done a fantastic job of keeping up all of the rarities for all of the cards in Forge. He is also responsible for playtesting the quest decks and determining the difficultly of a deck. Currently the decks are only divided up into three categories: easy, medium and hard, but three more "wizard" categories are going to be added soon which should make questing more difficult.

The hard thing is that once you start listing people you inevitably leave someone out, so let me say sorry in advance.

All of these people have helped make Forge the superb program that it is today. (These people also deal with all of Forge's inherent problems that I created. Reading someone else's code is like trying to follow a complicated math problem.)

Friday, November 20, 2009

DCMA Google Notice

I just received a e-mail notification from Google, the owner's of blogspot.com, that one of my posts contained an illegal link. The link was obviously to MTG Forge. I presume that this blog won't be shut down but who really knows.

I'll just post updates on Mediafire.com for awhile. This isn't a great way of doing things because MTG Forge will probably be removed from mediafire.com also.

(This is directed toward Wizards of the Coast. I enjoy Magic and I also understand that you own Magic and can do whatever you want to do with it. I also understand that you have been burnt by other computer programs such as Apprentice and Magic Workstation which makes money off of your work.

MTG Forge has about 2,000 cards and is a casual player's dream. Some of these cards are on your restricted list and will never be printed again like Tithe, Sapphire Mox, Timetwister and Wheel of Fortune. Other cards are out-of-print powerhouses like Flamtongue Kavu and Kiki-Jiki, Mirror Breaker. MTG Forge has a few cards that are in Standard such as Wrath of God, planeswalkers, Lightning Bolt and a variety of creatures with a few "vanilla" abilities.

You are not loosing money when people download this program. I officially want to wave the white flag of peace and would enjoy talking to you on the phone. Anyone from a wizards e-mail address can contact me at (mtgrares yahoo com) and I will give you my phone number.)

Improving Min-Max and Alpha-Beta on Wikipedia

Min-max and alpha-beta are both mentioned on Wikipedia but they have horrible, unusable pseudo-code. The book “Algorithms in a Nutshell” has GREAT pseudo-code so I posted it in both of the discussion sections. (I was too afraid of making the changes myself in the main Wikipedia entry.) Below are links for min-max and alpha-beta pseudo-code.

Min-Max
Alpha-Beta

Wednesday, November 18, 2009

Difficult Cards to Program

Magic is great game full of wonderful, complicated cards. Today I'm going to talk about some of the hardest, thorniest cards to implement.

MTG Forge has 2,100 cards so there are plenty of complicated cards to choose from. The planeswalkers stand out in my mind. I had to add an extra combat phase which wasn't too hard (although MTG Forge still suffers from the flaw that if your opponent has two planeswalkers, you can only attack one of them). The planeswalker's abilities were the hardest part because I had to write the code from scratch which involves some very heavy hacking.

Many planeswalkers have rather common effects but Elspeth, Knight-Errant ultimate ability says "For the rest of the game, artifacts, creatures, enchantments, and lands you control are indestructible" which isn't something easy like dealing damage, it generates an ongoing effect. Each of the planeswalkers took about 220 lines.

Both Adarkar Valkyrie and Kiki-Jiki Mirror Breaker both have abilities that copy creatures and each take up about 100 lines of code. Adarkar Valkyrie lets you "steal" a creature if it is put into the graveyard and Kiki-Jiki lets you copy one of your creatures for one turn, then it is sacrificed. Both cards are extremely fun to use because of the broad variety of creatures that have effects when they enter or leave the battlefield. Flametongue Kavu is a perfect example. He is a 4/2 and does 4 damage to one creature when it enters the battlefield. Combine him with Kiki-Jiki to really turn up the heat.

Incendiary Command was very hard to program but the card isn't that useful. It weighs in at around 200 lines. I coded it after my (failed) phone interview with Wizards. The head guy who called himself Elf or something, asked me how I would implement the 5 card cycle of Commands. I answered him then furiously coded Incendiary Command that night.

I eagerly e-mailed him the next day and ... well nothing happened. For some reason I chose Incendiary Command which is the weakest card in the cycle. When I add cards I usually like to get more bang for my buck, like a super big creature or a devastating spell. I wouldn't even pay 25 cents for Incendiary Command, it is a crap rare indeed. I would rather use the cheaper Pyroclasm which only costs 1R and deals 2 damage to each creature.

p.s.
Kiki-Jiki is unusual because it creates tokens that have a name, typically tokens are nameless.

Monday, November 16, 2009

New Version

I'm always happy to announce a new version of MTG Forge. This version has 268 new cards which brings the grand total up to a whopping 2,149. Well kiss my grits, that's alot of cards, oh my!

MTG Forge finally has Pacifism, which is a classic card. White also gets other new creature enchants like Pillory of the Sleepless, Cessation, Nimbus Wings and Bound in Silence. Two other great classics were added: Giant Strength (enchanted creature gets +2/+2) and Rukh Egg, for those crazy, red mages. Feel free to put it into a red and white deck with Wrath of God for some good old-fashioned fun.

For those Johnnies out there, Sunglasses of Urza is calling your name. Those crazy glasses let you spend white mana as though it were red. Some people would argue that Sunglasses of Urza is worthless but hey, MTG Forge has it now so you can burn any copies that you own. The powerful signets from Ravinca are also included. They let you turn 1 mana into 2, which sounds like a pretty good deal to me.

Some of the Zendikar cards which are included are: all 5 Refuge lands (the lands make 2 colors and give you 1 life but enter the battlefield tapped), Umara Raptor and 6 other new ally creatures which get a +1/+1 counter every time you play another ally creature.

This update was written by the great guys from the forum Rob, Dennis, Zerker, and Silly Freak, Chris and Cyclope. They have kindly donated hours of their time (and sanity). Without those guys, none of the "magic" would happen (pun intended, ha).

p.s. This is the same as the 10-18 version that was posted on the forum. (Yes, the forums get all of the new stuff first.)

p.s.s. I did finally update the set editor which is included in the download below. The set editor lets you change the files that are used to generate the booster packs. Booster packs are used for sealed, drafting, and quest. Basically you can add/remove cards or change the rarity. Also note that the booster pack code doesn't support mythic rares.

Download MTG Forge

Friday, November 13, 2009

Min-Max Evaluation Function For Magic

Below is taken from a private forum about a private Magic program that uses min-max for the computer AI. The AI easily out performs MTG Forge's AI and can play instants and abilities during combat. The author's idea was to use an object with different "layers" for the evaluation function instead just number. (I'm sorry for keeping the name of this program private, but that is the author's wishes, not mine.)

Below is copy and pasted from a private discussion. I did not write it. I'm still working on my own version of min-max and Magic.

I got a lot of requests asking me the AI evaluation function in (private Magic program). I will try to explain a little bit of the function here. You may need to have a basic understanding of how Minimax algorithm works first before you can totally understanding how to apply this to your program.

In the very first engine I have created, my evaluation function is very simple. Basically it counts how many cards in-play for the player and combine that with the player's life. Since life is more important than how many cards a player has put in-play, the life total is multiplied. The result is what I called a score and each area contributing to this score is a component. This calculation is also done for the other player and is subtracted. So for example:

Player 1 - 3 in-play cards - 20 life -> 3 + 20 * 100 = 2003
Player 2 - 10 in-play cards - 18 life -> 10 + 18 * 100 = 1810

Score for player 1 at this stage is 2003 - 1810 = 193 (score for player 2 will be -193)

You will be surprised by how Minimax can perform some amazing things with such a simple evaluation function. There are some special cases in the equation I am not mentioning here. These cases are used to handle losing conditions besides a zero or negative life, e.g. draw with no cards in library, losing condition set by a card, etc. In those cases a lowest possible negative number is used for the player's score regardless of other components.

As a side note, if my computer is infinitely fast and can evaluate the whole game from start to finish in a reasonable time, the evaluation function can be as simple as using just players' life total (plus the win/lose special score.) This is because A.I. can foresee all the consequences of each move and number of in-play cards is not needed to make a sensible decision.

Since our computer can only do a limited amount of calculation and MTG is not a simple game like tic-tac-toe, we need to guide the Minimax/alpha-beta algorithm to an approximated score when an end-game state cannot be achieved. The in-play card scoring part in the above example is one of the approximation. Now you can find many example of winning a game without a single card in-play (e.g. using red.) However in a more general sense the player life part of the equation is kind of balancing this out. So either you are putting cards out or reducing your opponent's life. If you are not doing both, you are not in a good position.

After the first version of the evaluation function, I quickly found out that not all cards are equal and I shouldn't give them equal scores. Ideally, if a card's purpose is to reduce an opponent's life and is effective about it (directly or indirectly), the opponent's life decrease should reflect in the evaluation function and so the merit of one card will be obvious against another card which cannot achieve the same thing. However, when there are too many possibilities and time is limited, Minimax may not be able to reach such a conclusion.

At first I tried to give a card more points when it has more abilities and in case of creatures considering their power and toughness. Later I changed to a more generic 'base' score by just looking at a card's casting cost. The calculation is simple, 150 points for colored cost and 100 points for generic cost. This simple calculation can usually account for how powerful a cards is. However if a card has an unreasonable cost, e.g. Black Lotus, this calculation will not give Minimax a good representation of the card. Hopefully in those case the power of the card (or the lack of) will be reflected in other evaluated parts. Besides the base score, a few bonus points will be added for creatures' power and toughness points.

Besides in-play cards, there are points given to cards in hand and library.

I want to get back to the multiplier given to the life component in the above example. When I add more and more components to the score, it becomes easier for components' scores to 'overlap.' In the above example, using a multipier of 100 will not be enough if all the in-play cards' score total is exceeding 100. Once that is happening, Minimax will behave weird and no longer to preserve a player's life but to put more cards on the table!

To create a solution which is once and for all, I have created a separate score class to deal with scores rather than just use a single integer number. Basically the class has multiple layers of sub-scores. Sub-scores in the upper layer are more important than sub-scores in the lower layers. Each sub-score value is by itself an integer which will allow me to have more precision in tinkering. These are the current list of all the sub-scores:

Limits - represents boundary situations, highest significance
Wins - represents win/lose situations
Creatures - a special sub-score to allow a less conservative play in early game situations
Life - represents play life
Library - represents cards in libraries
InPlay - sub-score for in-play cards
InHand - sub-score for hand cards
Misc - minor scores to prevent indecisive situations, lowest significance

Comparisons of two scores is performed by comparing the highest significant sub-scores against each other first. If they are the same, the next lower significant sub-scores are compared and so on.

Wednesday, November 11, 2009

Evolving a Good Evaluation Function for Min-Max

This is very nerdy so feel free to skip this and watch an episode of The Simpsons or even better The Big Bang Theory. I really do think I'm half-Sheldon and half-Leonard, ha. (I promise to write a normal article about MTG Forge next time.)

For my geeky readers, you might want to checkout this article about evolving a good evaluation function. The name of the article is "Bootstrap Learning of Alpha-Beta Evaluation Functions" which refers to the evaluation function that is used for alpha-beta, an optimized version of min-max. (The article uses the Greek symbols alpha and beta.)

I'll try to summarize the article. The min-max algorithm doesn't involve any learning since it uses a static evaluation function and the article proposes the idea that you save the game state tree that is generated and try to evolve a better evaluation function. The idea is to test the evaluation function with the previously generated game tree to see whether the evaluation function made good choices.

(Remember that the goal of the evaluation function is to determine which player is winning and by how much. Usually the evaluation function generates an integer number to represent how much the AI is winning or losing.)

Saving the whole game state tree that alpha-beta creates is difficult. I understand the alpha-beta algorithm but I don't understand it well enough to code it and the alpha-beta code that I have found is recursive, so I don't know how to save the game state tree that is created.

Basically the article is really interesting and has some really good ideas but I'm not sure how to practically use it. (Thinking about AI hurts my brain.)

p.s.
I got my four year bachelor's degree in Information Science but we didn't touch AI. I really need a Master's degree or PhD in order to really understand AI. Anyone willing to foot the bill? :*)

p.p.s.
I found a nice Java implementation of the alpha-beta algorithm in the download section for the book "Algorithms in a Nutshell". You can read more about the book and download the code from here. (To download the Java source code the link is on the left side in small letters, click on "Examples". Now you should see three directories, click on "Releases".)

Or you can download the 10 MB zip file from here.

Monday, November 9, 2009

Why Programming AI is Hard - Part 4

This is the fourth and final part in this series that explains how the min-max algorithm could improve MTG Forge's AI. I'm going to summarize the previous three articles.

AI programming is hard. Actually any computer programming is hard, but AI programming is even harder. I feel that this is important, so I keep emphasizing this point. It is like saying if you know English then you should be able to write a novel or be able to read a medical dictionary. Writing a novel or reading a medical dictionary is a very specialized form of English.

The min-max algorithm works for two player games like chess and should also work for Magic: The Gathering. Actually using min-max in MTG Forge is very hard because of the programming. You have to copy everything and iterate through the each player's actions. Basically the min-max generates future game states and picks the best one. (Instead of copying the game state it would be better to implement an undo system using Command objects. That way you wouldn't have to copy everything.)

The min-max algorithm has to figure out who is winning. The min-max algorithm might generate 1 or 2 moves ahead and then try to determine which player is winning. Determining which player is winning is very complicated and will require much tweaking. Most of the time the min-max algorithm will not be able to generate all future game states because the number of possibilities is astronomical.

Well this ends this series of four articles that examines the question, "Why programming AI is hard?" The min-max algorithm is very important and I'll bore you with more details later. (joke)

Friday, November 6, 2009

Response to Comments

My last post generated a lot of comments and I wanted to address a few of them. Much of MTG Forge contains my “philosophy” of computer programming and Magic. My philosophy is often “if it is good enough, then stop.” Different people have different ideas about what is “good enough” and usually for me “good enough” means what is easiest for me to program. (I always knew that the user interface was going to be very plain at best.)

Many people don’t like the idea that the AI cheats. Of course most of the time people don’t know that the AI really does cheat. If I write and say that MTG Forge’s AI looks at your hand, people would get upset. But if I never tell people, they wouldn’t ever know, so they couldn’t get upset. (And please note that MTG Forge’s AI does not look at your hand because it wouldn’t be helpful.) I try to give users as many options as possible and MTG Forge has the option to smooth the AI’s land but you can also turn that option off.

MTG Forge is really just thousands of little decisions that I and other people had to make. Much like movie reviews where a person watches a movie for two hours and then criticizes it, I (and others) have spent hundreds of hours working on MTG Forge. If something works, like the deck editor, I receive no comments about it but if something is broken, I receive tons. Often I receive more criticism than praise and it doesn’t bother me. People are using MTG Forge and are enjoying a good game of Magic and that was my goal. (Ok, really my goal was for me to enjoy a good game of Magic but I don’t mind sharing.)

All of MTG Forge’s major flaws are a result of decisions that I made, such as the AI isn’t great, you can’t sideboard, and not all of the phases are implemented and I understand how these omissions could be frustrating for other people to understand.

I didn’t want MTG Forge to be a half-written program that never really did anything. Sourceforge.net and other sites have a TON of half-written programs which no one uses. MTG Forge is useable and despite some horrible coding practices like 10,000 line methods and global variables, it is very playable. (I just enjoyed a great 10 game quest last night. Ok, you got me, it was really a 16 game quest because I lost 6 times, ha.)

And to quote myself, MTG Forge is a collection of bugs that happens to play Magic.

p.s. I love the new Zendikar basic lands, they look great.

p.p.s.
Truthfully, I'm a perfectionist and I want everything to be 100% perfect but then I would have never completed MTG Forge. Computer programming (and life) often involve compromises.

Wednesday, November 4, 2009

Why Programming AI is Hard - Part 3

Hopefully you read (or at least glanced) through parts 1 and 2 that talk about how the min-max algorithm can be used to simulate an AI opponent. This article describes some of the problems when using min-max.

In theory min-max can only be used for games that don't have any "hidden information" and in Magic, the cards in your hand and deck are "hidden information". I have no problem with the idea of allowing the min-max algorithm to see all of the cards in you hand and deck. The only possible "problem" that I see is that this might create an AI that is "too good". I seriously doubt this situation would occur because of the complexities of the actual programming.

(Programming is very hard in case you forgot, ha, but you probably didn't forget because you might be a programmer yourself. Programmers have to interface directly with the computer, so technically, programmers aren't human.)

p.s.
In order to use the min-max algorithm you have to be able to generate all possible moves for both players. I could have also said, "In order to use the min-max algorithm you have to generate all possible game states." I didn't use the term "game state" because I didn't want people to geek out and quit reading my blog. :--)

p.p.s.
On a side note, according to Wikipedia there is a variation of min-max that can use probabilities. You could use probabilities instead of taking my suggestion of revealing the hidden information; there is a 20% probability that your opponent is holding Wrath of God in his hand.

Monday, November 2, 2009

Why Programming AI is Hard - Part 2

I'm going to continue my thoughts about the AI algorithm min-max. Previously I said, "In order to use the min-max algorithm you have to be able to generate possible moves for both players."

Ideally you would generate all possible moves for both players until the game ends. Usually generating all possible moves is impossible even for simple games like checkers, so the trick is to use an "evaluation" function that evaluates the game. The evaluation function basically determines which player is winning.

A rough analogy would be a person's life points as a very simple evaluation function. Usually the person with the highest life points is winning, notice that I said "usually". A good evaluation function for Magic would look at both players' life totals, cards in hand and creatures in play to determine which player has the best chance of winning. Needless to say that the evaluation function for Magic would be very complicated considering creatures like Keiga, the Tide Star and Royal Assassin which can win games by themselves.

Creating a good evaluation function is very important. If your evaluation function is lousy, then your AI will be lousy. (There is probably a better word than "lousy" but it conveys the right idea.)

As you may or not remember, the XBox 360 game Duels of the Planeswalkers used min-max. You can read about the AI engine that the game uses here.

p.s.
Technically min-max can only be used for games that don't have any "hidden information" and in Magic, the cards in your hand and deck are "hidden information". Read my *astonishing*, earth-shattering post on Wednesday that solves the hidden information problem.

p.p.s. I just picked Phelddagrif because it had a weird picture.

Friday, October 30, 2009

Open Letter to Wizards of the Coast

This is directed toward Wizards of the Coast. I enjoy Magic and I also understand that you own Magic and can do whatever you want to do with it. I also understand that you have been burnt by other computer programs such as Apprentice and Magic Workstation. I also realize that you want to close down websites such as magic-league.com

My program Forge has about 2,000 cards and is a casual player's dream. Some of these cards are on your restricted list and will never be printed again like Tithe, Sapphire Mox, Timetwister and Wheel of Fortune. Other cards are out-of-print powerhouses like Flamtongue Kavu and Kiki-Jiki, Mirror Breaker. Forge has a few cards that are in Standard such as planeswalkers, Lightning Bolt and a variety of creatures with a few "vanilla" abilities.

You are not loosing money when people download this program. I officially want to wave the white flag of peace and would enjoy talking to you on the phone. Anyone from a wizards e-mail address can contact me at (mtgrares yahoo com) and I will give you my phone number.

Wednesday, October 28, 2009

Why Programming AI is Hard - Part 1

One of the most common questions that I get asked is "Why is the AI so bad?" and I understand where people are coming from. When you play a game of Magic in real life you expect a certain level of sophistication from your opponent. A human opponent will attack and block intelligently and play cards that improve his chance of winning. MTG Forge's AI often doesn't attack or block intelligently and sometimes shoots itself in the foot with cards like Ambition's Cost (3B, Sorcery, You draw three cards and you lose 3 life).

The computer has been known to play Ambition's Cost when it only has 2 life, thus losing the game. This situation can be improved by programming the computer NOT to play Ambition's Cost when it has 3 or less life but this doesn't improve the situation very much because currently MTG Forge's AI cannot determine whether the cards in his hand are good or not and thus randomly plays Ambition's Cost like a drunken sailor. (Sing with me, What-would-you-do-with-a-drunken-sailor, What-would-you-do-with-a-drunken-sailor, What-would-you-do-with-a-drunken-sailor, Early-in-the-morning, ha.)

One common AI algorithm that is suitable for two player games likes chess and Magic is min-max, also called minimax or alpha-beta (which is an optimized version of min-max). Min-max is named after the conflicting goals of the two players, you want to maximize your chance of winning and your opponent wants to minimize it. In order to use the min-max algorithm you have to be able to generate possible moves for both players.

OK, take a breath **whoooo**. I know we are just scratching the surface but you've digested some difficult stuff and hopefully you feel smarter without having to listen to boring classical music. (I like classical music, just not the screeching violins. Please leave a comment if you actually do play violin.)

Stay tuned for more info, this is a four (or five) part series and yes I do get more technical.

p.s. This is the first time that a web page has mentioned both drunken sailors and the min-max algorithm, my highschool English teacher would be proud. :--)

Monday, October 26, 2009

MagicWars - Player versus Player

MTG Forge has been a very successful "small Magic program" so I try to inform my readers of other Magic projects. MagicWars is a great new program which lets you play against another person on the Internet and enforces all of the rules. The program was written by nantuko84 and you can post questions to the MagicWars forum. It has a nice shiny user interface with lots of eye-candy (unlike MTG Forge) and currently has 450 cards.

MagicWars has 100 cards from Zendikar as well as all 145 cards from Alara Reborn, which includes cards with cascade. Implementing a whole set, even a small one, is phenomenal. MagicWars has many decks that are currently running around in Standard such as Time Sieve, RW Reveillark, UB Faeries, and Cascade-Swans, which makes MagicWars appealing to players that want to playtest current decks.

I have previously written about why a good user interface is very important and MagicWars doesn't disappoint in this area. The user interface is very nice with pretty little icons that appear next to cards that have abilities such as flying and deathtouch. MagicWars also supports such advance features as transparent windows and changeable backgrounds.

The project is written in Java and is open source, so anyone can contribute. Nantuko84 also writes a blog.

(Warning Will Robinson, MTG Forge users should put on sunglasses before viewing screenshots with this much eye-candy.)

Screenshot 1 - game in progress
Screenshot 2 - deck editor

Download MagicWars

In order to host a game you have to manually type in your IP address. Below is taken from the wiki.

Just unpack archive and run bat file. If you need to host a server, change address in MagicWars.properties file

address=localhost to address=

and in jndi.properties (I will find out later how to set jndi on a fly from java) jnp://localhsot:1099 to jnp://your IP:1099

That's it! Have fun ;)

Wednesday, October 21, 2009

MTG Forge - The Beginning - Part 2

When I was working at Rhino Video Games (which was bought out by GameStop) they had a few 8th Edition Starter decks. I bought a few of them and really enjoyed the game. At that time I thought that trading card games were a gift brought down by the gods. After I explored a few other trading card games I understood that Magic: The Gathering was the first and the best TCG game around. Other TCG games are interesting but nothing has the depth of Magic.

The first TCG videogame that I was exposed to was Yu-Gi-Oh on Gameboy Advance and I absolutely fell in love with it. The game enforced all of the rules and it was phenomenal. At the beginning, MTG Forge was actually an implementation of Yu-Gi-Oh and later I learned of Magic and converted my project. Later I found Magic Online and through my experience I learned the rules of Magic well enough in order to program MTG Forge.

MTG Forge to me is a very personal project and I'm very glad that other people have fallen in love with my program. And although MTG Forge was started as a one man project, currently there are a few people who help out. The forums have really been a great help. I personally coded MTG Forge's first 1,200 cards but other people have contributed all of the other cards past that point.

p.s.
The worst videogame TCG that I played was the awful "Marvel/DC Vs." game for PC, if you clicked on a card you HAD to play it, the program didn't have a cancel button. Playing the videogame was dreadful for a beginner because I would accidentally click on a card like "Giant Growth" and the computer would make me use it. I still admire the VS TCG since it has comic book characters and interesting mechanics, no land cards.

p.s.s.
MTG Forge was also greatly influenced by the Microprose PC game Duels Of The Planeswalkers, which people informally called Shandalar. I love creating decks using all of the cards but drafting, even with those horrible old sets, really sucked me in and I wanted to draft more. One of my biggest pet peeves was annoying draft cards that were either too powerful or too wimpy, so that is why I allow the user to easily add or remove cards from the draft set. (Just remove the card name from one of the files: common.txt, uncommon.txt, or rare.txt)

Monday, October 19, 2009

MTG Forge - The Beginning

When I started programming MTG Forge, I didn't know if the program would ever be good enough for someone else to play and enjoy, there are MANY half-written programming projects on the Internet. MTG Forge was created on a very old computer (700 MHz CPU, 128 MB) with an old version of Java 1.2, now Java is up to 1.6 or something.

Even though I had graduated with a bachelor's degree in computers the longest program that I'd ever written for college was in Cobol. It was a 500 line monstrosity that could have been easily written in 100 lines of Java. The longest Java program that I ever wrote for college was probably around 70 lines. Yes I enjoyed programming but that doesn't mean that I was necessarily good at it.

I had about three "false starts" with MTG Forge. A "false start" is when the program was sufficiently large and was actually doing something but when I added more stuff to it, it would just brake and the program could not be fixed.

This meant that the architecture wasn't correct, so I would use some of the "good stuff" like the Card and SpellAbility classes and then try to write a better foundation the program wouldn't "brake" in the future.

Wednesday, October 14, 2009

Publicity (aka advertising)

In the beginning no one downloaded MTG Forge because no one knew about it, so I began my publicity campaign (which I think of as advertising). The first public thing I did was to begin this blog. Starting out was difficult and I was only getting 2 or 3 views a day which was abysmal. I even thought about closing it down.

After I really understood what people wanted, just Magic and computer programming, I was able to focus and write articles that people enjoyed. I limited myself to only posting twice a week (for my sanity) and keeping the articles relatively short, 150-300 words.

The obvious first place to advertise is on Magic forums. So I posted some stuff on StarCityGames.com and was banned because I "advertised" too much. Now I understood that I need to advertise but in a gentle fashion, "Oh have you heard about this program that lets you play against the computer?" Another good place to advertise is the Wikipedia article on Magic: The Gathering. One day I casually added a paragraph about MTG Forge and I still get about 1/3 of my hits from Wikipedia.

Recently I advertised on cubedrafting.com. MTG Forge isn't really a cube but I posted about it anyways and 256 people read my post. (A cube is a special collection of cards that is specifically designed for drafting.)

Currently my blog gets around 150 views a day while is absolutely phenomenal but I still advertise a little in order to increase the number of people that know (and love) MTG Forge. :^)

p.s.
StarCityGames.com did forgive me and they let me write an article about MTG Forge and recently Abe Sargent also wrote about MTG Forge (thanks for the advertising).

Monday, October 12, 2009

User Interfaces Are 90% of a Program

MTG Forge has progressed from being "merely ok" to "totally fantastic". When I started MTG Forge from scratch I was very nervous and questions like "How good can you write a user interface?" and "Exactly which cards can and cannot be supported?" and "How good with the AI be?" haunted my mind. It is really tough to convince yourself that it will be ok and to start the project anyways.

In the beginning MTG Forge didn't use any card pictures, it only showed colored boxes with the cards name and the mana cost. Then I figured out that I could show the card picture in the panel on the right and later someone figured out how to resize the picture and show it for cards in play.

In the beginning I really wanted to resize the card picture and put them "in play" or on the battlefield but I didn't know how to rotate a card picture 90 degrees. Someone sent me come code which rotated the card picture in ONE LINE. All it takes is one magical line that I couldn't figure out.

At the beginning I received many e-mail complaining about the user interface but after a few changes I stopped hearing about it. From this I learned the first law of programming for the public: "User interfaces are the single most important part of a computer program." The second law is that "Once X is good enough, you will stop hearing complaints about X." MTG Forge's user interface isn't perfect, but it certainly seems "good enough" for most people.

If something is bad you will definitely hear about it. If something is good you might hear about it, lol.

Wednesday, October 7, 2009

How MTG Forge Uses the Mouse for Targeting

I couldn't think of a shorter title. Today I'm going to talk about how MTG Forge uses the state pattern to handle all of the mouse input. I'm afraid this is going to be a little bit technical and boring, so feel free to stop at any time. This is probably most interesting to those few people who actual want to program Magic or another card game from scratch.

I'm going to try to explain my idea but fundamentally it all comes down to using the state pattern. The state pattern lets you change the behavior of an object. Let me show you an example in Java.

interface Mouse
{
void clickCard(Card c, Zone z);
}

class MouseControl
{
private Mouse m;

public void setMouse (Mouse mouse)
{
m = mouse;
}

public void clickCard(Card c, Zone z)
{
m.clickCard(c, z);
}
}
MouseControl really doesn't do much and just passes along the information to the Mouse object. The Mouse object overrides clickCard() and does the really "work." To select a target for Giant Growth you would override Mouse.clickCard() to only allow the player to target a creature. The pseudo-code would look like this.

class GiantGrowth implements Mouse
{
public void clickCard(Card c, Zone z)
{
if(Zone.equals("Battlefield") && c.isCreature())
{
//process and go to the next Input
//if you read below, this is where you would call stop()
}
}//clickCard()
}
In MTG Forge I don't have a Mouse interface, I call it Input, and MouseClick is renamed InputControl. (Really Input is just an Adapter class, an interface with methods that don't do anything.) The Input class also has methods to click on a player, so you can target a player. The user interface only uses InputControl and doesn't care which specific Input object is currently being used.

The Input and InputControl classes can become very complicated especially when you consider the rare situations where Inputs can be "stacked" such as if you have a Keiga, the Tide Star in play and you play another one. Both cards go to the graveyard because they are legendary and the player will get to gain control of two creatures. Currently MTG Forge does not "stack" Inputs and doesn't correctly handle the above example with Keiga, the Tide Star.

Hopefully now you understand the power of the state pattern. In MTG Forge all of the phases are implemented as Inputs. Input objects are used for mulligans at the beginning of the game and to pay for mana costs. When I programmed MTG Forge I took many shortcuts in order to get finished, but this is one area which works beautifully and is one of the cornerstones of MTG Forge's success.

p.s.
Below is the Input class from MTG Forge which has many more methods. While handling mouse inputs is nice, really I want to tie the text of a card such as "Target Creature" or "Target Player" with the mouse so the Input class shows text to the user using showMessage(). Whenever InputControl switches to a another Input, it calls the showMessage() method first, so the user will know what is going on.

The Input class also handles if the user clicks on one of the two buttons. Typically the buttons show the text "OK" and "Cancel" so the Input methods are named selectButtonOK() and selectButtonCancel(). The ok and cancel buttons can display different text such as "yes" or "no" and one or both buttons can be disabled.

Whenever an Input object gets done executing, usually when the user clicked on a creature, the stop() method lets InputControl know that it can go on to the next Input. The next Input is typically an Input that represents a phase such as Main 1 or Declare Attackers. When a spell or ability is on the stack, an Input is also used in that situation.

For a card like Giant Growth the user chooses a target creature then pays for the card. In the targeting code, which is an Input, after the user has click on a creature the Input would call the method stopSetNext(Input in) which stops the current Input and allows the argument to be next. So in the Input used to choose the target creature, after the user has clicked on a creature it would called the method stopSetNext(new PayManaCostInput()) so the user can pay the mana cost.

I know this is a lot of information but if you are serious about programming a game like Magic, you really need to use the state pattern to handle the mouse. More information about MTG Forge Input's can be found on the forum here.

public class Input 
{
//showMessage() is always the first method called
public void showMessage() {AllZone.Display.showMessage("Blank Input");}

public void selectCard(Card c, PlayerZone zone) {}
public void selectPlayer(String player) {}
public void selectButtonOK() {}
public void selectButtonCancel() {}

public void stop()
{
//this lets the InputControl know that it can go on
//to the next Input
//this method works like exit()
}

public void stopPayCost(SpellAbility sa)
{
AllZone.GameAction.playSpellAbility(sa);
}

//exits the "current" Input and sets the next Input
public void stopSetNext(Input in) {stop(); AllZone.InputControl.setInput(in);}
}