CCG programming — a state machine nightmare!

So, at the moment we’re working on a CCG. That’s “Collectible Card Game”, if you’re not familiar. Think Magic the Gathering, Paranoia, Legend of the Five Rings, etc. It’s always a genre I’d wanted to tackle, having been a huge MTG player in college. And, I originally was thinking that it’d be a relatively easy coding job. I mean, what’s there to do? Some cards? Some effects? Make them attack and block? Piece of cake.

Well, I was sorely mistaken. 234K and 100-something ActionScript files later, I’ve realized why it took Wizards of the Coast so long to get Magic Online to work right. How do you describe cards in data? How do you describe how and when cards affect each other? How do you write AI for a card game with a huge variety of potential play options? All of these are non-trivial questions, and require careful data and rule management to get to work right.

In the course of solving these problems, I’ve already discovered a few key concepts:

More on all of this in a future post.

AS3 - a few minor quibbles

For anyone that’s tried to write complicated games in Flash, Actionscript 3.0 is a godsend. Real classes and inheritance! Object-oriented programming! Display lists! Optimized bytecode! Those of us who come from a more traditional C++ background feel right at home.

However, there’s a few lingering bits of weirdness that have bothered me for a bit, and today I feel like complaining about them!

#1 Preloading

Preloading in AS3 is a nightmare. If you have to deal with assets from a Flash file it’s even worse. If you’re able to have 2 separate SWF’s, you can simply have one load the other as binary data and everything works fine. But in my line of work, we have to cram everything into one SWF file. This causes problems because your preloader code has to start running before the entire SWF is downloaded. This can create all sorts of linkage problems when trying to refer to library assets. In the Flash 9 IDE, anything that doesn’t exist in the first frame isn’t accessible via Actionscript. And anything that does exist in the first frame gets automatically loaded, before your preloader can execute. So the solution is to do a number of confusing steps: Make sure “export in first frame” is turned off for all library assets. Then, put them on the timeline, after the first frame, but don’t play that frame! Just skip over it. Then, make sure any referencing code executes after that frame you skipped, because Flash won’t find the assets via Actionscript until it’s already “seen” them on the timeline. Ugh. This is one of the reasons I’m moving to Flex.

#2 Class paths

Let’s say you want to make a class called “MyClass”. Well, it has to reside in a file called “MyClass.as”. And, the only (externally visible) class that’s allowed to be in that file is… you guessed it, “MyClass”. While this is nice for the compiler, from my experiences it increases the number of necessary files by at least 50%. It’s rather often that I’ll have a class with only a few variables in it — typically a structure for returning information from a function. Having to explicitly make new files for this sort of thing bloats the workspaceand makes it harder to group related classes together.

#3 Enums

No enums? What were they thinking? Yes, they are just fancy renamed integers — but they give you compile-time error checking. You can approximate them by typing things like “public static const ER_OK : int = 1″, but that’s just a workaround.

#4 Arrays

You have arrays, which are nice… but they can’t be typed. This is fine as long as you’re very careful to always typecast the results properly, but it’s caused me quite a few bugs. Flash 10 is supposed to add a new fixed-type (and optionally fixed-size!) array called Vector, using a slightly ungainly syntax: “var vec:Vector.<type> = new Vector.<type>();”

All that being said, it’s a very usable language, and it’s great for writing web-enabled games…