To be clear, what I’m asking here is:
- Are there explicit definitions to serve as answers for these questions, based on the ZMS 1.1 specifications? Failing that, are there accepted or consensus definitions among those actively writing and maintaining Z-machine interpreters?
- If the answer is yes to the above, what are those definitions with respect to my original questions about Flags 2 bit 4 and the return values for the @save_undo opcode?
I’m asking from the perspective of someone writing a game, who is trying to anticipate the interpreter environment(s) on which it will be played.
Dannii makes a good point about the possibility of loading a save game from interpreter A into another interpreter B with different capabilities. From the functional perspective of the game, this is equivalent to saying that the interpreter is free to change its mind during execution about whether or not it supports undo capabilities. There is a relevant passage in the remarks at the end of section 6:
Given the existence of Quetzal, a portable saved file format, it is quite possible that after loading, the game may be running on a different interpreter to that on which the game started. As a result, it is strongly advisable for games to recheck any interpreter capabilities (eg Standard version, Unicode support, etc) after loading.
However, note that a preceding passage in the same section basically disclaims save game portability as a feature of the standard:
These issues are taken up in great detail in Martin Frost’s Quetzal standard for saved game files, created to allow different interpreters to exchange saved games. This Standard doesn’t require compliance with Quetzal, but interpreter writers are urged to consider it: it can only help authors if players can send them saved games where bugs seem to have appeared.
I do appreciate your responses, @Mike_G, as they are very informative. However, I’m still looking for concrete answers, and it’s not encouraging that you’ve already proposed two different possible models of interpreter response. The purpose of a standard is to create predictability from both sides of an interface, so shouldn’t it have definite answers here?
As a broader question, there seem to be real questions about the purpose(s) which are served by Flags 2 bit 4. Competing concepts include:
How the flag is to be set by the game:
1a. It’s to be set in the game by the compiler at compile time only, to signify that the game wishes to use undo capabilities at some point or always during execution.
1b. It’s to be set by the game via opcode at any point during run time, to signify that it wishes to use undo capabilities from that point onward during execution. (And the game may attempt to send this signal more than once.)
How the flag is to be cleared by the interpreter:
2a. It’s to be cleared by the interpreter only at VM initialization, to indicate that it cannot or will not support undo capabilities at any point during that run of the game (regardless of future changes in interpreter or interpreter settings across play sessions).
2b. It’s to be cleared by the interpreter at VM initialization and upon restoration of a saved game, to indicate that it cannot or will not support undo capabilities during that particular play session of the game.
2c. It’s to be cleared by the interpreter frequently (i.e. at least per turn) during execution, to indicate that it cannot or will not support undo capabilities at that point during a particular play session of the game.
How the flag is to be set by the interpreter:
3a. It should never be set by the interpreter. (This looks like the best interpretation of what’s actually in the standard.)
3b. It should be set by the interpreter at VM initialization, to signal to the game that it is willing and able to support undo capability through that run of the game (regardless of future changes in interpreter or interpreter settings across play sessions).
3c. It should be set by the interpreter at VM initialization and upon restoration of a saved game, to indicate that it is willing and able to support undo capabilities during that particular play session of the game.
How the flag is to be cleared by the game:
4a. It’s never supposed to be cleared by the game.
4b. It should be cleared at compile time to indicate that the game doesn’t care whether undo capabilities are available or not. (This seems supported by the standard as written.)
4c. It should be cleared at any point during run time to signal to the interpreter that the game does not want undo capability to be present. (This isn’t supported by the standard, but it puts the game on equal footing with the interpreter about being able to change its mind during execution.)
It seems as though the bit is intended to serve more than one purpose: first as a signal from game to interpreter, second as a signal from interpreter to game. I haven’t found anything about timing requirements that will let the signal flow both ways unambiguously. It’s also complicated by the fact that, as written, each side is only empowered to say one specific thing in the process. The game says “I would like to use undo” and the interpreter (observing the bit as set at one or more unspecified points) either responds explicitly by clearing the bit to say “Too bad, you can’t.” or implicitly by leaving it set to say “OK, that will be fine.”
The implication is that, after a single initial exchange or at any point in a continuing conversation, the state of bit 4 can be read by the game as “Undo capability is available now.” That seems to be the usage intended by the standard, but the details about the nature of the conversation between game and interpreter to create this meaning aren’t clear.
To add more complexity, the result of @save_undo serves as a separate method of communication between game and interpreter about the interpreter’s willingness/capability to provide undo, and there doesn’t seem to be firm information in the standard about whether and how those signals from the interpreter side should correlate.