[i7] Resetting deep game state variables without restarting

Inform 7 seems to store a lot of variables without providing the dev with any access to changing them. Is there any way I can reset the state of ‘[one of]option a[or]option b[or]option c[stopping]’ so that it no longer remains stopped, but starts from the beginning again? What about statements like ‘if we have examined the X’ - any way that I can reset the state of the game so it returns to thinking we haven’t examined X yet, without a restart?

If you need a reason, consider the case of trying to restart a game within a game, without affecting the state of the ‘meta-game’.

I don’t think there is a solution to this deficit currently. As a result of it, I have had to avoid ANY use in both my WIPs of syntax like ‘[stopping]’ or ‘if we have…’ or anything that depends on changes in game state that can’t be changed back.

If there is a way I’d love to know it so I could stop restricting myself to using only a subset of the language.

Well, one experiment you can run is the following for “one of/or”:

room 1 is a room.

when play begins:
say “[one of]test 1[or]test 2[or]test 3[stopping]”;

Compile the program. Then note the auto.inf file in the …/Build directory. Copy it to auto-3.inf or whatever.

Change the one line to:
say “[one of]test 1[or]test 2[stopping]”;

Then recompile and compare the auto.inf files. The difference in the code will tell you how to use inform 6 to reset things…I assume.

Similarly, I suppose you could run an experiment

room 1 is a room. the box is in room 1.

check examining the box:
if the box is examined:
say “Test phrase here.”;

Again, you can see the inform 6 phrase, what “if the box is examined” is, if you search for “test phrase here” and then use that to determine what to set.

I don’t know if you’ve worked with I6 within I7 before, but it’s a lot less sticky than it sounds.

That’s the problem with some specialization or customization that works 99% of the time–it spoils you for the 1% of the time you need to change things.

If I have the time to run these tests, I can show you what I think you can/should do, but I’m shaky with I6/I7 myself.

Thanks those are good tips. I might try that out. Hopefully it could lead to some fairly simple, repeatable ‘reset that variable’ syntax, because it would have to be at least as convenient as just declaring my own separate ‘X, Y, or Z has been examined’ variables, and ignoring the built-in ones, which is what I’m doing now. (As for ‘stopping’ - well, there’s really no simple solution to that besides creating custom ‘print cycling messages’ routines, which I essentially have done in complex cases - it’s where you just want a simple case that works that the irreversibility of it all annoys.)

Follow-up: (edited to note: posted, like, seconds after you posted :slight_smile: )

room 1 is a room.

when play begins:
    say "[one of]test 1[or]test 2[or]test 3[stopping]";

check examining the player:
    say "[one of]t1[or]t2[or]t3[stopping]" instead;

chapter reseting

reseting is an action applying to one thing.

understand the command "reset" as something new.

understand "reset [something]" as reseting.

carry out reseting:
    i6-reset;
    the rule succeeds.
    

to i6-reset: [resets play begins then examining player]
(-
    I7_ST_say_one_of-->1=0;
    I7_ST_say_one_of-->0=0;
-)

Now, you would need to write a for loop to clear everything more sensibly. And I don’t know how to do a SIZEOF command for an array in I6. But I think that is how resetting [one of] text can and should work.

For “if we have” I always used the workaround of

a thing can be examined or unexamined. a thing is usually unexamined.

after examining: now noun is examined.

(OK, I admit, I never knew about “if we have examined.”)

That allows us to say:

to reset-exam:
    now all things are unexamined.

This might be a bit of a pain if you want several actions, but examining is the big one. The I6 uses “TestActionBitmap” where I assume you can forcefully set many of the variables if you want, but I get lazy with I6.

1 Like

Cool, thanks Andrew. Would I have to look up every ‘cycling/stopping’ variable’s underlying i6 representation, or does this reset them all? (If I have to look up every one, would those designations change if I inserted more source code earlier in the document and then recompiled?)

EDIT: Reading a bit more carefully I think I understand that the variables need to be looked up one by one and that they are numbered in order, and therefore these numberings could maybe change on recompile. So it’s a bit fragile; it means I have to keep track of the numeric sequence of randomised statements throughout the game, and not fuck that up, or else face intractable bugs, but hey: it’s a solution where I didn’t think one was possible.

Yeah, unfortunately it’s not a full solution & I didn’t make that clear.

Unfortunately there’s also no way for I6 to “see” the I7 as it can for I7 labeled objects. For instance,

the box is a thing.

(-
print (+ the box +);
-)

So if you didn’t want to clear everything, it’d be a mess.

However, since the I6 source has this…

Array I7_ST_say_one_of --> 4;

You could always check for that. One problem here is that while I7_ST_say_one_of --> 0 gives the array size of strings, it doesn’t happen for integers.

It would be useful if the generated I6 code said

CONSTANT number_of_one_of = 4;
Array I7_ST_say_one_of --> number_of_one_of;

But it doesn’t. At least in 6G it doesn’t. Maybe someone here can show what I’m missing?

So I’m confused (but interested), but I’m glad to be able to help somewhat. Because I sort of had this question myself, and once someone else asked it, it got me thinking.

One possible solution you could use (which is a huge hack) is, if the first entries are unique, reset the arrays based on whether their first entry is identical to another array…but that is so much more to take care of.

Yes, the indexes into I7_ST_say_one_of are based on the order the phrases are compiled, so they’ll change as you edit the code. If you want to reset all the cycling messages, you can loop through the array (although knowing when to stop may be hard).

If you only want to reset some of them, you’ll probably need to redefine the phrases to make that easier; section 27.29 in Writing With Inform describes the tricks used to define the standard phrases. Here’s one approach:

  • Define a version of the message cycling phrase that takes a message ID argument, like [resettable message 123 one of]foo[or]bar[or]baz[repeating]. (You might need to come up with new names for “or” and “repeating”.)
  • In the definition, before printing anything, call a routine (CheckForReset) and pass in the message ID and the array index.
  • Define CheckForReset to set the array entry to 0 if the I7 code has requested to reset this message (e.g. I7 stores the requested IDs in a list, CheckForReset calls a rule to check the list).
3 Likes

I never knew this. Thanks so much! I’m going to have to reread that last section. I was always a bit worried they’d be totally arcane (I think I just glazed over after release options,) but this example clears things up.

Wow. How’s that for digging in the guts? Defining my own alternative in-string control structures? Like Andrew, I never knew that was in the manual, either. But now I do. Thanks for the info. I can see how learning how to do that could come in handy in all sorts of ways.

I will be back to check this forum again, in the morning.