Most effective way talking with a NPC who is in another room

Dear all,

I have been lurking for quite some time, and this month I am finally making my first serious attempt to write a game in Inform 7. Some people might roll their eyes about my question, but I must admit that I did not find a really satisfying answer here, the manual, the RB or anywhere else.

My current project is set in the recent past. Let’s say we have a prison cell. The cell for itself is a room and the player is inside. The prison guard, a minor NPC, is patrolling the hallway which is the room next to our cell. The player can hear his steps. Since hanging around in a prison cell and working out tricky escape plans can get boring after a while, we want to talk with him.

Now, I am considering two approaches:

  1. Since we are unable to see through the massive door and we can guess that the guard is outide, talking to the door would be my first option. Maybe I can make something like “Understand talking to the guard as talking to the prison cell door.” I thought of implementing this via Emily Short’s Inanimate Listeners. Does this work?
  2. Defining a rulebook that would allow to speak to people in adjacent rooms. I think there was an example somewhere in the forum for this.

What would you recommend?

I really appreciate your input.

You could nuke the standard rules that bar the player from talking to the guard.

First, you need to put the guard into scope (or else the parser won’t even understand references to him).

After deciding the scope of the player when the location is the cell: place the guard in scope.

Now tell Inform not to block attempts to speak to the guard. (You might not need all of these lines, but better safe than sorry.)

Rule for reaching inside the corridor when asking the guard about: allow access.
Rule for reaching inside the corridor when telling the guard about: allow access.
Rule for reaching inside the corridor when asking the guard for: allow access.
Rule for reaching inside the corridor when answering the guard that: allow access.

I have a somewhat similar situation in my current game, and I am using a solution along the lines of the one suggested by jrb. Also, and this is something you may already know, but I found it handy: before rules fire before the basic accessibility rule.

Thank you so much for the replies. This is a good example of thinking too much in one direction on my side. I think jrb’s approach is more elegant than my approach.

OK, so I hope it’s OK if I add a follow-up question to this post, seeing as my issue is on the same subject.

Basically, I have a similar situation, in that I want the player to be able to call to a character who is not in the location. I put this character in scope and that solved that problem. Of course, this means that the player can always refer to the character and target commands at the character that require visibility (like “examine”). I solved this problem by having a before rule to cut off all such attempts (basically, any action but calling to the character). Then I discovered that a lot of my existing rules for other actions hinge on said character being visible or not. I could change those conditions to “in the location,” but the adjacent location is also visible to the player, and the player can interact with this character when he is in that adjacent location. So my next idea is to make these two connected locations into one region and then use that in my conditions.

It’s just that this seems like a lot of jury-rigging to get around the ramifications of placing another character in scope all the time. Is this the best way to go about this, or is there another way to circumvent the problem of not being able to refer to a character who is not in scope?

Would it help to use the [any thing] grammar token (probably with a custom action), which doesn’t require the object to be in the location?

Remotely calling is an action applying to one visible thing. Understand "call [any thing]" as remotely calling.

Now at least your jury-rigging is restricted to this one action.

Hmm… I’m a little confused. Perhaps I am misunderstanding what that line does, but does it still not require the NPC to be in scope? My problem is that I have a lot of rules that rely on the NPC being visible, and these are triggered all the time when I put the NPC in scope.

To give a quick example, we start in the Dining Room, which is west of the Kitchen, which is in turn south of the Backyard. There is no wall between the Dining Room and the Kitchen, so they are both in scope (e.g., when the player is in one, the other is in scope). However, no one can see from the Dining Room or the Kitchen to the Backyard, and vice versa. Mom is currently in the backyard engaging in horticulture, so the player can’t see her and she can’t see the player.

There are a number of actions that are grouped under “being naughty”: dancing on the dining room table, putting the family dog in the chandelier, etc. If one of these actions happen in the Kitchen or the Dining Room and Mom is in one room or the other, she will scold the player. So we write a rule like this:

After being naughty while Mom is visible, say "Mom glares at you with her hands on her hips: 'Jeremy Percival Jones, you stop that right this instant!'"

And everything is peachy… until we want to implement a verb to call Mom while she is in the Backyard (or elsewhere in the house that is not in scope). In order for the player to even be able to refer to Mom in the first place, she has to be in scope, and that breaks the above behavior. Now Mom will scold poor Jeremy if he waters the marigolds with Gatorade no matter where she is, even if she is down the street at the market buying eggs.

Now, I suppose we can fix this by making the Kitchen and the Dining Room a single region, and then using “while Mom is in the Family Area”, but what if we have many such areas? Say the Backyard is visible from the Side yard, and vice versa–what do we do when Jeremy starts lopping off the tops of the chrysanthemums with a two iron?

It seems to me that I would have to work in more and more exceptions as things progress, all for the sake of allowing the player to call Mom when she is not in the immediate vicinity. I was just wondering if it is possible to allow the player to refer to an NPC that is not in scope, or if there is some easier way here that I am not thinking of.

The token [any thing] puts everything in scope for the purposes of that particular action. So CALL MOM would work regardless of where Mom is, and you don’t have to manually mess around with scope.

One caveat is that depending on how extensive your game is, you might want to be careful about how you use the [any thing] token, since it literally treats every thing in the game as in scope. This can lead to disambiguation problems if you have a lot of similarly named objects (CALL ROSE - “Which do you mean, Rose, the rose, the rose garden, or the rose-colored glasses?”)

You can get around this by narrowing the scope of the grammar token. Use [any person] instead of [any thing], for example; or create the adjective “callable” and use [any callable thing].

Another way of thinking about this is that “[any thing]” doesn’t bother with scope at all.

When you have a line like this:

Understand "call [something]" as calling.

then when you type CALL GUARD, the parser will try to match “GUARD” against all the things in scope.

But when you have a line like this:

Understand "call [any thing]" as calling.

then when you type CALL GUARD, the parser will try to match “GUARD” against all the things in the model world, whether or not they’re in scope. And since you haven’t actually put the guard in scope, you don’t need to worry about visibility.

One thing to keep in mind is that when you use the “[any thing]” or “[any person]” token, parser errors like “CALL PRISONER” when there’s no object named “prisoner” will give the error “That noun did not make sense in that context” rather than “You can’t see any such thing”–this is generally considered a fairly annoying error message. So you might want to change it somehow.

So the answer to my question is that, yes, I did in fact misunderstand what that line does. :slight_smile:

Thank you both for the clarification (and to jrb for the correct solution in the first place!).

[Edit: Just implemented this, and it works like a charm!]

OK, I’m posting this here because it is still relevant to the topic.

I got the above working fine, and everything was going great until I tried speaking to the NPC while on a bed in the room next to the room the NPC was in. So:

[Room #1 (supporter)] - [Room #2]

Doing this triggers the “reaching into a room” rule, which confused me at first, since Room #2 is in scope. Then I looked at the Standard Rules and saw that asking/telling apply to one thing and one topic–that is, one touchable thing, as opposed to one visible thing. Which is why the basic accessibility rule is being triggered. My first thought was to try to change the commands so that they would apply to “one visible thing” instead, but I couldn’t seem to get that to work. I kept getting an error (sorry, “problem”) on compiling, telling me that I should make a new action and then change the grammar to use that new action instead. So I did, or at least I tried to, but couldn’t get that working, either. I’ve tried everything I can think of, but I cannot figure out what I’m doing wrong.

So, what’s the solution here? Is it possible to change the Standard Rules? If not, how does one go about creating a new action and rerouting commands to that. I tried to take a look at some extensions to see how they did it, but the grammar they used does not work for me. I feel like I’m missing something here, but I can’t quite figure out what it is. It seems as if, no matter what I try, I am unable to get to that part that specifies the target of the command as touchable rather than visible. I really did want to figure this one out for myself, but I’m kind of tired of banging my head against the wall.

I await your elegant and blindingly obvious solutions, and thank you in advance.

The “Before” rules fire before the accessibility rules, so you could use them to reroute asking about to your new action on one visible thing:

[code]Remotely asking it about is an action applying to one visible thing and one topic.

Before asking someone about something: try remotely asking the noun about the topic understood instead.[/code]

You’d have to write rules like this for each such action, and this would bypass the default rules that print “There is no reply” for asking someone about something, so you’d need rules for those too. (It’s nice to have them, anyway.)

You could also try making reaching inside/reaching outside rules that apply specifically to these actions:

Rule for reaching inside when asking about: allow access. Rule for reaching outside when asking about: allow access.

You can even use a kind of action to make this work for a bunch of actions at once:

[code]Asking someone about something is speaking. Answering someone that something is speaking. Telling someone about something is speaking.

Rule for reaching inside when speaking: allow access.
Rule for reaching outside when speaking: allow access.[/code]

For rerouting the command directly to the action, so “ASK GUARD ABOUT MAGAZINE AND KEYHOLE” gets mapped directly onto the action of remotely asking the guard about the magazine and keyhole, you have to use something like

Understand the command "ask" as something new.

or

Understand nothing as asking. [not entirely sure about the correct syntax there]

to zap all the old Understand lines for “ask,” and then rewrite them for your new command. (See Writing with Inform §17.3.) But in this case there are more convenient ways to do that.

Thanks once again, matt!

Of the three solutions you proposed:

  1. Rerouting using before rules

This was what I tried after I failed to replace the Standard Rules with new commands, but I think I got the grammar wrong; specifically, I didn’t know the wording for “the topic understood”, and that was tripping me up.

  1. Reaching inside/outside rules

This is probably the best solution, and I don’t know why I didn’t think of this, especially when I just used similar rules to solve another problem. facepalm

  1. This is what I originally tried, starting with ‘Understand the command “ask” as something new.’ Unfortunately, I could not get this to work. Whenever I tried to then redefine the actions, the compiler kept spitting out problems, telling me that the actions already existed. It would be nice to understand exactly why it didn’t work, but if I can get the reaching inside/outside rules to work (and I imagine I will), I’ll settle for that for now.

It sounds like you did something like this:

[code]Lab is a room. [just so this will compile]

Understand the command “ask” as something new.

Asking it about is an action applying to one visible thing and one topic.

Understand “ask [someone] about [text]” as asking it about.[/code]

The problem is that the “Understand… as something new” line rips up all the Understand line for “asks”–but it doesn’t affect the asking it about action. It’s as though you’d deleted the lines from the Standard rules that say something like this:

Understand "ask [someone] about [text]" as asking it about.

but you still have the lines that define the action, like this:

Asking it about is an action applying to one thing and one topic.

So when you try to define asking it about again, Inform complains. The solution is to give your new action a different name:

[code]Lab is a room. [just so this will compile]

Understand the command “ask” as something new.

Remotely asking it about is an action applying to one visible thing and one topic.

Understand “ask [someone] about [text]” as remotely asking it about.[/code]

and it will work. (The asking it about action is still there–there’s no way to get rid of it as far as I know, short of replacing the part of the Standard Rules that defines it–but as long as there aren’t any commands that actually invoke it, that should be fine.)

As you said, this isn’t the easiest solution in this case anyway! But it’s worth clearing up for future reference.

Thanks for clearing that up, matt. You were spot on with what I was getting wrong.

Your explanation is basically what the problem message was trying to tell me, but somehow it wasn’t getting through. I guess that’s what I needed to know: that there is no getting rid of the original action. Everything else makes sense now.

Slowly but surely, my understanding of I7 is growing. :slight_smile: