[I7] NPC Scope and the "Can See" check

I’m modifying the scope of hallways so you can see into other adjacent hallways. Doing it like this:

After deciding the scope when the location is a hallway:
	repeat with the other place running through rooms which are adjacent to the location: 
		if the other place is a hallway, place the other place in scope.

Works great for the player. You can examine things in the other hallways.

But I have some NPC logic that checks: if the npc can see the player but this seems to fail when the NPC and player are in adjacent hallways. Is there something else controlling the “can see” check? Something I need to override?

Can see is linked to the visibility relation, and changing the scope is indeed how you change that relation.

The problem that you’re having is because your rule operates relative to the location, which is the location of the player.

This means that the player can see the npc when the NPC is in an adjacent location to the player, but the npc can’t see the player, because the player is in the player’s location, not a location adjacent to the player (obviously!), and so your rule doesn’t put them into scope.

The simple thing is to always phrase your can see checks with the player first, since it should be a commutative relation anyway. But if you want to extend this so that you can do other things (such as checking if an NPC can see another NPC), you can rewrite your rule like this:

After deciding the scope of a person (called the actor):
	let the place be the location of the actor;
	if the place is a hallway:
		repeat with the other place running through rooms which are adjacent to the place: 
			if the other place is a hallway, place the other place in scope.

(Your original rule could cause other surprises, such as an NPC being able to see something in the hallway on the opposite side of the player – or on both sides of the player even if the NPC themselves were nowhere near the player.)

4 Likes

Ahhhhh yeah that was it. For some reason from the examples I just assumed the location was some variable in the deciding scope activity but it’s just a shorthand for the player location.

Thanks friend. It works now, finally.

1 Like

Just one small addition, for people who come across this thread in the future: “the actor” in I7 is also a variable referring to the person doing the current action. Inform doesn’t stop you from having multiple variables with the same name, even though it really should imo, and the results can be hard to predict. So if you get weird errors, change it to “the beholder” or whatever and see if that fixes it.

3 Likes

Kinda related so I didn’t want to make a new thread, but I’m having a related ish problem with concealment.

The PC has a pocket. I want to say that the contents of the pocket are concealed so NPCs can not see them, but in so doing, the PC now also can not see anything inside their own pocket. There doesn’t seem to be anything in the concealment rule to indicate who is doing the looking. I tried the actor but that made it angry.

EDIT: NM, misunderstood what you were trying to do!

I wonder whether you might want to just define a new NPC-centric visibility relation. I suspect trying to hack the default visibility and concealment rules might be more challenging than it’s worth…

1 Like

You would think that (and I did too at first), but as it turns out the actor is not actually a global variable; it only exists inside action-processing rulebooks. So in this context it’s an entirely separate variable that cannot possibly collide with the other one. (Hence I figured it was less confusing to use a familiar name for the concept. But yes, you can use whichever name you like.)

1 Like
Rule for deciding the concealed possessions of the pocket:
	if the person reaching is the player, no;
	yes.

Or you can write that all in one blob:

Rule for deciding the concealed possessions of the pocket when the person reaching is not the player: yes.

(If you want to get really fancy, this can be extended to allow other actors to also have pockets, where things are only visible to the respective owners of the pocket. That is left as an exercise to the reader.)

Often though it’s not really necessary to fully model the world from the point of view of any actor, since typically either only the player is doing actions at all, or NPCs are only doing simple actions. And it’s usually possible to handwave away the necessary checks some other way.

One example of such handwavery:

Definition: a thing is npc-invisible rather than npc-visible if it is in the pocket.
Definition: a thing is Bob-visible rather than Bob-invisible if it is npc-visible and Bob can see it.

And now you can make checks such as all Bob-visible things or if the watch is npc-visible, and put them just in the places where something needs to care about it.

4 Likes

Ahh okay, the person reaching was the rulebook variable I was missing.

Is there any… Reference? For things like variables available in each rulebook? Or is this all part of a great oral tradition and one day I’ll have to tell my kids about the person reaching so they can carry on making Inform games.

It is… not super easy, at least in my experience. What I usually wind up doing is turning on the RULES debugging command and trying to suss out from the output where the action is going wrong, then checking out the text of the standard rules to see if that sheds any light. And if that doesn’t work, random googling of the documentation can work (12.18 of Writing with Inform has some helpful info on “person reaching”, it looks like).

In this case I think it’s extra-hard because the rules are really set up with a bunch of player-centric assumptions that aren’t obvious – that’s why I suggested, and Gavin provided much more helpful examples of, defining your own definitions and relations so you can know exactly what’s going on.

1 Like

Well in this case, it’s in the Kinds Index → Values, which list the global variables in your game, (those from the standard rules, as well as the ones you’ve defined). The “person reaching” variable is listed in the “Used when ruling on accessibility” section.

As far as the temporary variables made in each rulebook, it’s best to just consult the standard rules themselves. What I did was just loaded up the standard rules into a word processor and then saved it as a pdf, which I can then search without fear of accidentally making changes.

2 Likes

Ah okay. I was looking just in the rules section. Didn’t realize that’s where the variables were. The Index is a really cool feature, I just wish it showed me a little more.

The person reaching is documented in §12.18. Changing reachability.

Unfortunately the docs have a tendency to mention things once and only once, and in this case don’t have any indication that it’s still valid to refer to this from the deciding the concealed possessions activity.

Honestly, I’m not even sure if this is the intended way to do it, or if it might break in a future version if the library is refactored. But it definitely does work in the current version. (It actually probably isn’t entirely intended – the reachability rules are called in a different context from the scope/concealment rules, although they are both broadly kinds of accessibility rules. But it just so happens that the way the code is currently translated, it ends up referring to the correct variable.)

Usually, when I can’t get a straight answer from the docs or the Index, I’ll resort to reading the standard library code, or even the generated I6 output. That’s actually how I verified this particular usage. :smile:

1 Like

The website said the last release of Inform was in 2015. I would think if an update was released after all this time, more than just this esoteric behaviour would break. But I have no idea what the dev plans and history are.

In theory it’s going through a complete refactor and will be open-sourced when that’s done.

2 Likes