The Grail of YendorMay 10, 2004 · peterb · 4 minute read
Random thoughts on the meta-design of roguelike games, preserved here so I don’t lose them.
In the late ‘80s, I nearly failed out of college playing urogue, a rogue derivative by Herb Chong that, as near as I can tell, was heavily based on AT&T’s Advanced Rogue. I was quite addicted. I liked it even compared to the then-more-advanced Hack, because it seemed simpler, more elegant somehow.
In the late ‘90s, I tried compiling urogue on the then current x86 systems, Linux and NetBSD, and the build failed utterly. I spent a little time and ported it to modern unix and ANSI C (and, before you ask, no, I won’t give you the source code). It was a fun weekend project and I got to play around a bit. A couple of years ago I noticed that parts of my port no longer worked on FreeBSD, although it still worked fine on Linux – specifically, the restore from save file functionality was broken. After a while I figured it out. When urogue (or arogue) want to save the game, they basically dump the data segment into what amounts to a core file, and then at restore time read it back in using sbrk. It is a tragedy of Learian proportions: it’s amazing that it ever works at all on any system with modern memory management. Presumably it stopped working on FreeBSD when they unified the VM and the buffer cache.
I spent a day or so sketching out various designs to actually save the state in an orderly fashion and read it back in at restore time without resorting to Stupid Unix Tricks. I prototyped one method that got me about 70% of the way there, but it was pretty ponderous coding. And I sat back in my seat and said “God, this all sucks so much that it would probably be easier to just reimplement the whole thing from scratch.”
I didn’t immediately sit down and start writing it because: plenty of people have written rogue clones, and a urogue clone wouldn’t really add much to the culture of roguelikes except giving a nostalgia kick to the 16 or 17 people left alive who remember actually playing the original. And besides, there was so much cookie-cutter work. All of the really interesting parts of urogue were the corner cases. Those are what I wanted to spend time working on. What I really wanted was a set of classes that took care of all the stupid, boring stuff that is practically the same in every roguelike, leaving me to concentrate on the interesting stuff, which is the content.
But nothing like that exists.
I guess, if I really want it, I’m gonna have to make it.
Probably 90% of the content of roguelikes is in the monsters, items, item descriptions, and their effects on the player character. In an ideal world, the designers of a roguelike would spend their time on that content rather than on implementation details.
If this is true, then we can abstract out the following things to be done via a java class library. (Why Java? Why not. Seriously, mostly because I want to at least pretend that this could be usable on any platform, and because if there were ever an application where performance is not an issue, roguelike games are it.)
- Dungeon/maze generation
- Character generation
- Item generation, placement, and usage
- General combat mechanics (collision detection)
- Output routines (should support both text output and tile-based graphics – more generally, should allow output to some other piece that will actually manage the display – there are people who play rogue on Palm Pilots or cell phones.)
- Inventory management
- Should support both clock-moves-per-turn and semi-real time (e.g. Diablo-like) behavior.
Provide standard classes which do boring things for all of the above, but could be overridden by the ambitious developer who wants to do something special.
Most interesting behavior is going to be defined by callouts to user-provided interfaces. There has to be support for scripted behavior and events (think: cut scenes, movies, Nethack’s “special” levels, etc. in a way that isn’t mind- numblingly painful). Put another way: the library has to be complete enough that you get real value from using it as a base to build off of, but liberating enough that you don’t need to rewrite huge sections of it the moment you want to do something unique. This may not be possible. I don’t know yet.
Minimal victory: reimplement urogue with this class library.
Marginal victory is if one can implement a close approximation of both Nethack and Angband in it.
Complete victory is if one can also implement something like Diablo in it.
You may all commence the calling me crazy. Here are some spoilers for urogue that might explain why I love it so (note: although the extension for the spoiler file is “.doc”, it is a normal text file.)