Timing complex actions with after and report say commands

Consider a simple example…

[code]There is a room called the test room.

There is a container called the box in the test room. It is open, openable, not lockable.

There is a Jack in the test room.

After closing the box:
if the Jack is in the box:
say “Congratulations! You made your first toy Jr. Elf.”;
continue the action;

Test box with “close box / open box / put jack in box / z / close box”
[/code]

The problem is that the close report for the box occurs after the “say” command in the “after” rule

[code]>[5] close box
Congratulations! You made your first toy Jr. Elf.

You close the box.[/code]

I understand why this occurs but it is not the desired effect. This is how I have “fixed” this issue.

[code]After closing the box:
if the Jack is in the box:
The jack-timer expires in 0 turns from now;
continue the action;

At the time when the jack-timer expires:
say “Congratulations! You made your first toy Jr. Elf.”;[/code]

I get the desired results

[code]>[5] close box
You close the box.

Congratulations! You made your first toy Jr. Elf.[/code]

But the real issue, is there a good/standard way others are dealing with this timing issue without using a zero timer? I don’t particularly have an issue with my solution, but this would seem to be a common occurrence among games, so I thought someone else might have a more elegant solution.

Thanks!

I apologize for adding a question rather than answering yours, but what happens if the Congratulations message is moved to a Report or Carry out rule?

I don’t know if this would work, but I would normally put the message in a “Report closing the box” rule. If this still ends up in the wrong order (which I think it probably will because of rulebook ordering), I might try “Last report closing the box”, but messing with Last is pretty fragile.

It sounds as though you want both the standard “closing the box” report output plus the special message.

As you understand, the After closing rulebook processes before the Report closing rulebook, so placing the rule there will naturally cause its output to come first.

In a similar situation, I would tend to make use of the Every Turn rules, with a condition that watches for the completed toy state. Every Turn rules run after action processing is complete, so they won’t interfere with normal action output.

I’d put messages like this in a Scene.

[code]Preparation is a scene. Preparation begins when [something]. Preparation ends when the jack is in the box.

When preparation ends: say…[/code]

They prove very nice for checking solutions to puzzles.

Thanks for the quick replies. I want to update this issue a little as in the process of posting my question gave me ideas to try :wink: I over simplified the problem in my last post. The problem is that I have a puzzle that must be solved. A device must be switched on somewhere in the process, but not necessarily as the last step. So I need a place for all conditions to be checked before the puzzle is considered solved. I updated my code using an “Every turn” statement as this point. I also complicated my problem by trying to “help” the player when he forgets to open and close the box and so all the messages have to be output in the correct order.

This solution runs correctly. If someone has a more elegant solution, please chime in.

[code]There is a room called the test room.

There is a container called the box in the test room. It is open, openable, not lockable. The box can be activated. The box is not activated. The button is a device. The button is part of the box.

There is a Jack in the test room.

There is a spring in the test room.

Before inserting something into the box:
if the box is closed:
try opening the box;

Last report inserting something into the box:
if the spring is in the box AND
the jack is in the box:
try closing the box;

Last report switching on the button:
if the spring is not in the box OR
the jack is not in the box OR
the box is not closed:
say “Nothing happens.”;

Every turn:
if the spring is in the box AND
the jack is in the box AND
the box is closed AND
the button is switched on:
now the box is open;
say “Boing! The jack pops out of the box!”;
if the box is not activated:
say “Congratulations Jr. Elf, you made your first working toy!”;
now the box is activated;

Test box1 with “x box / close box / put spring in box / put jack in box / close box / switch button on”

Test box2 with “x box / put spring in box / close box / switch button on”

Test box3 with “x box / switch button on / put spring in box / put jack in box”[/code]

I have never used scenes, so I think I will read up and test that out. Seems like a more elegant solution. Thanks.

That makes sense. Not sure why I didn’t see it before. I reworked my solution and “every turn” works well. Thanks.

They’re good for this because the conditions are tested after all actions finish. Also I believe Inform optimizes them a bit more than every turn rules (so once this has happened it won’t keep checking for it every turn) though I’m not certain about that, it’s a part of the internal machinery I’m not too familiar with.

You’re welcome, but Draconis’s suggestion of scenes is better advice. His approach has the advantage of letting you easily detect the plot-relevant state for purposes such as, for example, having a boss elf periodically harass the player character until the toy is done. And it probably also makes for easier-to-read source code.

In terms of general advice, the if conditions you’re placing at the start of your various rules can also be placed in the rule’s “preamble”, e.g.

Last report switching on the button: if the spring is not in the box OR the jack is not in the box OR the box is not closed: say "Nothing happens."

would become

Report switching on the button when the spring is not in the box or the jack is not in the box or the box is not closed: say "Nothing happens." instead.

This allows I7 to automatically order the rules in the rulebook in a way that usually makes sense for your purposes. See WWI 19.6, 19.7 and 19.16. This ordering can be overridden, as well – see WWI 19.4. Writing them with empty preambles means they default to the same order in which they’re found in the source code (which is also sometimes handy).

As usual, great advice. I learn so much from the experienced authors monitoring questions on this site. I will start playing with rule preambles and scenes to stream line my code. Thanks again!