Hypothetical Object Response Tests?

I now have in place a set of shell scripts that run tests in my WIP and test their results against a set of blessed transcripts, thereby freeing me from the hopeless tangle of the Skein. But now that I have a bunch of manually created tests, I’m looking for the next step to automate…

I’ve been thinking about using Object Response Tests. I could go to several critical points in the game and do a full ANALYZE ALL, but I think too many actions in my WIP would change the game state enough to make that very useful as it’s implemented. However, if I could throw an “undo” in after each action, it could be a real powerhouse. It seems like it would be pretty straightforward using Hypothetical Questions. Has anyone else tried combining these extensions before?

I haven’t heard of any such attempts, but if someone manages to get it done I’d be very interested in adding that functionality to the extension.

Another approach would be to save the game and then restore after each test or round of tests. You could adapt the save code from Alternative Permadeath to this end pretty darn quickly, by changing these two rules so that save and restore happens when you need it to:

[code]
Before reading a command when roguelike mode is true (this is the automatically save before input rule):
write game data to the file of save data;
continue the action.

When play begins when roguelike mode is true (this is the restore when play begins rule):
if the file of save data exists:
read file of save data into memory.[/code]

That sounds good, Erik.

I managed to do the undo pretty quickly by doing a search-and-replace on Object Response Tests.

[code]This is the output hypothetical results rule:
say the hypothetical output;

This is the test taking rule:
announce tests for “taking [the noun]”;
hypothetically try the test-actor trying taking the noun and consider the output hypothetical results rule.

[etc][/code]

It’s hacky, since you can’t wrap the entire test in a hypothetical - or perhaps you can?

Anyway, Alternative Permadeath sounds better suited to the task. I hadn’t realized it could work that way.

Yeah, my goal in writing the save-restore code in Alternative Permadeath was to provide an author-controlled interface for save/restore. I chose roguelike style save-restore as the implementation because it was easy–those two rules I called out above describe the whole of the roguelike save model–but I was really after the layer than enables it. If I ever do any more with it, it will probably be to implement a save-slot system, with one save file for each slot.

I guess the question is whether you can protect some data from the restore, so you can continue looping through tests.

Upon review, I’ve decided that Hypothetical Questions is actually the one I want here. At first I thought you could only run a single action hypothetically, but you can actually run any phrase, not just a “try” phrase. So my extensive search-and-replace was unnecessary, and big chunks of action can be done hypothetically (although you’ll need to reserve a very large buffer for hypothetical output).

[spoiler][code]Version 1 of Hypothetical Object Response Tests by Mike Ciul begins here.

“Tests objects just like Juhana Leinonen’s extension, but does an UNDO after each test.”

Include Hypothetical Questions by Jesse McGrew.
Include Object Response Tests by Juhana Leinonen

Book 1 - Hypothetical Output

This is the output hypothetical results rule:
say the hypothetical output;

Book 3 - Actions - Not for release (in place of Book 3 - Actions - Not for release in Object Response Tests by Juhana Leinonen)

Object-analyzing is an action applying to one visible thing.

Understand “analyze [something]” as object-analyzing.
Understand “analyse [something]” as object-analyzing.

Carry out object-analyzing (this is the go through all analyzing rules rule):
repeat with x running from 1 to the number of rows in the table of analyzing actions:
hypothetically follow the testing rule in row x of the table of analyzing actions and consider the output hypothetical results rule.

All-encompassing analyzing is an action applying to nothing.

Carry out all-encompassing analyzing (this is the analyze everything in the location rule):
repeat with x running through things enclosed by the location of the test-actor:
if the test-actor can see x:
try object-analyzing x.

Understand “analyze all” as all-encompassing analyzing.

Test-verb-trying is an action applying to one topic.

Understand “try [text]” as test-verb-trying.

Check test-verb-trying (this is the unknown verb test label rule):
if the topic understood is not a topic listed in the Table of analyzing actions:
say “Unknown verb test.” instead.

Carry out test-verb-trying (this is the repeat an action with all objects rule):
if the topic understood is a topic listed in the Table of analyzing actions:
repeat with x running through things enclosed by the location of the test-actor:
if the test-actor can see x:
change the noun to x;
hypothetically follow the testing rule entry and consider the output hypothetical results rule.

Test-actor changing is an action out of world applying to one visible thing.

Understand “actor is [any person]” as test-actor changing.

Carry out test-actor changing (this is the change testing actor rule):
change test-actor to the noun;
say “Object Response Tests now uses [the noun] as the actor.”

Hypothetical Object Response Tests ends here.

[/code][/spoiler]

It might be more orthogonal to have a switchable “hypothetical mode” in which all commands are automatically undone at the end of the turn. I haven’t quite figured out which extension should be used for that, or how.

I guess keeping track of loop variables with Alternative Permadeath isn’t that hard after all - you can save at any point in the turn, not just before reading a command:

Carry out object-analyzing (this is the go through all analyzing rules rule): repeat with x running from 1 to the number of rows in the table of analyzing actions: write game data to the file of save data; follow the testing rule in row x of the table of analyzing actions; read file of save data into memory;
The tradeoff, then, is whether we need an external file for savegame data, or a very big buffer for output data.

Ah, and now I understand your earlier questions, which I admit that I wasn’t really able to make sense of before seeing that you were making that assumption.

I extracted the necessary Glulx code from Hypothetical Questions, removing the output buffering. Now I have the best of both:

[spoiler][code]Version 1 of Hypothetical Object Response Tests by Mike Ciul begins here.

“Tests objects just like Juhana Leinonen’s extension, but does an UNDO after each test.”

Include Object Response Tests by Juhana Leinonen

Book 1 - Triggering Undo From I7

save-restore status is a kind of value. failure to save, successful save, and successful restore are save-restore statuses.

To decide which save-restore status is result of saving undo state: (- Save_Undo_State() -).

To decide whether successfully saved undo state: Decide on whether or not the result of saving undo state is successful save.

To restore undo state: (- Restore_Undo_State(); -).

Include (-

Constant FAILURE_TO_SAVE = 1;
Constant SUCCESSFUL_SAVE = 2;
Constant SUCCESSFUL_RESTORE = 3;

! returns 1 when entering the hypothetical universe, 2 when returning to reality, 0 if entering failed in the first place
[

Save_Undo_State rv;
! Not sure if any of these settings are necessary…

! do { @random 0 seed; } until (seed ~= 0);
!@getstringtbl strtbl;
! @getiosys iosys iorock;

@saveundo rv;

!@setrandom seed;
!@setstringtbl strtbl;
!@setiosys iosys iorock;

switch (rv) {
	0: return SUCCESSFUL_SAVE;
	1: print "[This game requires an interpreter with undo support.]^"; return FAILURE_TO_SAVE;
	-1: return SUCCESSFUL_RESTORE;
}

];

! consider a rule, protect its result, and restore the state saved by Hypo_Start
[ Restore_Undo_State rv;
@restoreundo rv; ! never returns if successful
print “[What happened to my undo state? --hypo]^”;
];

-)

Book 3 - Actions - Not for release (in place of Book 3 - Actions - Not for release in Object Response Tests by Juhana Leinonen)

Object-analyzing is an action applying to one visible thing.

Understand “analyze [something]” as object-analyzing.
Understand “analyse [something]” as object-analyzing.

Carry out object-analyzing (this is the go through all analyzing rules rule):
repeat with x running from 1 to the number of rows in the table of analyzing actions:
if successfully saved undo state:
follow the testing rule in row x of the table of analyzing actions;
restore undo state;

	[if the result of saving undo state is:
		-- successful save: follow the testing rule in row x of the table of analyzing actions;
		-- successful restore: next;
		-- failure to save: stop the action;]

All-encompassing analyzing is an action applying to nothing.

Carry out all-encompassing analyzing (this is the analyze everything in the location rule):
repeat with x running through things enclosed by the location of the test-actor:
if the test-actor can see x:
try object-analyzing x.

Understand “analyze all” as all-encompassing analyzing.

Test-verb-trying is an action applying to one topic.

Understand “try [text]” as test-verb-trying.

Check test-verb-trying (this is the unknown verb test label rule):
if the topic understood is not a topic listed in the Table of analyzing actions:
say “Unknown verb test.” instead.

Carry out test-verb-trying (this is the repeat an action with all objects rule):
if the topic understood is a topic listed in the Table of analyzing actions:
repeat with x running through things enclosed by the location of the test-actor:
if the test-actor can see x:
change the noun to x;
if successfully saved undo state:
follow the testing rule entry;
restore undo state;

Test-actor changing is an action out of world applying to one visible thing.

Understand “actor is [any person]” as test-actor changing.

Carry out test-actor changing (this is the change testing actor rule):
change test-actor to the noun;
say “Object Response Tests now uses [the noun] as the actor.”

Hypothetical Object Response Tests ends here.[/code][/spoiler]

I think I’ll create some mode settings to allow the player to choose between ORT’s default behavior, undo for individual action tests, and undo for entire tests. Any suggestions for naming the commands?

Maybe:

autoundo off
autoundo actions
autoundo turns

Done. (well, not finished, but implemented…)

eyeballsun.org/i/Autoundo%20for% … 0Tests.i7x

And I’ve added a new mode!

Now

autoundo freeze

will automatically undo the entire turn after every single command - so you can go to a certain point and try lots of different things from that point, even without using Object Response Tests.

Oooooooh. Aaaahhhhhh.

No, really, that’s pretty awesome.

Glad you like it! It was a major headache to figure out how to do it - my head is not good at tracking the stuff that goes on during save/restore operations. But I was so pleased when it finally worked!

Please have a look at it and tell me how it works. I simplified a lot of stuff that I copied from Hypothetical Questions. I don’t know if I went too far - it looked like he was doing something with the random number seed and a couple other state variables, and I wasn’t sure what the purpose was. If I need to put those lines back, let me know…

The purpose of those lines is to restore any changes made by the hypothetical code to the random number generator, string decoding table, or I/O system, which aren’t part of the Glulx undo state. You may as well uncomment them, although it might not make a difference in this case.

Without those lines, HQ can’t give a good answer to questions like “what number would come up if I spun the roulette wheel now?”, because the real spin won’t land on the same number as the hypothetical one anyway. It will also leave the game in a bad state if the hypothetical changes the string table or I/O system, although that’s unlikely. Also, if the hypothetical makes changes to the Glk state (opening files or windows, etc.), those won’t be rolled back either way.

If you don’t mind, I will uncomment those lines, but add your post as a comment.