Automatic hints not playing nice with other code

(Thanks to everyone who’s helped me on other stuff so far - I know these must seem like noob questions.)

I’ve got a point in my game where I’d like to automatically give a stuck player hints. However, I’m not having much luck getting these to play nice with other code.

So, for example:

The Laboratory is a room. The lab door is a locked door. The lab door is north of the Laboratory and south of the Resurrection Room. 

Using is an action applying to one thing. Understand "use [something]" as using.

The player carries an orb.

The wizard is a man in the Laboratory.

Instead of asking the wizard about something:
	say "'Hmm hmm,' he says, absentmindedly.";
	continue the action.

Hint-countdown is a number that varies. When play begins: now hint-countdown is 4.

Instead of going north from the Laboratory:
	say "The wizard looks up briefly and mutters some words, and you are thrown back from the door."

After doing anything other than using the orb:
	decrease hint-countdown by 1;
	continue the action;
	
After doing anything other than using the orb when hint-countdown is 1:
	say "Maybe something in your inventory will help.";
	continue the action;
	
After doing anything other than using the orb when hint-countdown is less than 1:
	say "[italic type]Type USE ORB.[roman type]";
	continue the action;

Before using the orb:
	now hint-countdown is 100000;
	say "The orb glows and suddenly the entire northern wall is gone!";
	continue the action;

Every turn:
	say "hint-countdown is [hint-countdown]";
	continue the action.

Here’s a sample readout:

I think the issue that I’m having is that my “instead” rules are meaning that the parser isn’t registering these actions as a “doing anything” that would decrease the countdown. However, adding “continue the action” statements or rephrasing as “carry out asking” results in nonsensical scenarios like the game reporting both that the wizard responds and that he does not respond, in the same turn. What do I need to do to make sure the countdown is counting down? Is there some kind of “return” equivalent that I’m missing?

It’s also mildly frustrating to me that, while I’m able to get special responses to print before the hint, the default responses (like “Time passes” or “Dropped”) are printing after. How can I fix this?

Thirdly, attempting to go north is not registering as a “doing anything” (with or without a “continue” statement), presumably on account of the door’s being locked, but I’d also like this to count towards the hint countdown.

I think you’ve made this harder than it needs to be. After rules are really for reporting an action and handling side-effects. Everything you’re trying to do can be done with an Every turn rule like:

Every turn:
	decrease hint-countdown by 1;
	if hint-countdown is 1:
		say "Maybe something in your inventory will help.";
	otherwise if hint-countdown is less than 1:
		say "[italic type]Type USE ORB.[roman type][line break]".

However, I’d be tempted to do it this way instead, sort of like Example 143 in The Inform Recipe Book:

[code]The orb can be hinted.
The orb can be used.

When play begins:
first hint is ready in three turns from now.

At the time when first hint is ready:
say “Maybe something in your inventory will help.”;
now the orb is hinted.

Every turn when the orb is hinted:
say “[italic type]Type USE ORB.[roman type][line break]”.

After using the orb:
now the orb is not hinted.
[/code]

Also, I think your “continue the action” lines aren’t needed are needed in the other rules. They should never be needed for Every turn rules, and for your Instead and Before rules, you don’t really want anything to happen afterwards. The Every turn rules will run regardless of whether the After rules stop or continue the action.

Thank you, it looks like your first suggestion took care of the countdown once it’s begun! I’m having the same issue with starting the countdown, though, which in my actual game is meant to be triggered by one of several events rather than the beginning of play or the entry to the room. For instance, I’ve written that going north is “futile behavior” (like the manual’s “unmaidenly behaviour”) that triggers the hint countdown, but unless I include the “continue” statement (which reports the player trying the door after being blasted back), the action doesn’t complete and start the countdown. How do I need to phrase this?

In the example, the countdown starts when play begins. Sounds like you want to delay the start until something happens?

If you’re sticking with the hint-countdown method, do something like:

The orb can be hint-pending.

When play begins:
   now hint-countdown is 999999.

Instead of going north from the Laboratory:
   say "The wizard looks up briefly and mutters some words, and you are thrown back from the door."
   if the orb is not hint-pending:
      now the orb is hint-pending;
      now the hint-countdown is 4.

Okay, so there’s no way to handle this other than by duplicating the code? (ie.

[code]Instead of going north from the Laboratory:
say “The wizard looks up briefly and mutters some words, and you are thrown back from the door.”
if the orb is not hint-pending:
now the orb is hint-pending;
now the hint-countdown is 4.

Instead of asking the wizard about something:
say “‘Hmm hmm,’ he says, absentmindedly.”;
if the orb is not hint-pending:
now the orb is hint-pending;
now the hint-countdown is 4.[/code]
)

I’d hoped to avoid such duplication by tagging these two actions as “futile behavior” and letting “futile behavior” trigger the countdown, but obviously if there’s no way to make that happen I’ll just duplicate.

You’re correct that you shouldn’t duplicate. Check out Chapter 11 of Writing With Inform.

To start the countdown:
   if the orb is not hint-pending:
      now the orb is hint-pending;
      now the hint-countdown is 4.

Instead of going north from the Laboratory:
   say "The wizard looks up briefly and mutters some words, and you are thrown back from the door."
   start the countdown.

Instead of asking the wizard about something:
   say "'Hmm hmm,' he says, absentmindedly.";
   start the countdown.

Thanks - I ended up starting the countdown in “Before” statements to avoid having a “start the countdown” event that wouldn’t fire under most “if” circumstances, but having a “to start the countdown” set of events works and if the “before” ends up leading me wrong then I’ll revisit this.

No worries, and good luck.

Be careful with Before, though. Sounds like your good in this example, but you’ll need to be careful they are aligned with your Instead/After statements, or you risk starting the counter but not carrying out the action that’s supposed to trigger the start.

Sorry, I don’t follow - could you clarify? (I’ve mostly been having the opposite problem!)

The issue is the risk of creating side effects before you decide on the action. Suppose you want a booby-trapped box with a delayed bomb that explodes after it’s opened.

Box is a container in location. It is openable and closed and locked. It has key red key.

Before opening box:
    box explodes in 3 turns from now;
    [or now the explosion-countdown is 3]

In this example, you start the countdown before Inform checks that the box can actually be opened. If the player doesn’t have the key, it will still start.

Since you’re triggering on things that the player is trying but failing, you can use before to catch and block the action as well as start a timer. But otherwise, you’ll probably want to start a timer only after you known the action has succeeded.

I see. In this particular case, I think it’s working out okay, but yes, I’m aware that for other situations it could be an issue.