Mar 17, 2010

The Dragon Age of mainstream game scripting

It's amazing how much depth great role-playing games can have to them. Some of the quests, which start as usual pre-canned in-game experience, can suddenly spill themselves onto higher layers of reality, sometimes in quite unanticipated ways.

I had been enjoying Dragon Age: Origins for quite a while already, before I found myself engaged into one of such meta-quests, which I'd like to tell about.

So, I went to Orzammar, the underground dwarven capital, where the "A Paragon of Her Kind" storyline subplot started to unwrap. There was quite intricate political struggle for the crown between two houses going on there, and apparently I was expected to eventually side with one of the parties.

In quite a boilerplate way, the two emissaries were giving tasks to be fullfilled in order to prove the loyalty to either of houses. Apparently, it was also anticipated by the developers that player might want to try playing both sides in a double-agent kind of way, and that's what I've tried doing...
just to find out that the whole plot got stuck into a logical deadlock, which turned out to be a bug. Of course, I did not have the recent save games to reload from (of course!), so I became disappointed and unmotivated.

Luckily, Bioware released the Dragon Age Toolkit, which any owner of the game can download and use to modify the game to his taste. It's a great move from their side to have it released, which me and I believe a lot of other people really appreciate. So, I downloaded it, installed and digged straight into the scripts trying to find the place which could be patched to allow me keep playing.

Long story short, I succeeded at hacking the game plot script and could enjoy the game again. It would be a perfect time for the happy end, perhaps, but the whole "fix the quest scripts to allow continuing playing the game" meta-quest spawned even new set of quests in different layers of reality.

The first quest was about learning how the DA Toolset works, getting insight into the tools and workflow which developers used to produce this great game, examining its strengths and weaknesses. Very useful experience.

But there was another thing, which somewhat stroke me. In the process of digging the scripts I've got the impression that the script code structure is quite a bit more complicated than it could be. The logical deadlock bug in the scripts, mentioned above, turned out to be not as surprising as one would expect, given that author had to anticipate the combinatorial explosion of all the many possible developments in the plot, and the language used for that did not seem helping much in that... and I wonder how much QA efforts and bugfixes  it needed before getting into the shippable state.

This another meta-quest was about understanding the current state of higher-level game programming DSLs (aka "game scripting languages"), which in turn made me also sidetracked into such side-quests as trying to learn about the Prolog programming language, semantic networks and what else... but I digress.

In case of Dragon Age, the scripting language has a simple C-like structure, and workflow in scripts is centered around events coming from the engine and other scripts.

When it comes to the story development, scripts collaborate closely with the conversation editor, which is used to build the dialog trees (which are not actually trees, but rather DAGs, still represented in a tree view in the editor). Each branch in the dialog tree can be masked out by some global flag, as well as it can change some global flag if player picks this dialog branch in the conversation.

This leads to the following patterns:
  • there is a rather extensive set of global flags, related to the given storyline. Sometimes these flags can be quite complicated (e.g. "A_HAPPENED_BUT_B_HAVENT_HAPPENED_YET_AND_PLAYER_DID_C")
  • when flag changes (triggered by the player picking certain dialog branch or for some other reason), it fires the event. Events are handled in the scripts, in rather big switch/case blocks.
  • every case block can have complex and nested conditions checks, which may change other flags as the result, for example enabling/disabling some other dialog tree branches.
All in all, amount of bookkeeping-style code compared to the actual logic code seems to be incredibly high, and logic code itself is spread over different places, the code being heavy on side-effects.  And it's not due to the bad coding, obviously, but rather because of the traits of the scripting language and framework itself.

It seems that one of the main criterias in picking the scripting language for game development still remains familiarity, which most of the time just means syntax familiarity.
Familiarity is considered to be important, so that designers and generally people not having "extensive programming background" can use it without much problems.

And I guess it makes sense. For example, in case of Dragon Age, majority of the scripts appear to be written by intern and fresh from the college folks (one can track the author names from the scripts themselves). Now, by no means I am trying to imply that it somehow correlates with the code quality - years of experience quite often mean nothing, and no doubt those people coming from college are brilliant. But I believe it still kind of shows the general attitude in the industry. Which is: "Game logic scripting is a beginner level, routine task".

Still, the question arises: is this really the most productive level of abstraction to work with? Could be  low-level imperative manipulation with global flags and multiply nested blocks of if-then-else logic, giant case switches with side effects replaced with something which maps better into the domain area? Something, which would allow to do more complex, rich, interesting, emergent things without need focusing attention on the spaghetti logic and fighting the peculiarities of the scripting language?..

Despite all the interest, research and developments in this area, it seems that on the industrial, mainstream level, the technologies which serve as the game designer's medium for creating the high-level game playing experience, remain grossly underdeveloped. But it would be unfair to call it "the stone age", of course. It is developing, albeit slowly. And, no matter what tools are used to achieve it, in the end of the day it's the end result which matters.

Thus I dub the present as "The dragon age of mainstream game scripting".