Is there a function that can be used to generate global state of objects, rooms, doors, nouns, etc in a story?

Hey all,

Super thankful of all of the help provided so far, cannot wait to put the project up!

Had a question about I7, related to state management and merkle trees (a cryptography thing that we’re trying to work on). Basically we want to make a cool little bookmark based on the state of different variables and make the bookmark change based on things that the player has accessed.

We have an idea on how to do that, and were just going to manually say “find all variables, save all of their states to a table, make an array/object out of the possible states, feed that array/object into the fancy bookmark maker”, but figured we’d ask if there was something innate to the language or i7 program/compiler where we could pull all of the states of all of the items created.

We figured that because the Index is able to list a lot of stuff (basically everything), that there might be support for that, but we weren’t sure how the devs referred to state management, tries, or other data structures generated by the whole story file.

This is difficult because Inform compiles the game down to Glulx/Zcode, which are low-level machine code VMs. They don’t have reflective information about their own state. Everything is represented as bytes.

Inform also generates the Index pages, but the game (and interpreter) don’t have access to that.

You can parse some of the state back out by using the debug info: see project.inform/Build/gameinfo.dbg. This is an extensive data file describing the byte address of everything. But trying to track all the game state this way is going to be an extensive headache.

1 Like

Why not just store a save file every turn?

1 Like

We could do that, but if we wanted to track state and pass that to an external file, we’d need to know heads/tails of what was saved anyways.

Looking at the index and how it’s able to track every room, door, direction, rule, scene, object, etc. maked us think that there would be a way to abstract some of that and get an object that can programmatically see the state of a fragile vase in a Red Room that’s coded to disappear/break when thrown.

We’re probably going to keep a tally of all of the objects we make and their states, and manually use that to generate the “save state” as you said, but was wondering if there was a programmatic way to do it already that’s hidden behind some technical term we don’t yet know.

fyrevm-web channel IO would allow you to do both, saving off any data you want in a custom channel along with the save file.

1 Like

Assuming you don’t mind running only in the browser*, and it sounds like you might have been planning on that anyway, I think you could probably accomplish what you want vis-a-vis dynamically updating the contents of a window based on state with Vorple. You could send as much state info as you wanted, based on whatever level of granularity was relevant, but you’re still stuck building the representation yourself. Doing it dynamically sounds easier than having all the potential output generated in advance and finding it via lookup based on a some string or hash representation of the whole game state… but it sounds like you have some particular reason for wanting to do it that way. (And of course, you could still implement it that way.)

*It could also be bundled with Electron if you wanted a standalone app.

1 Like

It occurred to me that the output of the “TREE” and “SHOWME ...” commands gives you some of the information in which you are interested (about objects and their states). This includes information about custom properties like your example with the potentially broken vase.

Example from the “Disenchantment Bay” scenario:

>tree
compass (629728) 
  the north
  the northeast
  the northwest
  the south
  the southeast
  the southwest
  the east
  the west
  the up
  the down
  the inside
  the outside
(darkness object) (629760) 
(Inform Parser) (629792) 
(Inform Library) (629824) 
(property_numberspace_forcer) (629856) 
(ValuePropertyHolder_43) (629920) 
(ValuePropertyHolder_47) (629952) 
Cabin (631104) 
  a cabin door
  a view of the Malaspina glacier
  yourself
    a backpack (open)
      a warm beer
    a pair of sunglasses (being worn)
  a glass case (closed and locked)
    a collection of fishing rods
  a bench
    some blue vinyl cushions
  some navigational instruments
  some scratched windows
  a radar display
  some radios
  a Captain
    a small silver key
    a baseball cap (being worn)
  a sign
storage compartment (631520) 
  some nets
  a warm Coke
screen (631616) 
Deck (631712) 
  an ice chest (closed)
  a glacier ice

>showme coke
warm Coke - beverage
location: in the storage compartment , which is part of the bench in the Cabin
singular-named, improper-named; unlit, edible, portable; closed, openable
list grouping key: none
printed name: "Coke"
printed plural name: "beverages"
indefinite article: none
description: none
initial appearance: none
heat: warm

Unfortunately:

  • they are only available in debugging releases, and
  • I think there’s no (convenient, built-in) way to execute them programmatically and capture their output.

I don’t know enough about the underlying I6 code to say if one could work around these problems somehow.

But if you use Vorple, as was suggested, you could use Vorple Command Prompt Control to issue those commands, like this:

Include Vorple Command Prompt Control by Juhana Leinonen.
Release along with the "Vorple" interpreter.

The Cabin is a room.

The coke is in the Cabin.

[Insert the whole Disenchantment Bay example here for more interesting output.]

When play begins:
	queue a parser command "tree";
	queue a parser command "showme coke".

(And use “Release for Testing” in the I7 IDE.)

You could tweak this, for example using “without showing the command”; and you could do something with the output using output filters and so on.

1 Like

Hey, as an update to this, do you think it would possible to tweak Glulx (GitHub - erkyrath/glulxe: The Glulx VM reference interpreter) to make it so that each object/item/player’s state is hashed, and then a merkle tree can be generated from those hashes?

The answers above still apply.

So I’ve been pondering this and I think that it can be done without having to modify the runtime environment. It all depends on what’s inside the “fancy bookmark maker” black box, though, and it what it needs as input, and exactly what you’re tracking about different rooms and objects.

But I threw some code together to implement two different possibilities.

Let’s say you have a simple map set up with some rooms and objects:

Include Epistemology by Eric Eve.

Bedroom is a room. The futon is an enterable supporter in Bedroom.

Hallway is west of Bedroom. The rug is scenery in Hallway.

Bathroom Door is a door. It is west of Hallway and east of Restroom. There is a toothbrush in Restroom.

South of Hallway is Living Room. The blue couch is an enterable supporter in Living Room.

West of Living Room is Kitchen. The electric mixer is a device in Living Room. A beer is a thing in Kitchen.

Southeast of Living Room is Front Lawn. The lawn chair is an enterable supporter in Front Lawn.

I include the Epistemology extension because it tracks the known/unknown status of objects (and several other things about them, which might be better for your specific scenario, depending on the specifics of that specific scenario). Otherwise, this just sets up a map and sprinkles some objects in it. The only thing I’m using below from Epistemology is the “known” adjective, though.

You can then track the objects and their status in a table:

Making a bookmark is an action out of world applying to nothing. Understand "bookmark" as making a bookmark.

Table of Stuff
Name	Status
an object	a text
with 50 blank rows

Report making a bookmark:
	blank out the whole of the Table of Stuff;
	repeat with item running through objects:
		choose a blank row in the Table of Stuff;
		now Name Entry is item;
		if item is a room:
			if item is visited:
				now Status entry is "True";
			otherwise:
				now Status entry is "False";
		otherwise:
			if item is known:
				now Status entry is "True";
			otherwise:
				now Status entry is "False";
	sort the Table of Stuff in Name order;
	showme the contents of the Table of Stuff.

Tables are the basic structured data format in Inform, so I had to work with that.

The action-processing machinery here is probably not what you want, but it could be easily adapted to do something else with the table once it’s been filled out. One of the downsides is that you probably need to make the table of sufficient size in the beginning (I think? are tables resizable?). I use the command showme the contents of the Table of Stuff here just as an example for poking at the construction: it results in kind-of-ugly output that’s only intended for debugging, and printing the bookmark to the screen in that format is probably not what you want. (For one thing, I don’t think that Inform has any mechanism for parsing a printed table back into a game state at all.)

But one thing you can do with tables is write them to disk, and depending on your setup, that might work, especially if you’re running in an environment where you’re also doing other stuff; you might plausibly open a socket or some other kind of file-like object and write to that. Writing with Inform 23.11 through 23.15 talks about writing external files.

Notice that the table that gets printed includes all sorts of under-the-hood objects, like the compass and some Inform internals, like the Darkness object and each of the compass directions. I didn’t filter that out, but there’s a good chance that you might want to.

Ryan Veeder has written some blog posts about how he worked with external files in Inform to implement autosaving for his game Ryan Veeder’s Authentic Fly Fishing, they’re here and here (and there are maybe others? poking around his blog might pay off).

You might want to track other things than just a true/false status for each room and object, but this basic idea should be readily adaptable if you do.

Alternately, if what you really want is just to produce a short-form True/False check for each object and room, you might try something like this:

Making a binary bookmark is an action out of world applying to nothing. Understand "binary bookmark" as making a binary bookmark.

To decide what text is the binary bookmark:
	let things be the list of objects;
	sort things in printed name order;
	let the output text be "";
	repeat with item running through objects:
		if item is a room:
			if item is visited:
				now output text is "[output text]1";
			otherwise:
				now output text is "[output text]0";
		otherwise:
			if item is known:
				now output text is "[output text]1";
			otherwise:
				now output text is "[output text]0";
	decide on output text.

Report making a binary bookmark:
	say the binary bookmark.

This just gives you a string of ones and zeros with no direct indication of what they represent; bookmarks made this way would of course break if the game’s internal structure changed. But it’s a more lightweight form, and you could (for instance) parse the string representation back into a large integer and do something with it, or maybe break it into six-character chunks for processing into a Base64 string to build the bookmark out of, or something.