Porting Zork — Part 1: Introduction
The classic text adventure game Zork has had a special place in my heart for a long time: I've been hard pressed to think of a game I might have even played before delving into the white house and succumbing to the appetite of a grue. Regardless of whether it is the first game I played, I credit it—at least in part—for sparking my interests in gaming, artificial intelligence, language, and programming.
As an ode to it and the influence it's had on me, I've always wanted to do something involving Zork. I've tossed around various ideas—creating my own adventure game, writing a Z-machine parser—and ultimately decided on porting it from its original incarnation into other languages as a way to both understand the original creators' design. It'd also be nice to have a more interesting "hello world"-type project for playing around with languages I'm not familiar with than the bog-standard "write a blog platform".
I've created a repository on Github to track this project and this series of blog posts will act as my implementation notes throughout the porting process.
Zork was written between 1977 and 1979 by four members of MIT's Laboratory for Computer Science Dynamic Modeling System (MIT-DMS): Tim Anderson, Marc Blank, Bruce Daniels, and Dave Lebling. Eventually, they (and a number of other implementers) would go on to form Infocom, a company that specialized in text adventure games in the style of Zork.
While Zork has been ported countless times, it was originally written in the MIT Design Language (MDL, pronounced "muddle"). Designed in 1971, MDL is a functional language reminiscent of Common Lisp and Scheme. However, unlike those languages, MDL has been obsolete since the early '80s and lacks a lot of the syntax sugar and language constructs we take for granted today.
The MDL source code has been floating around the Internet for the past few decades, and I've included it in my repository for reference purposes.
In porting, my intention is to create as faithful an adaptation as possible without going too overboard. I'll discuss some specific examples later on, but in general:
- Data structures will be maintained as close to the original source as possible.
- Program flow will be maintained as close to the original source as possible.
- If the MDL source code contains subroutines that are simply userland definitions of language constructs that already exist in the target language, I will use the target language's construct instead of porting MDL emulation of it.
- MDL language constructs that do not exist in the target language—but should not affect program flow—will not be ported.
The end result should match the original Zork feature-for-feature, if not necessarily bug-for-bug.
Of course, I have to start somewhere, and I've decided to port Zork first to PHP, a language I'm deeply familiar with. In order to understand the MDL code, I'll be using the reference manual The MDL Programming Language by S. W. Galley and Greg Pfister.
The original source code is split into 19 files, each containing a mixture of subroutines, forms, and expressions. Right now, porting each file one-by-one seems like a great way to split everything up. If I find a cross-reference to another file, I'll port the minimum amount of relevant code to resolve the cross-reference.
The first file I've ported is the shortest of them all:
prim.mud. It contains a few subroutines for manipulating Zork's basic data structures.
Continue on to part 2: "Data structures".
Comments and feedback are welcome and appreciated. Need help on your next project? Let's talk.