How to program a text adventure in C
Many years ago (circa 1993) I ported the original Colossal Cave adventure by Crowther and Woods to TADS, a language created by Mike Roberts specifically for authoring text adventures. (Colossal Cave just came up recently here.)
https://ifdb.org/viewgame?id=c896g2rtsope497w
Graham Nelson ported my port to his Inform language, and Inform is probably your best choice if what you actually want to do is write a (plain text) adventure game.
If you want to learn C programming, writing a text adventure in C would be a fun learning project! But aside from pedagogy there’s no real reason to write a text adventure in anything other than Inform, TADS, etc. Not only is it much easier to use one of these purpose-built languages, with Inform you get multi-platform compatibility going back to the 8-bit era for free!
Personally if I had any free time, I’d be more interested in looking at how to use a frontier LLM like llama as an integral part of a text adventure. There was something like this using GPT-2 circulating on here a while back, but it was pretty rough.
However, it’s clear that if you figured out how to precisely control the LLM so it didn’t produce crazy stuff, you could realize the dream of truly realistic NPCs in these games. Text adventures would seem to be a perfect laboratory for experimenting with this.
I was wondering: does anybody know if there are any good resources for writing a good text adventure? Any nice tips and tricks? Mainly related to the content. I guess it overlaps with "writing a good novel", but I bet there're some specific advices that can be applied to the text adventure.
I wanted to write my text adventure, but I'd offer reader to have multiple options, especially for those who are not really practical with english (includes myself ^-^).
I think for a lot of people here, the hard part of writing an adventure is not writing the code but coming up with a compelling game with an interesting story and readable text. My advice is that if you want to actually end up with an adventure game that people can actually play, just pick an existing authoring system that looks like it will do sort-of what you want and start writing.
I speak from experience when I say if you start by writing the engine then you will quickly become side-tracked with technical issues and never get your game done.
I can recommend ink if you want a choice-based game. It is super easy to get started and the language lends itself to extension if you find it doesn't do what you need out of the box.
Some minor notes:
* Text adventures are a case where it is really advantageous to separate the declaration and definition of objects, since cycles are ubiquitous. For C, consider X-macros, tentative definitions (not in C++, sadly), and using the section attribute to make the list implicit (or if you don't want to rely on compiler voodoo, just output the index during another pass).
* It may be useful to distinguish several ways an object belongs to a location: on top of, contained in, held by, equipped by, integral component of, death drop of. Additionally, "has never been moved [by player? by code]" is often desirable to record.
* Backwards ownership is fine for savefiles and initialization, but during runtime it can be useful to cache lists in the other direction. A dict may be worth it in a few places if your adventure gets big enough, but linear search is fine for a long time (and makes e.g. conditional passages easier; you should simply check that every conditional transition is eventually followed by an unconditional one with the same tag. To ensure conditions are handled uniformly, transitions with multiple names should canonicalize first).
* For C statically-allocated arrays within a struct initializer, we've been allowed to write `(T[]){t1, t2, t3}` for a quarter century now. There's no need to name the separate objects.
* It is very useful for the runtime to support the notion of "overlays" - used for things like menus which can use surprisingly similar logic to rooms. Saves should only ever look at the main game layer.
* Relative directions are very interesting, but tricky to add to a game.
What I wish I had was an example of a game that is complete enough to be interesting but not too big, to be used when porting to a new engine.
I did once write a text-based adventure game in C, however I only did that to work out some of hte "plot" and the layout/objects I was going to work with.
My actual aim was to write a simple text-adventure in Z80 assembly, which could run upon a CP/M system. I did achieve that, and later ported the game to the ZX Spectrum.
A few years after that I used one of the inform-compilers to recode a couple of the puzzles in the Z-machine, which would also have allowed me to run the game on a CP/M system, but to be honest by that point I'd lost interest and I never ported the whole of the game's text, and the two different endings etc.
That said my toy adventure was popular when submitted here, back in the day:
I wrote a few MUDs in late 90s and early 00s.
LLMs would definitely make a more dynamic and lively world for NPCs. I can even see a place for dynamic quest building. But it isn’t going to produce a full world without a significant amount of prompting.
I do see how it can help write a lot of boilerplate (item descriptions, back stories, etc). A big thing I always wanted is memory and we worked a long time on it for tracking logic (footprints, hunting). Conversational memory is probably single biggest thing that excites me.
I have long wanted to make a procedurally generated text adventure that focuses on economics, information, and politics rather than spatial exploration. This gets complicated quickly, of course. Basic microeconomics and armchair psychology gets one a bit of the way there, but not enough to generate compelling dialogue and intrigue -- at least I have not been successful.
Does anyone know of good prior art in this space?
Oh man, I got PTSD (post traumatic strtok disorder) on page two and rage quitted the page.
I've lost too many hours to bad stdlib APIs.
Section 9 - Code Generation uses awk to parse a text file to generate c files. Very nice.
I honestly think that writing an adventure can be best done by first creating an adventure-writing DSL (in C, if you like).
A few observations on the C code (I didn't read all of it):
- please, no strtok
- a little more concentration on the UI, for example not using strcmp to test inputs
- make all preprocessor definitions be uppercase
- those conditional operators confused the hell out of me - just use if/else
The best way to implement a text adventure in C would be to implement a simple lisp interpreter in C and then implementing the actual game in a lisp DSL. Lisp lends itself surprisingly well to this, and defining game logic declaratively instead of imperatively is much more intuitive. Here are a few examples:
[1] http://www.ulisp.com/show?383X
Didn't read the article, but my first reaction to "How to program a text adventure in C" is to write a language / tool in C, and then use it to program the actual game much faster and safer. A Lisp-like a or a Lua-like language would both be relatively easy to implement.
Infocom was famous for using this approach, for instance.
I thought it was going to be something like this: https://github.com/dfremont/glulx-llvm
I thought it was something like LPMud or MudOS [0].
undefined
This is all one really needs to program a huge hit game in 2025.
DOOM is essentially a text adventure but with fewer keywords.
undefined