Dear God, Why Lisp?
I realized that I sort of stumbled off into Lisp land without explaining why. For those who have worked with a modern Lisp environment, some of the advantages are probably obvious. For the other 98% of the programming world I probably look like a nut. Here I’d like to make a case for why Lisp is a good choice, inside certain parameters, for game development.
Syntax
The first advantage I see in Lisp is also the most cited problem with it. Lisp’s syntax is a powerful tool for extending the Lisp language. Speaking in terms of compilers Lisp doesn’t so much have syntax as a directly written abstract syntax tree. The upshot of this is that, since Lisp’s syntax is so regular, Lisp itself can be used to write macros for your program. This makes building a domain specific language for writing your game much easier.
If you’re going to go through the effort of using a scripting language for your game you might as well make sure it’s actually useful for the task. There’s two ways to do this, either luck into finding one that already has the tools you need or take an existing one and build up to that point. My assumption here is that there aren’t going to be too many scripting languages built explicitly to support writing a space shooter or RTS, so we’re stuck building on top of something that does exist. Lisp’s abstraction capabilities let you turn your scripting language into something specifically tailored for writing your game more quickly and less painfully than anything else.
Dynamic Language
Obviously if I’m going to be doing some scripting the goal is to save time over writing in straight C. There’s a few advantages people typically look for here:
- No Compilation
- More powerful abstractions
The first advantage is the biggest. One big advantage of scripting is that it allows you to modify the game’s behavior without having to recompile. Lisp lets me take that one step further, which is something I’ll get back to in just a bit.
The other big advantage people look for in scripting is in the realm of abstractions. The idea is that you push game objects around with logic written in your scripting language and let the “system” language deal with rendering, representing vectors, loading resources, etc. Since my specific Lisp dialect (Clojure) interacts well with my system languge (Java), I’m all set in this regard.
Interactivity
One feature of Lisp dialects that few other languages have caught up to is the read-eval-print loop (from now on: repl). This is a powerful idea where a minimal Lisp program is loaded that does nothing but take in and execute new definitions and statements. The programmer can type their definitions in on the command line (or more comfortably direct their editor to do so from within a file) and have the repl execute them.
This is the heart of my theory about Lisp’s productivity boosts. I have set my game up so that it can be loaded in a debugging mode. Within this mode the game watches for new Lisp definitions or statements to be sent in and executes them. If I don’t like how some part of my game logic works I can change it and see that change reflected in the game as it is running. I don’t have to shut down, I don’t have to reload a script, and I usually don’t even have to reload the game environment. This is development at breakneck speeds, especially in the later stages of a game where fixing bugs might involve quite a while to wait on resource loading and playing through a game until the point where the bug is encountered.
Right now I’m working on building a replay system into the game. The idea is to record all meaningful user input so that can be played back through the game and I can fix buggy behavior by jumping back to before that behavior happened, modifying the relevant code, and testing it to make sure it now works correctly. On paper this is even more powerful, but we’ll see how it happens in practice.
3 Comments so far
Leave a reply
Where are you drawing the line between scripting and Java? Some of your examples seem to point to the rendering loop being called from the scripting engine side rather than the other way around.
[…] up. Clearly this allows for swift bug fixes in the game and AI logic portion of the game. This blog entry about using a Lisp variant for game development highlights why this is a good thing. Now I want to […]
Right now I have as much of it running in Lisp as I can, including the render loop. If it becomes an issue I can always rewrite that part of it, but for now it is nice to have access to the render loop at runtime if I discover I want to see something for diagnostics. I don’t plan on having any really fancy graphics, so taking a hit on execution speed is worth it in this case since I have a bit to spare right now.