[I6] Can you preserve a global variable after restart or restore?

I have a game with graphics and sound and allow you to turn them on or off. In both cases, the default is on.

I just realised that if I turn them off and restart a game, they turn themselves back on again. I’m presuming this is because I use Global variables to keep track of the status and when I restart a game, the global variables are reset. Similar thing for restore if the current status is different to the saved status.

So is it possible to save the status such that it is persisted after a restart or restore without resorting to saving to a file?

If you’re using Glulx, the @protect opcode can preserve a single block of memory across restorations. So you could use this on a special array:

Constant PRESERVED_AMOUNT [whatever you need]
Array protected_data -> PRESERVED_AMOUNT;

[ SetProtections ;
    @protect protected_data PRESERVED_AMOUNT;

Then just call SetProtections() when the game starts up. Now all the values in protected_data will survive restore, restart, undo, and so on, and you can use them for your settings.

Note: This differs from saving to a file in one crucial way.

With this system, if you quit the game completely, then start it up again, then restore a saved game, all the values will be reset to their defaults. (Because the game sets the default values, then protects those values, so the restore can’t bring them back.)

With an external file, if you quit, start up again, and restore, they’ll survive intact.

One way to change this is to only call SetProtections() after changing the settings, or after restoring a game. Another way is to use one of your protected values to store whether the values are all default, and not do the protection until that value changes. It comes down to what your intended behavior is.

It is a Glulx game, so this sounds perfect. I’ll give it a try.

Okay, that was a bit tricky. I couldn’t get it working at first because I fell foul of your [whatever you need]. When I read the Glulx spec, it turned out that [whatever you need] is in bytes, but your example was using a word array, so I really needed [whatever you need in words] * WORDSIZE. As I only need a few flags, I opted for a byte array, so I’ve set it up as follows:

Constant ACTIVE 0;
Constant GRAPHICS 1;
Constant SOUND 2;
Array media_state -> 3;

[ Initialise;
  if (media_state->ACTIVE == false)
    @protect media_state 3;
    media_state->ACTIVE = true;
    media_state->GRAPHICS = true;
    media_state->SOUND = true;
! Then set up the sound and graphics depending on media_state flags

Then all my other routines for drawing graphics, turning graphics on and off, playing sounds and turning sound on and off are dependent on the media_state flags.

It’s all tested and working well. Thanks for the pointers.

Oops, that’s my bad. I meant to make it a byte array—fixed now for the sake of future readers!