Which interpreters provide plugin systems? Which would allow me to develop such a system? Should I?

I have long had the desire to auto-generate a map as I play.

I see two possible approaches:

  1. Somehow intercept the transcript and parse it.

  2. Modify the interpreter to output the info I need.

#1 seems unlikely, as it would some gnarly parser work. There just too many ways for items to Create read Update and Destroy items.

#2 seems better, if the parsers are modular. I.e there is one central routine for each of the CRUD operations. However, Andrew Plotkin in this thread said

Z-code/Glulx interpreters are not structured on that level. There are such routines, but each game implements them separately. Moving and checking map connections can work differently from game to game; the interpreter doesn’t know what routines do what.

So, that seems to put the kybosh on that idea.

My latest thought - and I would like comments on its feasibility - is to mod each of the common interpreters, starting with TADS & Inform, so that, after processing each input, they broadcast details of every object in the game over a socket.

That would require a one-time modification to each interpreter. After which, plug-in writers can connect to the socket, parse this list compare it and against the previous version. This would allow them to detect CRUD operations and, in my cause, update the auto-map.

Can anyone say if this sounds feasible? Or if a sort of universal plug-in system is even desirable?

2 Likes

Ideally you would need the authors to include something in their games that state whether or not the game complies with the world model you’re using.

Idk about Inform, but every time you play a TADS game that uses rooms-door-item structures and the normal north-south-east-west-up-down-in-out, that author is willfully complying with traditional conventions.

A TADS game can literally be anything, and model the world in any way at all. The only reason most TADS games follow the usual IF parser world model and navigation is because that’s what the Adv3 and Adv3Lite libraries are specialized for.

However, literally nothing (but time and effort) is stopping me from doing away with rooms entirely, and making a parser game that works with continuous spaces (this is a mechanic from a WIP). Nothing (but time and effort) is stopping me from making a turn-based flight sim in TADS (another WIP).

Nothing (but way less time and effort) is preventing me from making a 4D puzzler with brand-new directions.

So your first priority for this kind of toolset is probably to write up a comprehensive document that outlines the standard of what your program/toolset would consider a “room”, “door”, “item”, and “valid direction of movement”. From there, an author would need to choose to cooperate with this standard while designing a game. Finally, they would need something to transmit to your toolset that announces the game’s world model will comply with your standards.

If a game doesn’t do this, your toolset needs a way to say “Hey this game is not supported. Sorry for the inconvenience!”

The authors might also want ways to influence how the information is presented in the toolset, to make sure certain curtains are not pulled away or anything.

3 Likes

A bit of vocab: TADS and Inform are not interpreters, but development systems really: I7 etc. are languages plus a set of libraries to generate Z-Code, Glulx, whatever.

The interpreters are things like Gargoyle, Frotz, etc.

With a completely static map, it is technically possible (though probably not easy) to hack I7 to output something that could be used to generate a map, given an interpreter that will support that. But as soon as the map is NOT completely static, it’s not really possible.

3 Likes

Also, just to provide a more immediate example:

In TADS, a “room” is actually just a hybrid of a travel connector and a container. Nothing about its class data makes it any different from a door or a locker that the player can step into.

The stuff that sends information to the interpreter UI identifies it as the container that is not itself contained.

If I made a car in a garage, put the player in the car, and then moved the car out into the empty void, the car might qualify as a room.

Again, Inform might handle stuff in a similar way; everyone who uses that is literally a wizard, and when I visit their side of the forum it feels like I’m reading cosmic texts.

But yeah, assumptions of world model stem only from the fact that authors willfully comply with it so far.

1 Like

A better option is to have the author provide the map in some kind of symbolic form. The author could provide a more appropriate map (taking into account hidden exits, etc.) than an automapper could, and it wouldn’t even be terribly hard.

2 Likes

OTOH if you want to see what you can do with mapping if you do it all yourself, check out:

(if you haven’t already)

1 Like

I feel like this would be the best option.

Also the automapper should be prepared for a situation where a map changes. I have another WIP that uses airlocks, where the connections between doors can change.

But yes, ideally the author would need a way to transmit standard-compliant world model data to the toolset, so that they could format it in a way they feel is best.

Like, I can make a hallway connect to a vehicle in TADS, which is contained inside of a room. The world model is literally 100% arbitrary. A standard model for communicating data would be a necessary first step.

1 Like

Thanks for some good feedback. But, let’s not get hung up on just mapping, even though it is my interest.

I think that we need something generic as we can’t forsee all possible plugins.

2 Likes

Oh…darn it, I just re-read your post, and realized you intended for a general toolset. Lol, sorry, must have gotten tunnel vision for a bit there.

1 Like

Short answer: There have been a lot of stabs at this idea, but when you dig into it, the idea of a standard doesn’t really fall out. Instead, you wind up making game-specific modifications to the interpreter.

Focusing solely on the Inform side for the moment, we’ve seen:

  • FyreVM: An alternate I/O layer for the Glulx VM which lets the game write to custom streams. Then the custom interpreter displays them however it wants. (Could be a separate inventory pane, could be a separate illustrations-and-maps pane, whatever you want.) This goes along with the idea that the interpreter will display the whole game using custom typography. If I recall correctly, the interpreter was a Unity app so customization meant adding more C#.

  • Vorple: A customizable web-playable interpreter for Glulx. The game can write to special output streams (like the above but implemented differently). Then the interpreter can display whatever it wants. Since the interpreter is a JS app running in a web browser, customization means adding more Javascript.

  • In Hadean Lands, I customized Lectrote to display a dynamic map (including the player’s location) and dynamic journal window (showing the list of spells you’ve learned). This works by peeking directly into Glulx VM memory and inspecting variables and object properties. Since the interpreter is a JS app running in the Electron framework, customization means adding more Javascript.

  • I actually did the same thing, in a very small way, for Advent Mirror. Here the interpreter is a web-playable JS interpreter, rather than running in Electron, but the process of peeking at VM memory is the same.

In all of these cases, there’s no standard for what information is communicated. If there were, the standard would need to be “all of it” and that would be very unwieldy. Instead, there is (generally speaking) a communication channel. The game author decides what information to put across and implements code on both ends of the channel.

However, customizing the interpreter runs straight into the other end of the problem, which is security. You can’t just distribute a code plugin as part of a game file. If you did, every third Inform game on IFDB would be a scam to steal your contact list and message all your friends about bitcoin deals. (If not just mine bitcoin directly on your CPU.)

If you do anything like this, your options are:

  • Your game is browser-playable only. All customizations are JS and run with standard web-page restrictions.
  • Your game is distributed as a downloadable app (perhaps on Itch.IO). People who download it understand the risks and rely on standard procedures for managing that risk. (Code-signed apps, virus scanners, etc.)

So the idea of a standard plug-in architecture kind of fails on both of these fronts. You’re customizing the interpreter anyway (either because it’s a browser page or a distributable app) so you might as well go down the path of controlling both sides of the channel.

10 Likes

Thanks, Andrew. That’s some useful information there. I think that my approach would be to dump all major data structures after every move, and have the plugins diff that with the last dump and take action as they see fit.

I am not sure how that would be unwieldy. Do you just mean the amount to data? It’s unlikely to be more than a few 100k, but even a few mB isn’t that much. Just push it over a socket and the plugin has enough time to receive and process it while the sluggish human takes seconds to enter the next command.

As to security, plugins could be open source, but why be platform specific? I agree with you on browser based. That makes it slightly more complicated, as push technology on the web is rather tricky. And, if we JS plugin queries he game engine then the game engine has to run a server.

Hmm, it seems that the Push API has wider support than when I last looked a few years ago.

Would that be an acceptable solution? Or should I give up on the idea? When you say “controlling both sides of the channel”, I see a one to many Relationship, where one “dump everything” mod the the game engine is used by plugins in ways that I cannot imagine.

Also, I would propose a way for authors to include a plugin kill switch in their works.

1 Like

Remember that most IF systems don’t have strictly-defined data structures that make it easy for an external program to see “ah, the Kitchen is north of the Living Room”. Instead, the game itself contains code to take the value at this memory address (the player’s location) and add this offset (the offset to the “north” property) and take the value at that memory address and store it to the first memory address (the player’s location)…

The interpreter is just retrieving values from memory, performing arithmetic, and storing values to memory. It has no idea what this means for the model world, or for the player’s experience.

This is why systems like Trizbort focus on working from transcripts, which capture the player’s experience better than looking at individual memory accesses.

5 Likes

I’ve thought before that it would probably be possible to create something like a GraphQL system in Inform, where VM hosts could query the game’s object tree and get back whatever data they need. But it would need a side channel/stream to be added to Glk and then to whichever interpreters people wanted to use. Would be a more flexible way than inspecting specific bytes like Zarf described above.

3 Likes

Can I dump all rooms/items, etc? I don’t want to know that the Kitchen is north of the Living Room, just that there is a Kitchen and a Living Room. And what they contain - after every command I enter, which might well change what they contain.

I feel like Trizbort can’t be totally accurate. How can it know that a magic bean can change to a beanstalk? Or that a worn out item has disappeared? That’s a shed-load of Natural Language Processing, far more complex than the actual game engine.

I will admit that Trizbort is very impressive, but I can see so many ways that it could go wrong. Absolutely no offence intended.

1 Like

Some systems have a transparent data structure for objects, like the Z-machine, while others don’t. In Glulx, an object is just a block of memory with pointers to other blocks of memory.

1 Like

If your main purpose is to auto-learn a map, I have a suggestion;

Assuming you want to use glk interfacing games, they always have at least two streams; the text “body” and the title “status” channels. The status line always has the current location.

So;

Just capture and track changes to the location in the status channel and learn when they change. You can then build a connectivity graph between locations as they are played. Now, of course, this doesn’t give you directions, but therein lies also the pitfall, as some games do not use standard directions anyhow.

It could actually be an advantage not to know the directions! In some games, directions are not consistent and there are also up and down to consider, which altogether makes drawing a flat layout complicated.

The games that I’ve made with auto-maps have always needed the layout to be authored manually up front, otherwise it’s just a horrible mess. I’ve tried fancy layout software with knowledge of the directions and they just don’t cut it. manual layout was always much better.

But;

There are many graph layout programs I’ve played with that do quite a good job of making a planar layout of a given connected graph. You don’t get NESW, but they do show connections, and it would still be quite cool (and do-able).

2 Likes

Unfortunately this isn’t always the case. Most Inform games do, for example, but what’s shown in the status line is entirely up to the game. You can make a game that has no status line, or has three status lines with different contents, or has a status line that shows the location’s description instead of its name (like in Scott Adams games)…

3 Likes

I know. And thanks for pointing this out. Trouble is, any such solution won’t work for all games. Suppose you have a game with a magic teleporter that you can use from any location. This will play havock with any learning algorithm.

2 Likes