Implicit action succeeding but preventing outer command from success?

I have two things I want to happen, first when the player opens a door, and next when the player goes through the door. Currently I have written this as a narrate opening rule for the first event, and inside a (select)...(or)(stopping) in the look query for the second event.

Unfortunately, most any player would just go through the door, which implicitly triggers the door-opening action, and, as far as the player is concerned, makes both events happen at the same time. This is a little overwhelming, so I would like the first event (triggered by the door-opening) to cancel the door-entering if that has been requested, making the player confirm their movement request before triggering the second event. I don’t quite know how to do that.

This is where I would write how I have thought about doing it, but none of the ideas I have are particularly clear in my mind – nor very clean. (I can trap door opening with a perform rule, but then I’m not sure how to stop the PC from entering the door aside from just not opening the door, but I want the door to be opened. I can trap the movement with a prevent rule on leave, but that rule triggers only after the implicit door opening, and there’s no clear condition on which to then allow the movement again, because by the time the prevent rule for leave is consulted, the door will have opened. Any prevent rule on go has similar effects as leave. I could put an any key query in the narrate opening rule to force a pause, but it still seems a little stilted and mistimed.)

The best I have come up with is

(prevent [leave #room #dir])
    (select)(or)(fail)(stopping)

but the problem with this is it stops the movement once even if the door was opened separately, unless the door-opening also results in an attempt to leave, but it gets complicated!

1 Like

can you give a quick sample transcript of what you want? i’m having a hard time picturing it.

1 Like

Maybe not a great example, but this is sort of sequence that inspired me:

Lab corridor
The strong metal door to the south looks important.

> open door
You turn the wheel to release the door from its sturdy
frame, and when you pull gently at the door, it flings
open with a terrible force. The gust from the other
side blows your cap off.

> south
You walk south through the strong metal door.

Wind tunnel
You tentatively enter the room, and as soon as you're
fully inside it, another gust blows you to the far east
end of the room, where you are trapped against a metal
grid.

This is what will likely happen, because a lot of players probably rely on implicit door-opening:

Lab corridor
The strong metal door to the south looks important.

> south
(first attempting to open the strong metal door to the south)
You turn the wheel to release the door from its sturdy
frame, and when you pull gently at the door, it flings
open with a terrible force. The gust from the other
side blows your cap off.

You walk south through the strong metal door.

Wind tunnel
You tentatively enter the room, and as soon as you're
fully inside it, another gust blows you to the far east
end of the room, where you are trapped against a metal
grid.

There is nothing strictly wrong with this, but I feel like it would be fair to players to offer the choice of not going through the door when the alarming thing has happened.

I.e. something like this would be ideal:

Lab corridor
The strong metal door to the south looks important.

> south
(first attempting to open the strong metal door to the south)
You turn the wheel to release the door from its sturdy
frame, and when you pull gently at the door, it flings
open with a terrible force. The gust from the other
side blows your cap off.

The sudden wind halts you in your tracks.

Lab corridor
There is an intense howling coming from the open strong
metal door to the south.

I have gotten something to work now, which is

#strong-door
(before [go #south])
    (* is closed)
    (#wind-tunnel is unvisited)
    (#player is #in #corridor)
    (first try [open *])
    (stop)

This re-creates the first try open behaviour from the standard library except (a) it stops action processing after doing that, and (b) it only triggers in the specific circumstance where this is the first time the door is opened… ish. But it still doesn’t seem like a clean solution and I feel like I’m missing something.

My main concern with this solution is that it is both too general and too specific at the same time. What if I change the direction of the door from south? What if there’s a different way to request movement in that direction that is not [go #south]? What if I rename the #corridor object? Etc. This could be solved with additional queries but it gets quite heavy for accomplishing something conceptually simple.

1 Like

something like?

(before [open $strongMetalDoor)
     \(first attempting to open the strong metal door to the south)\ (line)
     You turn the wheel to release the door from its sturdy
     frame, and when you pull gently at the door, it flings
     open with a terrible force. The gust from the other
     side blows your cap off.
     (par)
     The sudden wind halts you in your tracks.
     (tick)(stop)

you would want to put some kind of flag in to allow opening the door under other conditions.

you could also create a door that isn’t a (door $) and, therefore, won’t automatically respond to the implicit open. you would then do everything “manually” which, at least, gives you control over everything.

EDIT:
ah, as i was typing you did something similar already.

1 Like

So far the best I have is a combination of our solutions. Instead of having the event happen in a narrate opening rule I’ve changed to an after [open *] rule, something like (with additional logic to determine whether the cap is in a position to be blown off):

(after [open *])
    (#wind-tunnel is unvisited)
    You turn the wheel to release the door from its sturdy
    frame, and when you pull gently at the door, it flings
    open with a terrible force. The gust from the other
    side blows your cap off.
    (par)
    The sudden wind halts you in your tracks.
    (tick) (stop)

Something about (stop) makes me uneasy – it seems like a very low-level hammer to reach for – but maybe it’s appropriate in this case.

4 Likes

the (stop) would be appropriate. you may want a (tick) as well so that a turn goes by with the door opening, even if the [go $] that triggered the opening was aborted.

you may want a (tick) as well so that a turn goes by with the door opening

(first try [open *]) would (tick) for me, since this is an after query, right?

Edit: Apparently not if I (stop)! Thanks.

Don’t worry, (stop) is an entirely reasonable tool to use here! It’s meant to be used any time a sequence of actions should be interrupted—any time a (prevent $) rule succeeds, for example, it calls (tick) (stop).

2 Likes

Indeed, the language manual even states this very situation as an intended use case of (stop), in chapter 4 under stoppable environments:

For instance, TAKE ALL may result in several actions being processed, one at a time. If taking the booby-trapped statuette triggers some dramatic cutscene, the code for that cutscene can invoke (stop) to prevent spending time on taking the other items.

I had a feeling in the back of my head I had read this in the manual, but I was looking for it in the library manual rather than the language manual so I didn’t find it before I asked the question.

2 Likes