Adding a new chunk to Quetzal standard to store last output

While pondering the fact that a simple Ok after restoring a game isn’t very helpful, particularly if some extended time has elapsed since the save. This leads the player to type LOOK. This causes assorted daemons and routines to run, which is probably not what anyone wants to happen. So, I can fix this by altering the Inform6 Library to run a LOOK without running daemons or routines or add some new functionality to the Quetzal standard.

What I’m proposing is to add an optional chunk to the Quetzal standard that stores the most recent text output prior to a save being done. Then when the game is restored, instead of presenting the player with an unhelpful Ok, the player is shown that last chunk of output.

Could I get some thoughts on this?

The Quetzal chunk is a reasonable direction to go in, but the “Ok” is generated by the game code, right? (Probably library code, but a particular game could customize this.) And it’s generated after the restore operation completes. The interpreter can’t just discard it, and shouldn’t try.

Getting this to display sensibly is a bit tricky. If you just spit the text out during the restore operation, the screen will look like:

> RESTORE

You approach the dangerous-looking door.

> SAVE
Ok.

> 

This is a bit disorienting. (Although I admit that leaving the pre-restore text on the screen is also disorienting!)

I guess you’re thinking of not copying the final “> SAVE” (even though the “>” is technically the last game text output!) This gets into mild hackiness – not all games use “>” for a prompt – but you should be able to get it to work. You might want to mark the copied text in some way that distingushes it from the regular text output:

> RESTORE

| You approach the dangerous-looking door.

Ok.

> 

I think it would make sense to replace all on-screen text, up to and including the RESTORE command, with the saved output state. After restoring, the screen would then look like:

You approach the dangerous-looking door.

> SAVE
Ok.

>

What you see there is actually the “Ok.” from restoring.

The Dialog library prints a more verbose report after restoring, which includes the current location (like the Inform library does after undoing). That would turn out like this:

You approach the dangerous-looking door.

> SAVE
Game state restored successfully.
Outside the ominous door

>
1 Like

It would look more like this:

You approach the dangerous-looking door.

You can see a nasty knife here.

> SAVE
Enter a file name.
Default is "deadlydoors.qzl": y
Ok.

> RESTORE
Ok.

You approach the dangerous-looking door.

You can see a nasty knife here.

>_

The text saved in the Quetzal file would be inserted after the Ok from the Library and before the next prompt.

This question was prompted by a discussion at https://gitlab.com/DavidGriffith/inform6lib/-/issues/103 asking me for some way to give players something more than Ok. upon restore to remind them what happened prior to the save . That Ok is generated by the Library. I can also see how this addition to Quetzal would be handy for the new bot mode for Dumb Frotz that I’ve been fiddling with over the past month. See https://gitlab.com/DavidGriffith/frotz/-/issues/207

In my humble opinion, that would be very confusing. You are reproducing the old pre-save text after the output that’s generated by the restore operation.

This is the original timeline (game-world and real-world):

  • 1: Approach door.
  • 2: Player types “SAVE”, game/library says “attempting to save” in some way (possibly blank).
  • 3: Actual save is performed.
  • 4: Game/library says “save successful” in some way (possibly “Ok”).
  • 5: Player opens the door and dies.

After a restore, this is the real-world timeline, as it looks on the screen in a traditional interpreter:

  • 1: Approach door.
  • 2: Player types “SAVE”, game/library says “attempting to save” in some way (possibly blank).
  • 3: Actual save is performed.
  • 4: Game/library says “save successful” in some way (possibly “Ok”).
  • 5: Player opens the door and dies.
  • 6: Player types “RESTORE”, game/library says “attempting to restore” in some way (possibly blank).
  • 7: Actual restore is performed.
  • 8: Game/library says “restore successful” in some way (possibly “Ok”).
  • 9: Player does something more sensible.

Restoring causes the game world to backtrack to when the actual save was performed. So in the game world, this creates the following alternate timeline:

  • 1: Approach door.
  • 2: Player types “SAVE”, game/library says “attempting to save” in some way (possibly blank).
  • 3: Actual save is performed.
  • 7: Actual restore is performed.
  • 8: Game/library says “restore successful” in some way (possibly “Ok”).
  • 9: Player does something more sensible.

At the minimum, I would expect the text from each individual game-world timeline to appear in chronological order on the screen. Then, one can argue about how/whether to interleave the two timelines.

My suggestion is that when you restore, you also clear the screen and reproduce the output of 1–3 from the savefile. Then you execute 7–9 normally. That would put the alternate timeline on the screen, as described above.

Instead, your suggestion would put the following on the screen:

  • 1: Approach door.
  • 2: Player types “SAVE”, game/library says “attempting to save” in some way (possibly blank).
  • 3: Actual save is performed.
  • 4: Game/library says “save successful” in some way (possibly “Ok”).
  • 5: Player opens the door and dies.
  • 6: Player types “RESTORE”, game/library says “attempting to restore” in some way (possibly blank).
  • 7: Actual restore is performed.
  • 8: Game/library says “restore successful” in some way (possibly “Ok”).
  • 1: Approach door.
  • 2: Player types “SAVE”, game/library says “attempting to save” in some way (possibly blank).
  • 9: Player does something more sensible.

My point is that 8-1-2-9 does not make sense, in the game world or in the real world. If you print those lines as new content, they should appear in the correct order, 1-2-8-9. And then one can argue whether the old screen content (1–7) should be cleared or not.

1 Like

After a Restore command, an entry point to an AfterRestore() routine, for the game programmer to do whatever he wants with it, wouldn’t be enough?

I’m a bit skeptical about saving that text in the save file for two reasons:

  1. You’re dependent on all the interpreters catching up to the additions in the extended file format.
  2. You might have saved the game a week ago. I think you only need a reminder of where you are now (i.e. after doing the restore), not a reminder of the last action you performed a week ago prior to the save.

I agree with Linus. I don’t think anything from the past should be repeated on the screen, except to refresh your memory of where you are after the restore. Which leads me to a third reason for not saving the text in the file and reprinting it on the screen. (I had thought of this before, but forgot to mention it.)

One could argue that you don’t need to show the player where they are because it’s shown in the status bar. There is one problem with this argument. I have recently been wading through transcripts from my play testers. They would occasionally save a game and restore it later. When the game is restored, the transcript does not tell you where you are, so I have to go backwards through the file to try and find where they were when the game was saved. Of course, if they made multiple saves with different file names, I have no way of knowing which file was restored. At least not with Glulxe. This may be different for other interpreters. Which leads me to reason number 3:

  1. Transcript. The transcript should not repeat something that you’ve already done to make it look like you’ve done it twice and it should show you where you are after restoring the game.
1 Like

To me this seems like something that should be changed in Inform - what Dialog does seems like a good approach to take.

This is a positive feature, I’d say. It’s an optional addition to the save format and to the interpreter, which means that:

  • It will work with old games (there are a lot of old games!)
  • Old interpreters will silently ignore it;
  • A new interpreter will revert to the old behavior when loading an old save file;
  • If the player doesn’t like it (and some players won’t like it) they can use an interpreter that doesn’t support it or has a preference to turn it off.

Putting the logic in the Inform library means more complexity for the author to deal with, which is always a worry. (For example, repeating a Look action might change the game state.)

One option to deal with the save command being in the transcript, with game state being out of sync etc, would be for the interpreter to ask the user if they want to see the included transcript (possibly with distinct formatting if the terp supports it.)

An AfterRestore() hook seems like a very sensible thing to add in any case.

Agreed.

In my case, I had a daemon running in one room and it incremented the room state. Room graphics and reactions from an NPC were affected by the state. (It’s like a cut scene in the end game, except that the player has a few moves to react to the villain.) After a restore, I had to check if I was in this location. If I was, I had to decrement the state, then do a LOOK (now the image was correct), then test this location again. If it was the end room, forcibly run the daemon that would normally have been skipped to get the correct NPC response and increment the state to get back in sync.

So the post restore action was: test, look, test again. It works nicely now.

1 Like

I added an AfterRestore() stub that seems to work well enough. To make the game print the name of the location and a list of objects to take or manipulate, you do this:

[ AfterRestore;
        PrintOrRunVar(location.description);
        Locale(location);
];

I’ve checked this with both Z-machine and Glulx.

What about LookSub(1) or <<Look>>;? Will they work? Any preference?

<<Look>> will always produce the same effect as typing LOOK. As I dug into how to rework LookSub() to do a room description and not change the state of the game, I couldn’t figure out how to guarantee that or even craft a meaningful caveat of what to do or not to.

You might need to consider PrintOrRunVar(location.describe) as well, depending on the game. Also, this approach doesn’t account for lookmode.

I think that part’s intentional. I’d prefer to see the description again after a RESTORE, even if I normally play on BRIEF.

I tend to agree with you. In my current game, I’ve disabled brief and superbrief anyway, because of the graphics.

This is quite a bit off-topic, but I’ve noticed that verbose is the default nowadays. For a text-only game written in the style of a classic text adventure, I still prefer brief, especially on mobile phone.

For new games, you redefine the AfterRestore() function in your program and do whatever you want. However, a potential problem can occur if you recompile old games.