I started Forge, which is an open-source, free project that lets you play Magic: The Gathering against the computer. Currently other people are updating Forge and there will be no more posts to this blog.

Monday, September 8, 2008

Programming Cards using Plaintext

If you read my previous post I asked the question, “How do you condense a Magic card into reusable parts that can be written as text?” There are many answers to this question but I will show you how I plan to do it for MTG Forge version 2. I plan to encode cards using only text.

This is how cards will be encoded in version 2. Gone are the days of having to know Java. There is a lot of similarity between these two cards. Assassinate and Royal Assassin’s ability both have the same targets and resolve. My goal is to reuse the same Java code for both of these cards. My current way of cutting-and-pasting code is hacky to say the least.

The format above is similar to the current format in cards.txt. I love plaintext because it is so easy to read and understand. I am thrilled with the possibility of being able to encode spells like Assassinate using only plaintext. I realize that the format above won’t work for all cards, like Fire//Ice, but it will work for 90% of them.

This plaintext encoding is also very easy to parse. (Parsing is when the program interprets the plaintext and actually constructs the code for the card.) My goal is to reduce a card into a set of reusable parts. I want multiple cards to use the same targeting and resolve code.

Personally I am very excited about this “discovery.” The plaintext is very readable by both humans and machines. Practically I could add this to MTG Forge version 1 but I’m going to put it into version 2, because version 1 has many bugs.

I already have the experience of programming many Magic cards and I know what needs to be improved. Multiple cards need to use the same code. All cards that say “gain life” should use the exact same code and in version 2 they will.

Like I’ve said before, there are many ways to encode cards as text. My way may not be the best way for someone else, but it is the best way for me. I understand these plaintext cards and I “see” the code in my head. The targeting and resolve code can be separated and I also understand how to connect the targeting code to the resolve code.

p.s.It seems like I could remove the “text:” line but it greatly simplifies everything by keeping it. My goal is to make parsing as easy as possible and hopefully idiot proof, lol. (Parsing tends to be very complicated and hard to test. And yes regular expressions make parsing easier, but I want it to be very easy. And like all things in MTG Forge, it can be changed later. For all your programmers out there, I call that “very late binding” LOL.)

This plaintext encoding can also work for triggered and static abilities.

i hope the examples were not exactly as you imagine them. in whole, it's a good idea, but you should be careful with using the targeting restrictions in the resolve part. for example, ballista squad says "attacking or blocking creature" in the target but only "target creature" in the resolve. parsing that is maybe not that simple

also, for finding cards by properties (creatures you control, cards in your graveyard...), i think you should use a more generic ability.the "creatures you control get X/X" ability is very specific. it doesn't even allow night of souls betrayal. I imagine cards(controler=you,type=creature) or something like this.

the same could easily be done for targeting. it would mean to target one card matching the criterion, which would be also checked on resolution.

Making these generic abilities is easy as long as they're uniform in targeting. It's providing for these cases where there are many different restriction combinations....

Creatures you control is easy. All Creatures is easy. All Black Creatures is moderate. Black Elf Creatures You Control is getting more difficult. And those are just dealing with color, type and controller, the most very basic restrictions. Throw tapped into the mix, and wait for hell to freeze.... Reading this information is no problem. It's using this information later to form the spell abilities in code where it gets sticky. When I tried to implement a fraction of what Forge is talking about, I ended up with so many nested if-then-else blocks that I lost track of what I was trying to do in the first place 100 lines ago.

i didn't mean that your notation is bad. i like the splitting of cost, target and effect, which reflects the actions really taken. i just meant that you should be careful with the targets in your effects section.if the target is "attacking or blocking creature" you also have to destroy "target attacking or blocking creature". if you skip "attacking or blocking" you could also just say "destroy target"