VΘXΔM: a Z-Machine, Glulx, and Å-machine interpreter in Python

I’m introducing my interpreter VΘXΔM.

That said, I want to be upfront about what this is: a project I built mainly for myself, to see if I could. It competes with nothing and displaces nothing: Frotz, Glulxe, Lectrote, Parchment, Gargoyle, and the rest are the interpreters of record, and I use them too. This was about learning the specifications by enforcing them, one cited section at a time, and seeing how far a from-scratch implementation could honestly get.

The answer turned out to be: farther than I expected.

The machines

  • The full Z-Machine: all eight story file versions, including version 6 with its pictures, palettes, and windows, so that Arthur, Shogun, and Zork Zero play illustrated. Held to CZECH’s exact tallies in CI.
  • Full Glulx and Glk: glulxercise passes all seventy sections.
  • The Å-machine, the VM Dialog compiles to: certified the strongest way I could think of: every test battery the reference implementation ships replays byte-identical to the reference engine’s own transcripts, at the same seed.

The faces

  • A painted terminal, a pygame window, a browser tab (voxam --web story.gblorb – GlkOte served locally, art and sound included), a Tauri desktop app, and a raw stdio GlkOte wire (--glkote) for anything that wants to drive it.
  • Version 6 plays in the browser, too; the whole screen as one scaled canvas in the art’s own 320x200, palettes baked into the pictures. I’ll call it partially: the core gameplay is there, but some (very rough) edges are still being sanded.
  • Stefan Vogt’s arc_image picture band rides along: a conformant z5/z8 with a sidecar Blorb plays with its picture following the story, in the browser and the desktop app alike. I wanted to give Arcturus some love because I’m massively impressed with the project.

The command line, which is where most of the fun lives

  • Every session is reproducible: --seed plus the same commands gives the same session, forever. That’s the foundation on which everything else stands.
  • --record writes a play session as an acceptance script: a small grammar that can spell every input a display can produce, mouse clicks as <click x y> and menu keystrokes included; then --accept replays it. Forty-four recorded playthroughs replay end-to-end in CI, and their annotations double as a record of where the games’ published walkthroughs go wrong. There are already many acceptance scripts.
  • VΘXΔM also speaks RegTest, Andrew Plotkin’s regression-test format, twice over: --regtest my-suite.regtest runs a script through a built-in in-process runner on any platform, and the same file runs under Plotkin’s own reference implementation, driving voxam --plain over pipes; CI holds both to the same verdict. A seed on the script’s interpreter line makes the whole suite deterministic under either runner, which isn’t something most interpreters can offer RegTest at all.
  • --shots photographs a recorded walk frame by frame at a real display – the pygame window, or your own browser running headless – and --strip-diff compares two filmstrips pixel by pixel with VΘXΔM’s own PNG decoder. A seeded walk reproduces to the pixel.
  • --babel reports any story’s IFID by the Treaty of Babel’s rules; Infocom games are named from a table of their 246 known releases, and everything that can be named plays under its own title.
  • --decompose reads a Blorb apart chunk by chunk – picture sizes, sound durations, the iFiction record in its own words – and --extract frees the art, sound, and story as ordinary files that open anywhere.
  • --listing disassembles a whole story txd-style, and --trace writes every instruction a session executes as it runs.
  • And the small period details: --tandy raises the legendary Tandy bit, and the interpreter platform of §11.1.3 is claimable per run, so the games that check whether they’re on an Amiga can be told they are.

It’s on PyPI (pipx install voxam), with the Tauri version on the GitHub Releases area. The repo’s STATUS file is a ledger of exactly what’s enforced and what isn’t, kept honest by a test suite with 100% statement and branch coverage. While this is at version 2.3.0, that was me marking development milestones while I had a whole bunch of time on my hands. I fully expect there to be bugs still to be ferreted out and, in fact, I’m going to take a break and just play lots of games through the interpreter and see where it breaks!

Maybe next

  • Injectable “cheats,” similar to what Bocfel documents.
  • Text-to-speech, so sessions can be heard as well as read.
  • Automapping, drawn from the session itself as it plays.
  • Comparing a running Infocom game against Infocom’s own source; in the neighborhood of the Visible Zorker, though not the same idea: less “watch the source run” and more “hold the session against the ZIL and see where they illuminate each other.”
  • Continue building out the Story Probe, which attempts to learn how to play textual interactive fiction, but without AI or an LLM involved, including brute forcing its way to solutions.

As this is remarkably relevant to the discussion being had in the “mainstream IF” thread, I’d like to suggest that if the interpreter were to have a game-sensitive notes-taking tab it would be a boon - possibly less so on a desktop interpreter, so maybe not in your particular case, but a new interpreter is always an opportunity to have these things right at the entry level.

Automapping, drawn from the session itself as it plays.

My experience with Trizbort (I think it was Trizbort, that allowed for automapping from a transcript; you started a transcript, pointed Trizbort to the text file, and kept on playing. Your moves would update the transcript in real-time, Trizbort would read from it, and build an auto-map) showed me that such an automatic mapping convenience can work really well for many games, but not all. I would encourage you to also look into manual mapping, which I recently argued (as you know) would make a lot of sense being native to interpreters, and if you can get automapping to work that’s icing on the cake. :slight_smile: But regular old mapping, at the interpreter level, would be awesome.

Does the Å-machine implementation support text styling? Currently there is no command-line Å-machine interpreter that does, which is a notable deficit—I was going to make a thread about creating one once the 32-bit standard was out.

Not yet, but I’m digging into that as we speak. The LOOK chunk is already fully parsed: every style class arrives as its CSS-shaped key-value pairs (font-weight: bold, font-style: italic, colors, margins). The machine already routes enter_span/leave_span, enter_div/leave_div, set_body, and the deprecated SET_STYLE bits through the output API with their class indexes attached. Anything that wants to dress text receives everything it needs on calls that are already fired.

The spec’s own bar is generous here in that styling counts if bold and italic are merely distinguishable (“bright and underlined … qualify”). In my case, a blessed-terminal voice mapping font-weight/font-style/color to terminal attributes would clear it, and then VM_INFO 0x44 flips to 1, and Dialog games start emitting styled output on their own.

I can at least see how to get started on this.

Ah, yes, I did see that in the other thread, and I agree. That would be a great addition. I can start designing that out.

Yeah, I started digging into automapping and ran into various issues. All tractable, but all leading to a complicated design. So, yeah, I hear you on this. I think I’ll reorient my thinking on this and approach it the way you’re suggesting.

Yeah, I set the bar low because the Dialog debugger renders italics as underlined, and the Commodore 64 interpreter renders bold and italics as color changes (bold is a lighter color, italic is blue). But low as the bar is, none of the command-line Å-machine interpreters clear it!

Challenge accepted! I’m working on this right now.

Next up after that will be the note taker.

Regarding the styling, I’ve got this much working so far, at the very least.

The screen recording of Cairn shows what seems to be automatic mapping that you can rearrange manually.

That’s a pretty slick interface, at least from what I can see watching the video. It might be a little tricky in some specifics, but I think I can see how to implement something similar. I would have to rethink what I’m calling the “glass” interface a bit.

Excellent; if it were available on Android I’d download it yesterday, keeping Fabularium for the other formats.

EDIT - Actually, the more I look at Cairn, the more I like it. But I have no iOS devices anymore, and no desire to get them. I actually bought my first iPod specifically for the purposes of playing IF with iFrotz on them. That’s the kind of thing you might do once.

Cairn is written in Swift, so it’s pretty easy to pull apart. I bought it just to get the app and see what I can see. It’s clearly very modular at the code level. In fact, it’s so clean I suspected it was OpenSpec driven. And, sure enough, there’s a metric crap-ton of AI generated code in there. But, yeah, to implement this in my case would be a big change to the glass portion of the interpreter. Or, rather, this would actually become a variant frontend. (That’s what my Pygame, Blessed, Web, and Tauri basically are: just variants using the same wiring.)

A thought on maps, prompted by the suggestions above

The mapping suggestions in this thread sent me down a rabbit hole, and I came out wondering whether the automap, as we usually imagine it, is a legacy form that we just reflexively return to.

The classic automap commits to geometry, right? Rooms on a grid, compass lines between them, a pane of screen fighting the story for space. And geometry is exactly where these tools break or at least can have issues. Games scramble directions (the Zork forest), exits go up and in and “through the window”, connections aren’t reciprocal. Every automapper can end up fighting the games instead of serving the player.

So, here’s the question I keep circling: what do I actually want from a map mid-game? Honestly, for me, it’s two things. Where have I been, and what haven’t I tried. Neither is a picture. The first is a list of rooms. The second is a list of loose threads: exits I saw mentioned and never took, directions I never tested. A picture is one way to encode that, but it’s the expensive way, and it inherits every geometric quirk. A catalog encodes it directly, costs a sidebar instead of a pane, and can’t be broken by a game whose geography refuses to lie flat.

The interpreter’s view supports this better than the transcript’s, too: it can know rooms as the distinct things they are inside the machine, even when they all print “Twisty little passages, all alike”, and it can know which command moved you. That’s a graph whose edges are commands rather than compass points. No layout problem, because nothing gets laid out. The drawn map doesn’t die under this framing; it becomes an export for tools like Trizbort, for the people who genuinely want geometry.

One last thought on what this might actually look like, because it connects to the notes suggestion earlier in the thread. If a map is really “rooms visited” and “threads untried”, then a map is just a kind of note, one that the interpreter takes for you while you play. Which suggests the whole thing is one notebook with a few kinds of entries: pages the player writes freely, pages the interpreter keeps automatically (the room catalog, the loose ends), and pages that mix the two, like a room entry you can annotate (“the grating is under the leaves here”). All of it is keyed to the game and saved beside the story as an ordinary file you could open in any editor. No map pane, no notes pane (although I can see a way to have that available), no geometry engine. Just a notebook that happens to be partly self-writing.

Just noodling here …

Lovely discussion. I’m gonna dive into the little bits.

The classic automap commits to geometry, right? Rooms on a grid, compass lines between them, a pane of screen fighting the story for space.

Indeed. This reflects how we used to map things, and how, say, Infocom encouraged us to map things on their manuals and their transcript examples. It still works well for the vast majority of games, because the cardinal directions still map out to that grid, for the vast majority.

Games scramble directions (the Zork forest), exits go up and in and “through the window”, connections aren’t reciprocal. Every automapper can end up fighting the games instead of serving the player.

Indeed, that’s the point at which mapping was part of the puzzle. Those were done on purpose. It’s no surprise that automappers choke on those; they were designed to make the player stop and pause and “solve” the situation. It’s probably less of a thing in modern games, but a modern game can still try new and weird things that might mess with an automapper’s way of detecting where the player is or what the map looks like.

So, here’s the question I keep circling: what do I actually want from a map mid-game? Honestly, for me, it’s two things. Where have I been, and what haven’t I tried. Neither is a picture.

For me, I would add “where I currently am, and how to get to where I next want to go”. The spatial logistics. This, to me, would indeed be a picture. A map, if you will.

A picture is one way to encode that, but it’s the expensive way, and it inherits every geometric quirk. A catalog encodes it directly, costs a sidebar instead of a pane, and can’t be broken by a game whose geography refuses to lie flat.

I personally have no idea how anyone could navigate using a list of rooms and where their exits lead. Obviously people do, but I’m saying this to illustrate how, to me, that is impossible and leads to me getting lost and whipping out an external toold and mapping visually anyway. If a mapper can do both, i.e. the catalog and the picture, and toggle between, I think that’d be more work but it’d be a win; the player could choose. As for managing real estate, a tab you could go into and come out from would seem reasonable to me as a player. It’s not necessary to have the map always visible at all times. Probably mostly in the beginning.

One last thought on what this might actually look like, because it connects to the notes suggestion earlier in the thread. If a map is really “rooms visited” and “threads untried”, then a map is just a kind of note,

I agree with that assessment. Just, it’s not everyone’s idea of a “map”.

It feels superficial to comment on the name, but I suggest that you rename from VΘXΔM to Voxam.

The Greek letter Θ is a theta, pronounced “th”. The Δ is a delta, pronounced “d.” And, in Greek, X is the letter chi, pronounced “kh” (as in “chiropractor”).

VΘXΔM would be correctly pronounced “vthchdm,” with no vowels. When I say it out loud fast, it sounds like “vithctim.”

(You aren’t the first (and won’t be the last) to do something like this. Early posters for The Odyssey (2026) spelled it ΘDΨSSΣΨ. The Ψ is a, psi pronounced “ps”, and the Σ is a sigma, pronounced “s”, and so this word would be pronounced “Thdpssssps,” perhaps the sort of sound you’d make to invite a cat to approach you.)

To respond more substantially…

IMO, automapping works substantially better in cooperation with the author. Almost all ADRIFT 5 games support a map of rooms; the ADRIFT IDE lets the author position rooms on a canvas (like you can in Trizbort), and customize connectors between rooms (adding explicit bends to keep the connectors from overlapping with rooms).

When playing an ADRIFT 5 game with a map, you can pan and zoom the map, you can see exits that you haven’t tried yet, and even click on a room of the map to auto-walk there.

A big :+1: from me there.

I’ve been working on Spatterlight’s ADRIFT support recently, and, to that end, I’ve been working on a Glk extension to support author-provided maps in games.

It’s intended to support “rasterized” (PNG/JPG) maps with a “you are here” overlay, or a map that reveals itself room-by-room as you play (“fog of war”), implemented via SVGs.

Historically, automappers have tried to deduce what room you’re in, perhaps by trying to parse the transcript to read the room name. But rooms can change their names, and multiple rooms can have the same name (as in the classic IF mazes). A naive transcript parser can barely even detect room names (especially if they don’t have access to stylehints, which often add bold styling to room names).

But when the interpreter knows where you are, knows which exits you can use to leave a room, and when the author positions the rooms on a canvas, you can get quite far.

It’s a fair point! It’s an affectation. I did that to match how the spell was worded:

Even then, it’s not fully right. But, yes, the primary stuff is just “Voxam” and I’ll likely update the README to get rid of the affectation.

I think your addition is a major part of the ballgame, actually: “where I am, and how to get where I next want to go.” Sit with that for a second, because that isn’t a map feature. It’s (at least from a certain point of view) a confession that neither of us wants to read a map at all. I say that because this asks for the answers a map provides (“where am I, how do I get there”), not for the map itself. If you want the outputs directly, you perhaps never wanted to operate the instrument. The everyday parallel to “where am I and how do I get there” is precisely what GPS navigation answers. The moment drivers could state that need and have it met, road atlases left the glovebox. Not because atlases got worse, but because it turned out people had never wanted to read atlases! They wanted to arrive. The atlas was a workaround with a fold. And people consulting a GPS are very rarely sitting there reading the map it displays.

Here’s what convinced me. When I was building Voxam’s recorded playthroughs, the most painful part of the whole effort was traversal: running around, remembering where things were. And here’s the kicker: I had maps. Drawn ones, good ones. It didn’t matter because the map is a reference document. You stop playing, consult it, work out a route, then translate the route back into typed commands one at a time. The consulting throws you out of the story, and the translating is pure tedium. A catalog and a picture just charge the same toll at different booths.

So maybe the honest conclusion is: the map you read is the legacy part, whatever form it takes. The map you can ask is the point. “Where am I” is one line the interpreter always knows. “Take me to the mirror room” is the interpreter replaying the ordinary commands you already proved work, while the game narrates the journey exactly as if you had typed them, because as far as the game knows, you did. The story text still plays. The locked door still stops you, and it should. What’s removed isn’t the game’s geography; it’s the part where you were the lookup table.

Under that framing, the catalog and the picture both survive, but demoted: they’re how you browse for a destination, consulted occasionally, mostly early. The routing is what you would use every day. Which reframes my earlier question with perhaps a little more spank on it: if the tedium of retracing is the actual problem (and I know you didn’t say that; that’s me), is having the interpreter retrace for you still “cheating”? Or is typing “e, e, ne, u, get lamp, w” from memory for the fortieth time the thing that was never really the game?

Still noodling, but this pushback is perfect. It’s forcing me to really think through maps.

This deeply misses the point. Reading a map is not our intrinsic goal; it’s a tool that we use to get where we want to go. But maps are the best/only way to solve the problem of getting to where you want to go.

Have you ever used a GPS system with no map at all? It’s unheard of. They all come with maps, because maps are the optimal way to interact with GPS. For example, is GPS navigating you to the correct location, or to another far-away location with a similar address? The map answers that question.

There’s another feature I think you’d also like, which I’ve called “autowalk.” For example, Counterfeit Monkey lets you go to items and rooms, and it auto-walks you there, stopping if there’s an obstacle. Hadean Lands does something similar.

But how do you remember the name of the place you want to go? You remember it was kinda south-by-south-easterly…? If that’s all you know, you need a map just to know the name of the room in order to navigate to it.

Once you have that, perhaps you just want to click on the room, which, of course, requires a map as the UI to click on.

No, you especially need it in late game, when there are so many rooms that you can’t keep them all in working memory any more. When you can’t remember the name of the place you want to go, the map is the best UI to figure that out.

I will agree to disagree, because there is more that the map tells me. Where I am, and where everything else is. It simply locates me spatially. I feel that I have reduced things a bit by saying “where I am and where I want to go”. Ultimately, I don’t think I have the words to reduce it further than this: I want it to tell me where I am in relation to everything else, in a visual manner I can easily parse, in my brain, to map out to a certain territory. This does not preclude the “logging” method, but to me they are not the same; but it’s outside of my capabilities to tell you exactly why that is, I can only tell you that my brain doesn’t parse a visual map the same way that it parses a list of exits and connections. The visual map works with all the other illusions of the parser to create a world for me to immerse myself in. The logging method reduces the exits to their functional purpose and helps break the illusion. But, this is all just my opinion, and I wouldn’t defend it in argument. I don’t think I have the chops for that.

Here’s what convinced me. When I was building Voxam’s recorded playthroughs, the most painful part of the whole effort was traversal: running around, remembering where things were. And here’s the kicker: I had maps. Drawn ones, good ones. It didn’t matter because the map is a reference document. You stop playing, consult it, work out a route, then translate the route back into typed commands one at a time. The consulting throws you out of the story, and the translating is pure tedium. A catalog and a picture just charge the same toll at different booths.

I see your point, and it’s a good one. Though it’s maybe not that different from “I’m stuck. Stop playing, consult my notes, consult my inventory”. But it does occur more often.

So maybe the honest conclusion is: the map you read is the legacy part, whatever form it takes. The map you can ask is the point. “Where am I” is one line the interpreter always knows. “Take me to the mirror room” is the interpreter replaying the ordinary commands you already proved work, while the game narrates the journey exactly as if you had typed them, because as far as the game knows, you did. The story text still plays. The locked door still stops you, and it should. What’s removed isn’t the game’s geography; it’s the part where you were the lookup table.

I admit I’m having a lot of trouble with this, because the truth is, I kinda need the map to locate myself and the geography of the world. In many simple games, I can map it in my head. In others, I can’t. The ones where I can’t, I really do need a map. It’s not something I can argue, debate, theorise about. It’s a need. Maps tell you where you are, and I transplant that function into IF wholesale without giving it a second thought.

EDIT - Thinking about it, I suppose the question is: how important is it to you, the player, to create a mental map of the geography of the game? Because your cogitations seem to be pointing at a different way of experiencing that geography, one which prioritises room connections to their destinations in a logging format. And I find that fascinating because I’ve seen other people mention that, but my brain simply doesn’t work that way. We may have arrived at something very important, where we conclude that every mapper is incomplete because it only really accounts for one way of mapping.

Well, two points: every time I’ve introduced textual IF to a new audience (the “mainstream” discussion), the very thought of the map writing (or even consulting) was one of the immediate turn-offs. So if it misses the point, it might be better to first ask: whose point are we considering? There are many points of view, hence my parenthetical. It certainly didn’t miss the point for me, as I pointed out, since I didn’t want to create or read a map. And I know for a fact I’m not the only one. (Which isn’t to say I’m not in the minority!)

As far as the best/only way to go, I would argue two points:

  • Not the “only” way: routing is. A map gives you the route only after you derive it yourself; a route-finder (GPS, Beyond Zork’s own GO TO) gives it directly.
  • Not (necessarily) the best way: for “get me there,” the map is the slowest interface: locate self, trace path, translate to commands. It’s the best way to see the whole territory, which is a different problem.

That’s not what I said. What I said is that people are not necessarily sitting there consulting the map. Not that there’s no map at all. Of course there is. But, arguably, the optimal way to interact with GPS is to listen to a voice. The GPS map is there to glance at, not to work from. Very few people need to derive their route from it; the routing engine does that, and the voice delivers it. The map became a passive orientation display the moment routing existed. Which is exactly my proposal: keep a view for orientation and let the interpreter handle the routing. The thing that died with GPS wasn’t the map; it was map consultation, and that’s the part I’m saying text adventures still make you do by hand.

That’s what the catalog could be for, and it’s a browsing problem, not a navigation problem. Three things cover it: rooms in IF are named things you saw on the status line every time you stood in them, so recognition beats recall (you scan a list and “Round Room” jumps out); the list can be searchable by what you saw there, since the interpreter watched the text (“which room mentioned a grating?”); and for the genuinely spatial rememberers, that’s what the picture view is for. Pick your destination however your memory works, then the routing takes over. The map-as-picture survives precisely for your case; it just works the counter instead of driving the cab.

Well, here I can finally use my cognitive science to help because it (possibly) has your words for you. Researchers distinguish route knowledge (sequences of steps: from A, go east to B) from survey knowledge (the bird’s-eye sense of how everything relates at once). They’re handled differently in the brain: a picture is parsed in parallel, so relations like near, far, between, clustered come for free just by looking; a list is parsed serially, so those same relations must be assembled in working memory, link by link, which is effortful. “Where am I in relation to everything else?” is precisely the survey question, and a list structurally can’t answer it at a glance, because it can only state connections one pair at a time.

So, for what it’s worth, you’re not failing to articulate a preference; you’re describing a genuine representational difference. A drawn map is externalized survey knowledge. A log is externalized route knowledge. Some brains build the survey view internally from routes without much cost, and those people are fine with lists. Yours, like many, would rather have it built for it. Which, again, for what it’s worth, is the strongest argument in this thread for the picture surviving as a view.

And, actually, that helps me see a route to satisfying both views. Noodling some more …

Yes, I think that’s it exactly. That’s the part where I’m starting to see a way through the twisty little maze.