Something that’s always intrigued me about old-school adventure games are the scripting languages the developers came up with for controlling the game flow.
The idea was to have a simple language that’s both easy to read and write and which allows the developers to script game events without resorting to complex programming environments such as C/C++ or, God forbid, Assembly language.
Perhaps the most well-known scripting language for adventure games is SCUMM, the “Script Creation Utility for Maniac Mansion“. This language was originally developed by Ron Gilbert at LucasArts for use in Maniac Mansion and went on to be used in classics such as Indiana Jones and the Fate of Atlantis, the first three games of the Monkey Island series and countless other titles. (Starting with Grim Fandango, LucasArts replaced SCUMM with a LUA-based solution.)
In modern programming terms, SCUMM et al. can be described as a DSL (Domain-specific language), i.e. a computer language specialized to a particular application domain.
In this particular case the domain is “adventure games”. For my ongoing project Libera Me I’m working on a DSL of my own devising, tentatively named Legato (“Libera Me Game Tool”). Before we take a closer look at Legato, let’s check out what came before us.
Sadly, there is not all that much information available out there about SCUMM or related languages such as SCI (Sierra Creative Interpreter). Of course one could study ScummVM’s source code to learn about both, but I’d much rather write some code of my own!
After some searching I came across the Classic Game Postmortem – MANIAC MANSION which does happen to contain a few interesting code snippets of elusive SCUMM goodness.
Take this for example:
First impression: As far as programming languages are concerned, this is definitely on the very readable end of the spectrum. From this little snippet we can tell that SCUMM follows natural language patterns and is easy to understand even without prior knowledge of its scripting commands.
With this in mind I started out to create a custom scripting language for Libera Me. Now, after a few months of on-and-off work on the language and the interpreter, it’s finally in a functional state.
Legato is my home-made DSL written in Boo. Never heard of Boo? You really ought to! Boo is a Python-inspired language for .net and mono. Its special focus is metaprogramming through language and compiler extensibility, which makes it ideal for writing DSLs.
Moreover, Boo is one of the three languages supported in Unity out of the box. As Libera Me is built on the Unity engine, writing my DSL in Boo was the obvious choice.
Oddly enough Boo appears to be the least used of the three languages supported in Unity, which is surprising considering it is quite possibly the most powerful. In my opinion, anyway.
Legato is a domain-specific language designed to be used in Libera Me, although it is general enough to support other adventure games just as well. It’s also very easy to extend Legato with new features and commands so I’m kinda making it up as I go along.
Here’s some sample code:
As with the SCUMM code sample above, Legato’s syntax is very easy to digest without knowing anything about the language itself. Wherever possible, Legato follows the common subject–verb–object structure found in many natural languages, including English. Admittedly, the syntax is somewhat verbose, but that only adds to the readability here.
On top of that it’s really just a fully functional Boo script. Thanks to this, all common programming idioms such as variables, conditional expressions and loops are supported straight out of the box.
A Legato script is compiled at runtime when the stage loads. If the script is edited while the game is running, the interpreter can automatically detect the changes and will recompile the script in the background. This makes for a great workflow as any changes take effect immediately without having to restart the game or waiting for a lengthy recompile of the entire build.
Currently, the Legato interpreter understands only basic commands: “walks to”, “looks at”, “says”, “picks up” and so on. To make things easier, most commands have a default handler which can optionally be overridden per object and/or per scene.
My next step will be to add support for events. A scripted object can subscribe to certain events and then perform custom actions when the event takes place.
An example of an event would be the player character (the ego) attempting to leave the screen, “OnEgoLeavesScreen()”. When this occurs, any and all objects that subscribe to this event are notified and can take appropriate action, e.g. bid the player farewell or prevent him from leaving.
Please COntact me.