Extracting room connections from zcode

I’m working on an interpreter/mapper for android based on zmpp2 and my own White House mapper. One feature I plan on including is auto-mapping as you play. Most mappers parse transcripts for auto-mapping capabilities, but since the app will contain both an interpreter and a mapper I thought I would get more sophisticated than that.

I only have a rudimentary understanding of zcode, but I have successfully been able to detect when a room has been entered. Basally I watch for when objects are inserted into the object table; when the object being inserted is the player then the parent is the room. Where I’m stuck is determining the connections between rooms. I can see there are references to the adjoining rooms in the object properties but have been unable to determine which properties correspond to which directions.

One idea I had was to examine the routines for moving (go north etc.) but I can’t seem to find any such routines… are they not routines?

Anyone with a better understanding of zcode want to help me out here?

Room objects have direction properties called n_to, s_to, etc. These properties can have objects, strings, or routines as values.

When a player travels in a certain direction from a room, the corresponding property is consulted. If it’s an object, it’s either a door object or an adjoining room. If it’s a string, it’s treated as a customized cant_go for that direction, and the string is printed. If it’s a routine, the routine is executed and will either return an object (treated as the destination), or true (meaning can’t go, with a string already having been printed for the player), or false (meaning can’t go, with the library printing its own can’t go msg).

Check out §9 of the DM4 and associated exercises for details. You can also check out GoSub in verblibm.h to see the actual code where the library makes use of these properties when processing a command like GO NORTH.

There is no guarantee that a story file will store the room connections in any particular way.

This is true. The system that I described in my earlier post is implemented by the Inform library; it’s not inherent to all zcode files in the same way that the object tree is. It’s possible that a game is using an alternate library or no library.

Thank you! That was extremely informative. Unfortunately it sounds like it may be more reliable to simply parse the output to discover the movement direction. This will require some more thought.

How do I determine which properties are n_to, s_to, etc.? The source code for the reform decompiler has a comment, “In Infocom files, there’s a “direction” type for dictionary words, which tells us which properties are ZIL exits.” I am able to find the entries in the dictionary (flag bit 4 is set) but how do those tell me which properties are exits?

Unfortunately I never learned Haskell so I’m not able to piece together what reform does…

The property number of the corresponding direction property is stored in the dictionary entry for words that have the dir flag set.

If you grab the ztools and run infodump with -d and -c1 on an Infocom file, you can see this dict info. Here’s an example of some output lines for zork2 version 48:

[ 384] @ $4337 north   [32 ee 1f] <adj> <dir>
[ 540] @ $477b south   [32 f2 1c] <adj> <dir>

In this output, the third byte of data after the text of the word (1f and 1c respectively) encodes the property number: 31 decimal for n_to and 28 for s_to. The comments in the reform source say that Sherlock is weird and has only 2 bytes of dict info, so this exact layout may not apply to every single Infocom story file, but the principle ought to be the same.

Another easy way to get the numbers is to look at these reform symbol files. If you grep for “exit”, you’ll find the property numbers for the various direction properties in each game.

For modern files compiled by Inform, none of this applies. Instead, there’s a compass object containing a set of direction objects, each of which has a door_dir property whose value is the property number of the direction property associated with it. So, for example, the n_obj object is in compass and n_obj.door_dir is set to n_to.

If you do want to check out Haskell, here’s a post that I made with links to some free Haskell books.