Massive Multiplayer Games and the Failure of Game AI

Anyone who has not been under a gaming rock recently knows that games featuring light or non-existent AI, but many simultaneous human players have gained a rather large following. Games like World of Warcraft replace game AI with an extraordinary number of humans (ranging, of course, from terrible to astonishing in their skill level). I am happy for those that enjoy these games and their accompanying socialization. However, as a computer scientist (even if an “amateur” in the sense of not having a PhD to my name) I consider it a failure on behalf of the discipline.

Few games have any true level of intelligence. Most are based on overwhelming the user (i.e. first person shooters where each AI nemesis is cannon fodder–but there is so much cannon fodder one can hardly keep up) or “cheating” (see any EA Sports Game; Jerry Rice becomes Mr. Butterfingers when the 4th Quarter grows too close to a finish; Ryan Leaf and his ilk become the greatest thing in the world. In short: balance simply vanishes), or “peeking” (the computer receiving more data about the user’s tactical choices than is possible in reverse). True, these techniques make the game hard, but they lack the fulfillment of beating an opponent who is truly the player’s peer rather than some half-omnipotent, half-omniscient being.

Don’t be fooled: I am not saying that good AI is easy. Much the opposite. It is, perhaps, the single hardest piece of game development. Graphics, at this point, are not the hard part. In fact, the biggest drawbacks aren’t related to programming at all, but rather waiting for the available hardware to catch up to the software’s capabilities. Perfect AI is simply not possible right now. “Good enough” AI usually is, but would require substantial effort to put together and why spend the effort? After all, we can simply boast about our ridiculous polygon counts and cool endorsements, right?

MMORPGs simply punt on the issue. Yes, there are benefits to this style that cannot be achieved. The most prominent (and, perhaps, the only) one being socialization. Unless computers could actually pass themselves off as human, this part of the enjoyment is simply not replaceable. But let’s be honest: to rival players, the world is so big that the number of people they truly socialize with is fairly small. As a rule, most humans playing are still little better than AI cannon fodder to the small band of friends playing. I rather wish they wouldn’t pass off the problem, though. There are methods that are truly promising in games. Rather than encoding a handful of basic patterns, neural networks and machine learning offer some interesting possibilities.

Who knows? Maybe some day I’ll start up an Indie game studio with a dedication to AI. I doubt it though. Alas! It is more likely that this will remain the way of it for some time.

QuickBooks Frustrations

These past couple of weeks I have been adding extensively to our internal app’s QuickBooks integration, thereby giving me a chance to seethe a little bit more about the state of the SDK. Unlike my past article this is not a tutorial. This is a technical frustration vent.

Querying the “database” is, itself, far too verbose an operation. If you look at my previous article on the subject, you will see a nice long explanation of how to connect to the company file, build a request, and execute it. Why does it have to take that much work just to get a little bit of data? Can you imagine if connecting to a real database were that hard on the rest of the .NET framework? There would be developer revolt. There is, frankly, no reason for it. Actually, yes, there is. The QBFC API is a very, very thin wrapper around qbXML. It shouldn’t be. It should be a nice, fat layer that hides all that garbage a little better. It is better than XML, which is why I use it, but why couldn’t it be a heck of a lot better instead of only a little better?

First we have QuickBooks’s speed in dealing with requests handed to it by external applications. It is slow. Oh, man, is it slow. I have used a separate test machine to run the QuickBooks testing (and now I am using a virtual box) and, even with nothing else really running, QuickBooks takes forever to do simple lists of bills received. Even if the final count is, say, ten or twenty bills it takes forever for the requests to be handled. For goodness sakes, what are they doing internally?

Then we have the sample code in the documentation. It is bad. I don’t mean, not “enterprise-y” or not awesome, I mean it is terrible. The basic workflow it uses to query QuickBooks and deal with the results is just poorly constructed. Moreover, it is wrong. Flat out wrong. For fun, take a look at the code to list out invoices, in particular the function WalkInvoiceRet. It takes in a single argument, an IInvoiceRetList named InvoiceRet, and proceeds to extract the data. That function would not even compile, making it clear that it was a quick copy ‘n paste job. How do I know? The argument passed in is a list (RetList, get it?) BUT the following code treats it like a detail. To make this code work, you would have to add a spot somewhere that iterates over the elements in that list or (for demonstration) grabs the first one or something–but that C# code, when compiled, would throw type errors.

Then we have other wonderfully intuitive behavior, like line items failing to come when you use the included data list–even when you set IncludeLineItems to true. Or the fact that the documentation says that, by default, line items are not included, when, in fact, they are.

ARRRRRRRRRRGGGGGGGGGGGHHHHHHHHHH!!!

All right. I feel better now.