Gamasutra.com Features - Reflections on Building Three Scripting Languages
It's free to join Gamasutra!|Have a question? Want to know who runs this site? Here you go.|Targeting the game development market with your product or service? Get info on advertising here.||For altering your contact information or changing email subscription preferences.
Registered members can log in here.Back to the home page.

Search articles, jobs, buyers guide, and more.

Gamasutra
April 12, 2007

Reflections on Building Three Scripting Languages

arrowrightPage One
arrowrightPage Two
arrowrightPage Three
arrowrightPage Four
arrowrightPage Five

Printer Friendly Version




Latest Letters to the Editor:
Perpetual Layoffs by Alexander Brandon [09.21.2007]

Casual friendliness in MMO's by Colby Poulson [09.20.2007]

Scrum deals and 'What is Scrum?' by Tom Plunket [08.29.2007]


[Submit Letter]

[View All...]
  


Reflections on Building Three Scripting Languages


Language 1: ICE

In 2000, when 3DO (now extinct) was beginning its multi-platform common library strategy, one of the elements was a scripting language. 3DO was tired of each project designing and building its own language, then training the level designers in it.

When our project (Green Rogue for PS2) started, we, of course, wrote in our design doc that we would adhere to the new 3DO policy- i.e., that we would use the common library code, including its scripting language. Then I read the scripting language documentation. Or rather, tried to read it.

It seems the new scripting language was really just a macro preprocessor for C. I struggled to make sense of it and I knew no level designer was going to read it and comprehend it. The language presumed some event handling mechanism and timer, but didn’t supply one. That meant each project would create their own macros and timers and event mechanisms. Really, each project would be completely unique in its scripting language with just a minimal common core.

Finally, all the language did was preprocess C. That meant compiling the script into the load file for the PS2. If you wanted to change a script, you had to recompile and redownload the new ELF.

In those days, the Ethernet to the PS2 DevStation was EXTREMELY slow. The turnaround for designers when they wanted to change their scripts would have been horrendous. Which meant we had conflicting needs. On one hand, sometimes scripts needed to be compiled for maximal speed. On the other hand, mostly we needed interpreted scripts hotloaded during gameplay to speed up game production.

Build, Buy, or API?

We needed a scripting language, as this was for our level designers, not programmers, so forget API. Various people suggested using existing off-the-shelf scripting languages, but there were problems associated with each. All of the existing scripting languages were prepared to be general purpose programming languages. That meant scripters could try to write code that could hang our game.

We needed to tightly control just what things scripters could do and insure no crash was possible. With complex scripts we knew there was no hope of ever completely testing all paths of the script. So it was best to insure it could "do no harm."

Existing scripting languages also each had their own independent weaknesses. Lua, for example, had a built-in garbage collector. This is not something you wanted triggering during a real-time game. Python was strictly interpreted, which would be too slow for some scripts. And none of these languages addressed our primary need for compiled AND hotloaded interpreted. With the continued evolution of these languages, nowadays I would probably have chosen one of the two, but at that time neither was appropriate.

So I wrote up a two-page paper detailing the flaws of the library scripting language and got approval to build yet another scripting language. It helped that I spent part of a month building a prototype system to prove the basic concepts of ICE worked before submitting my request. But my goal went beyond merely writing a scripting language for our project.

That huge an investment can only be recouped if other projects also used it. So I intended to completely supplant the existing library language with my own, which would achieve what 3DO really wanted.

Many people have written scripting languages for their companies, only to have the language disappear after zero or one use. To accomplish making my language truly useful and universal, I needed to do the following: a) build a better language b) document it so people could learn to use it c) support it so that any project that needed new features could get them d) promote it in lunch lectures and by other means so that people knew why they should want to switch.

Without all of those steps, it would become yet another scripting language used on yet another project. And right up there in importance was creating a great name, something that people would react well to (this is a marketing exercise). I chose ICE.

ICE combined a simplified C-like syntax with runtime support for multitasking, events, timers and interpreted code. All code was “protected” from really dumb scripter errors. This made it much more than any simple API to common library code could be and is a classic example where a scripting language is needed and a bunch of shared library routines you can call from your programming language just won’t be as valuable.

The resulting system consisted of a C translator that generated either C source or interpretable byte-code (depending upon whether you wanted speed or hotloading).

ICE supported events with arguments and used those with all asynchronous calls instead of callbacks. The system supported “listening” for an event with a pattern match on its two arguments. I greatly prefer this extremely loose coupling mechanism to callbacks. So when, for example, the game engine’s animation system finished running some animation on a character, it would broadcast a completion event naming the animation and the character. Then ANY code, including the code that initiated the animation, could react and do things.

One could write independent routines that did different things with the information, without ever changing the original code. So special effects code could be added independently later. This is much better than virtual functions of class objects, because with those you still have to have planned a call in advance, knowing what you intend to do. So if you want to do something more later, you have to go back and modify existing code.

Because ICE needed visibility over arbitrary game engine functions, a registration interface was provided whereby the engine registered the name, code address, argument description, category, and documentation for routines being made available to its copy of ICE. ICE also had a command to dump out the documentation for all routines and engine variables so registered, so scripters ALWAYS had up-to-date documentation even as new capabilities were added daily to the game engine’s interface to ICE.

ICE supported a range of relevant data types: objects, strings, events, integers, floats, enumerations, arrays, and records. Two predefined record types: XY and XYZ were built in, to directly support location and vectors. Type checking was done at compile time. Objects could be used by name in a script, and as soon as that name was given an object at run time (perhaps much later in the game), the object was “registered” and the places in the script that used that name would be filled in appropriately. So scripts could easily refer to "Sarge" or "PickupTruck1" and not be concerned about finding the object involved.

ICE could directly read simplified C header files. This allowed it to share constant names and values with the engine instead of having to copy names and values into the scripting language by hand, a source of potential error that happened frequently on earlier projects.

ICE became the defacto scripting language for 3DO and the one people were initially required to use never saw real use.




join | contact us | advertise | write | my profile
news | features | companies | jobs | resumes | education | product guide | projects | store



Copyright © 2006 CMP Media LLC

privacy policy
| terms of service