I wrote a Fortran IV-to-C translator in order to re-experience Adventure as though it were still the late 1970s.
This is a personal project, but I’ve moved it to a public Github repository on the slight chance anyone here is interested.
There are many ports of Adventure that are playable today. (In fact, there are far more than I realized five weeks ago when I embarked on this project.) As heroic as some of those efforts are, every one I tried altered the experience in at least one way.
Mixed-case text, visible prompts, a status bar, etc. These are simply cosmetic changes, but they always put me on alert because they indicate that there are likely other changes.
Corrected spelling and grammar. I want to re-experience the game with all the warts.
Extensions. I want to play the WOOD0350v2 version, but some ports are based on versions that had extended maps and extra puzzles.
Bugs. In particular, bugs that affect navigation are a particular pet peeve of mine. Adventure itself has some mistakes in the travel table, but some ports have introduced subtle bugs.
Elimination of cave hours and wizard mode. True, this doesn’t fit a modern computing environment, and it’s not part of the game, but I wanted to re-experience it.
I started out with the intent of making a Fortran IV interpreter but pivoted to making a translator because … reasons.
And, to be clear, I didn’t set out to make a tool that completely understands all of Fortran IV (as implemented for the PDP-10). Adventure uses only a fraction of the language, so the plan was to implement just that fraction, which made the project much more tractable.
I didn’t really know any version of Fortran before I started, so I’ve learned a lot along the way.
So anyway, I’ve got a modern C++ program that reads the Fortran source code and spits out a C translation. The translation is not pretty, but it should be perfectly portable C11.
Right now it handles WOOD0350v2 (and v1 as of yesterday).
I’m looking to see whether I can extend the translator to handle CROW0000 as well. The challenge there is the use of a system-provided floating point random number generator. A simplification I’d baked into the translator was that it wouldn’t have to handle REAL (or DOUBLE or COMPLEX). The Woods versions used an integer-based linear congruential random number generator.
I wrote an ultra-conservative Rust port of a very early version.
It’s listed as CRAW0000 on the Adventure family tree:
Source is here:
I kept the code organized as much like the Fortran code as possible to avoid accidentally introducing differences in behavior. There are only two differences I know of:
I print an obviously new message instead of crashing when moving south from the swiss cheese room.
There was a subtle invalid index bug dealing with dwarves. It had no visible symptoms in Fortran, but Rust would panic. I adjusted the math on one line slightly to avoid it.
While this is an extremely early version, I have thought about tackling a more “recent” one someday.
fatal error: format: No such file or directory
9 | #include <format>
You need the command line option to tell the compiler that the translator uses C++20. For gcc and clang, I think that’s -std=c++20. The MSVC project uses /std:c++latest.
That’s just for the translator, by the way. The code generated by the translator is C11.
The WOOD0350 versions have an out of bounds index right at the beginning of initialization. It accesses one element before the beginning of an array (offhand, I don’t remember which). I’d be surprised if that’s not also in CROW0000.
If it were, it would’ve crashed on Rust (which prevents indexing out of bounds) unless I made a mistake in translation that also happened to correct it. That seems pretty unlikely.
Thanks. Looks like my gcc is too old. I upgraded to 13.2 but not good enough. <format> is now present, but <print> isn’t. I think that’s a gcc 14 thing.
Very nice! I’m going to follow along. Fortran was my first programming language in in 1970 or so, punch cards and all. At this point, I can hardly spell Fortran…
I upgraded to 13.2 but not good enough. <format> is now present, but <print> isn’t. I think that’s a gcc 14 thing.
Ugh. I forgot <format> and <print> didn’t come in the same standards update. So, yeah, the translator requires -std:c++23. Would it work with gcc 13.2? I don’t know.