Order of turn sequence rules (and some bragging)

Lost Items Version 3 is out!

eyeballsun.org/i/Lost%20Items.i7x

No guarantees that it’s bug-free, but it’s a major refactoring that incorporates what I’ve learned about the parser, and an idea I should have stolen from Aaron’s Smarter Parser a long time ago.

In fact, it’s so cool that I don’t even have to use Objects Matching Snippets any more. I’m using the built-in parser iteratively, as inspired by Smarter Parser - instead of printing a “you can’t see…” error right away, it aborts the turn and starts a new turn, this time with a flag to indicate that lost items should be added to scope.

However, there’s a minor snag. Noticing absence of lost items is something in between a parser error and an action now - it has access to a completely parsed action, but it doesn’t do anything except for output an error. But because it’s not done during the printing a parser error activity anymore, the turn sequence continues to advance, and every turn rules have a chance to fire, as well as the passage of time. You might argue that it’s not a bad thing, but I’d prefer to keep things the way the were before.

I thought this rule would take care of that:

[code]A turn sequence rule when we are looking for lost items (this is the halt the turn sequence after noticing absence rule):
Stop looking for lost items;
rule fails.

The halt the turn sequence after noticing absence rule is listed after the generate action rule in the turn sequence rules.
[/code]
But it doesn’t. I checked the index and I immediately saw the problem:

What I expected to happen was for the “halt the turn sequence rule” to appear immediately after the generate action rule, i.e. before the first anonymous (consider the scene changing rules) rule. Is there any way to force that order?

I kinda wanted to let the “setting action variables” rule run before noticing absence, but if I forget about that, I could just stick noticing absence in between the “parse command rule” and the “generate action rule.” What do you think?

Well, that idea didn’t work. It seems like the current action doesn’t exist yet after the parse command rule is done. That must happen somewhere within the generate action rule.

This is probably the simplest way to do this.

[spoiler][code]“Test”

Section 1 - The Improved Standard Rules (in place of Section SR2/8 - The Standard Rules in Standard Rules by Graham Nelson)

The little-used do nothing rule translates into I6 as “LITTLE_USED_DO_NOTHING_R”.

Include (-
[ LITTLE_USED_DO_NOTHING_R; rfalse; ];
-);

The start in the correct scenes rule is listed first in the startup rulebook. [6th.]
The position player in model world rule is listed first in the startup rulebook. [5th.]
The update chronological records rule is listed first in the startup rulebook. [4th.]
The seed random number generator rule is listed first in the startup rulebook. [3rd.]
The virtual machine startup rule is listed first in the startup rulebook. [2nd.]
The initialise memory rule is listed first in the startup rulebook. [1st.]

The virtual machine startup rule translates into I6 as “VIRTUAL_MACHINE_STARTUP_R”.
The initialise memory rule translates into I6 as “INITIALISE_MEMORY_R”.
The seed random number generator rule translates into I6 as “SEED_RANDOM_NUMBER_GENERATOR_R”.
The update chronological records rule translates into I6 as “UPDATE_CHRONOLOGICAL_RECORDS_R”.
The position player in model world rule translates into I6 as “POSITION_PLAYER_IN_MODEL_R”.

This is the start in the correct scenes rule: consider the scene changing rules.

The when play begins stage rule is listed in the startup rulebook.
The fix baseline scoring rule is listed in the startup rulebook.
The display banner rule is listed in the startup rulebook.
The initial room description rule is listed in the startup rulebook.

This is the when play begins stage rule: follow the when play begins rulebook.

This is the fix baseline scoring rule: now the last notified score is the score.

This is the display banner rule: say “[banner text]”.

This is the initial room description rule: try looking.

A first turn sequence rule (this is the every turn stage rule): follow the every turn rules. [4th.]
A first turn sequence rule (this is the first scene changing rule): consider the scene changing rules. [3rd.]
The generate action rule is listed first in the turn sequence rulebook. [2nd.]
The parse command rule is listed first in the turn sequence rulebook. [1st.]

The timed events rule is listed in the turn sequence rulebook.
The advance time rule is listed in the turn sequence rulebook.
The update chronological records rule is listed in the turn sequence rulebook.

A last turn sequence rule (this is the second scene changing rule): consider the scene changing rules. [3rd from last.]
The adjust light rule is listed last in the turn sequence rulebook. [2nd from last.]
The note object acquisitions rule is listed last in the turn sequence rulebook. [Penultimate.]
The notify score changes rule is listed last in the turn sequence rulebook. [Last.]

This is the notify score changes rule:
if the score is not the last notified score begin;
issue score notification message;
now the last notified score is the score;
end if.

The adjust light rule translates into I6 as “ADJUST_LIGHT_R”.
The advance time rule translates into I6 as “ADVANCE_TIME_R”.
The generate action rule translates into I6 as “GENERATE_ACTION_R”.
The note object acquisitions rule translates into I6 as “NOTE_OBJECT_ACQUISITIONS_R”.
The parse command rule translates into I6 as “PARSE_COMMAND_R”.
The timed events rule translates into I6 as “TIMED_EVENTS_R”.

The when play ends stage rule is listed first in the shutdown rulebook.
The resurrect player if asked rule is listed last in the shutdown rulebook.
The print player’s obituary rule is listed last in the shutdown rulebook.
The ask the final question rule is listed last in the shutdown rulebook.

This is the when play ends stage rule: follow the when play ends rulebook.

This is the print player’s obituary rule: carry out the printing the player’s obituary activity.

The resurrect player if asked rule translates into I6 as “RESURRECT_PLAYER_IF_ASKED_R”.
The ask the final question rule translates into I6 as “ASK_FINAL_QUESTION_R”.

The scene change machinery rule is listed last in the scene changing rulebook.

The scene change machinery rule translates into I6 as “DetectSceneChange”.

Section 2 - Game Code

A turn sequence rule (this is the special turn sequence rule): do nothing.

The special turn sequence rule is listed before the first scene changing rule in the turn sequence rules.

The Testing Room is A Room.[/code][/spoiler]

Hope this helps.

Indeed so. It runs during the “ActionPrimitive” function, which is in “actions.i6t”.

Why dont you have the rule run first in the action processing rules rather than listing it in the turn sequence rules? According to “ActionPrimitive” the setting action variables rulebook runs just before the action processing rulebook.

I would need to do both - there has to be a turn sequence rule that stops the turn sequence.

Thanks for the suggestion to replace the section in the Standard Rules. It seems a bit heavy-handed, but I think it’s reasonable from the point of view that those rules should have been given names in the first place.

You could try explicitly running the setting action variables rulebook, like so.

[code]A turn sequence rule when we are looking for lost items (this is the halt the turn sequence after noticing absence rule):
consider the setting action variables rulebook;
stop looking for lost items;
rule fails.

The halt the turn sequence after noticing absence rule is listed before the generate action rule in the turn sequence rules.[/code]

This way the setting action variables rulebook runs and the turn sequence rulebooks ends.

Hope this helps.

Thanks, another good idea there!

As far as principles go, what do you think is the right behavior? Should noticing absence be more like a parser error or more like an action failure? Should it be in a Before rule to allow other Before rules to override it? Should it not expect action variables to be set?

I have written code that sets non-action variables during “setting action variables,” so that multiple actions can use the same data. For example, in my hand-rolled version of player’s holdall behavior, I make sure every action marks its nouns as “not stowable,” so they are protected even if the action is redirected:

Setting action variables for doing something: If the noun is a thing, limit stowability of the noun; If the second noun is a thing, limit stowability of the second noun;

Is this an abuse - should I use a Before rule instead? I’m sure I had a reason not to do that, but I don’t remember what it was. And if it’s legitimate, how should Lost Items deal with it?

Would something like this work and be acceptable?

This is the halt the turn sequence after noticing absence rule:
	if we are looking for lost items:
		stop looking for lost items;
		rule fails.
   
This is the new generate action rule:
	consider the generate action rule;
	consider the halt the turn sequence after noticing absence rule;
	
The new generate action rule is listed instead of the generate action rule in the turn sequence rulebook.

Don’t you mean:

abide by the halt the turn sequence after noticing absence rule;

Rather than:

consider the halt the turn sequence after noticing absence rule;

otherwise the rule won’t stop anything.

You’d think that, given the name of the rulebook. However, Inform doesn’t really check this. The way I see it, the rulebooks pretty much do exactly the same thing regardless of their names. The only thing that’s special about the setting action variables rulebook is that it is called at a very early stage.

That said, it’s usually good practice to restrict the use of the setting action variables rulebook to setting action variables. The right behaviour that you mention is more like a set of guidelines, but one that is best followed.

That depends. If you really need a rule to run earlier than the before rulebook then go right ahead, it should be OK, otherwise you might as well use a before rule. Also, the setting action variables rulebook is “considered” rather than “abided by”, so any rules here won’t be able to stop thing outside the rulebook.

Come to think of it, there isn’t very much happening between the processing of the setting action variables rulebook and the before rulebook. So, if a before rule is too late, then the chances are a setting action variables rule would also be too late.

The most orthodox way do this would probably to add a rule at a really early stage would be to create a rulebook and have it run at the relevant point in the I6 code, like so.

ProcessRulebook((+ the name of the rulebook +));

It would require replacing chunks of i6 code, but it does have its advantages in the fact that you can fine tune its location to suit the purpose.

Hope this helps.

I’m not following the whole discussion, but if you want to stop the turn sequence rules after the generate action rule, you can set the I6 variable “meta” to true/1.

Quite!

That sounds dangerous - doesn’t meta change a whole bunch of things? I had the sense that it’s only ever set once during a turn, and pretty much everything depends on its value remaining the same.

On the other hand, its meaning is a good fit - noticing absence is like an action out of world.

This is taking me on a bit of a tangent… I had some issues with Object Response Tests because the object analyzing action is not out of world. It can’t be, because it triggers other in-world actions. But it also shouldn’t normally be affected by Before and Instead rules. Noticing absence seems like another one of these edge cases (and in a similar way to object analyzing, I think some of my “for noticing absence” rules try other actions).

Would it fit better as an activity?

I’m not sure what you’re referring to, Zarf. Object analyzing is the action in Juhana’s extension that is triggered by the command “analyze [something].” If I’m not mistaken, even if that were an out-of-world action that triggered an activity, the “meta” flag would still be on when that activity “tried” various actions, so they wouldn’t behave as they should.

As for noticing absence, it already is an activity.

Sorry, I did not look at the extension and misunderstood what the point was.

I think it should be safe to change in a carry out rule (for example). Once an action has been generated I don’t think the meta variable is used again,

Could you possibly set meta to false, run the other actions, then set it to true again? But it’s not a big problem if a debug command unnecessarily runs the before/instead/after rules.

Maybe not a big problem, but it was a problem - there was an instead rule that stopped some tests from running. I had to write an exception into the instead rule, and then figure out how to make the exception compile when I built the game for release.