[I7] Something Done When Player Can See or In Presence Of

I’m modifying some examples from the Inform 7 recipe book. I have the following:

The Lab is a room.

Kitty Pryde is a woman in the Lab.

The Undertomb is a room.
It is down from the Lab.

A thing can be secret or obvious.
A thing is usually obvious.

Cain Marko is a man in the Lab.
Cain Marko carries a quantity of plastic explosive.
The quantity of plastic explosive is secret.

Kitty Pryde carries a laptop bag and a microfilm.
The microfilm is secret.

Rule for deciding the concealed possessions of something:
	if the particular possession is secret, yes;
	otherwise no.

Instead of examining someone:
	say "[The noun] is openly carrying [a list of unconcealed things carried by the noun]."

The player carries the vision glasses.
The vision glasses are wearable.

Instead of wearing the vision glasses:
	now the player wears the vision glasses;
	say "Nothing seems to happen."

Instead of wearing the vision glasses when the player can see anyone who is concealing something:
	now the player wears the vision glasses;
	say "The glasses feel warm. Immediately you can see [a list of things which are concealed by people who can be seen by the player]."
	
After printing the name of a thing (called the item) which is carried by someone while wearing the vision glasses:
	say " (carried by [the holder of the item])"

Test secrets with "examine Kitty Pryde / examine Cain Marko / wear glasses / take off glasses / down / wear glasses".

This is a slightly modified version of the example “Interrogation”.

The idea here is that I would expect the last command in my test script (“wear glasses”) to provide a different response (“Nothing seems to happen”) than it does, given that the player has moved to another room where Kitty Pryde and Cain Marko are not. But instead here is the transcript:

Notice at [6] the same response occurs as at [3]. But the rule that is being followed there is “Instead of wearing the vision glasses when the player can see anyone who is concealing something:”. Yet at that point the player has moved down [5] and Kitty Pryde and Cain Marko cannot be seen.

This happens even if I change the rule to:

Instead of wearing the vision glasses in the presence of someone who is concealing something:

It seems that my understanding of and/or implementation of scope is a bit off, but I’m not seeing what I’m doing wrong here.

That said, the same problem seems to occur in “Interrogation” example from the manual as well. Specifically, if you add a new room to that example, go to it, and then “wave the wand”, you get the same effect that I’m seeing.

I think the issue here is with the concealment relation, or the various forms of the verb “conceal.” If you run a command to print the list of things concealed by the player, at any point, it gives you the microfilm and plastic explosive.

I’m not quite sure why this is, but it seems as though the “concealed by” relation can relate people to things they don’t hold, while the “concealed” property as defined in the Standard Rules:

The verb to conceal (he conceals, they conceal, he concealed, it is concealed, he is concealing) means the concealment relation. Definition: Something is concealed rather than unconcealed if the holder of it conceals it.

seems to specifically refer to concealment by the holder, which may prevent some weird results. (Honestly I can’t figure out where the concealment relation gets calculated at all.)

So I think what is happening is that the wrong rule is firing because the player is visible, and the player counts as concealing the microfilm and explosives.

Anyway I think this can be solved by defining a new relation that holds when someone is concealing something that they are the holder of, and I also defined an adjective for people who are concealing something that they are the holder of, because that makes the rule easier to write. Here’s what I have, with the debugging rule that shows you what the player is considered to be concealing:

[code]The Lab is a room.

Kitty Pryde is a woman in the Lab.

The Undertomb is a room.
It is down from the Lab.

A thing can be secret or obvious.
A thing is usually obvious.

Cain Marko is a man in the Lab.
Cain Marko carries a quantity of plastic explosive.
The quantity of plastic explosive is secret.

Kitty Pryde carries a laptop bag and a microfilm.
The microfilm is secret.

Rule for deciding the concealed possessions of something:
if the particular possession is secret, yes;
otherwise no.

Instead of examining someone:
say “[The noun] is openly carrying [a list of unconcealed things carried by the noun].”

The player carries the vision glasses.
The vision glasses are wearable.

Instead of wearing the vision glasses:
now the player wears the vision glasses;
say “Nothing seems to happen.”

Instead of wearing the vision glasses when the player can see a shifty person:
now the player wears the vision glasses;
say “The glasses feel warm. Immediately you can see [a list of things which are hidden by people who can be seen by the player].”

After printing the name of a thing (called the item) which is carried by someone while wearing the vision glasses:
say " (carried by [the holder of the item])"

Test secrets with “examine Kitty Pryde / examine Cain Marko / wear glasses / take off glasses / down / wear glasses”.

True concealment relates a person (called X) to a thing (called Y) when X is the holder of Y and X conceals Y. The verb to hide means the true concealment relation.
Definition: A person is shifty if it hides something.

Every turn:
say the list of things concealed by the player;
say line break;
say “The player does [unless the player conceals the microfilm]not [end if]conceal the microfilm.”;
say the list of things hidden by the player;
say line break;
say “The player does [unless the player hides the microfilm]not [end if]hide the microfilm.”[/code]

I believe the problem is with the “deciding the concealed possessions of something” activity. Apparently there is no built-in check that the particular possession is actually a possession.

The Chamber is a room.

Mike is a man in the chamber. Mike holds the revolver. 
Rule for deciding the concealed possessions of Mike: yes.

Instead of examining Mike: 
	say "Mike is carrying [a list of things concealed by Mike]."

X MIKE produces

That might be worth reporting as a bug, when inform7.com is back up.

Great analysis, all. I’m in process of implementing Matt’s suggestion, but then I’m curious: even assuming the bug about concealed items, does this explain why the problem manifests even when the NPCs are not in scope?

The say statement in the rule in question is:

say "The glasses feel warm. Immediately you can see [a list of things which are concealed by people who can be seen by the player]."

Even given the issue with concealed, that last part is still “by people who can be seen by the player”. And in my step [5] I went to a room where the people were not present.

The player is still a visible person and all those things are evaluated as being concealed by him.

ETA: Also, I’m afraid that this probably means that code like this is going to get inefficient–it seems like the Deciding the concealed possessions of a person activity might run for every single thing in the game world, which means that a line like “If the player can see a person who conceals something” (or truly conceals something) might run once for every visible person and for everything in the game world… might get messy. I guess you should see if there’s a slowup and if there is you could try writing a phrase that loops over the player’s possessions and then checks them individually, if that’d be more efficient.

Ah, of course. Got it. And to play around I tried this variation:

Definition: a person is someone else if they are not the player.

Instead of wearing the vision glasses when the player can see someone else who is concealing something:
	now the player wears the vision glasses;
	say "The glasses feel warm. Immediately you can see [a list of things which are concealed by someone else who can be seen by the player]."

Here I modified part of the instead rule and the say statement to use my definition and then I get this when I run the test command:

Here [3] and [6] are reporting different things but [3] is now reporting nothing, while [6] is accurate.

But if I change the say statement to this:

say "The glasses feel warm. Immediately you can see [a list of things which are concealed by someone else]."

Then it all works correctly. Specifically with that change:

Note that [3] and [6] are now correct.

But now that it’s just “someone else” rather than “someone who can be seen by the player”, the performance inefficiency you mention could kick in depending on what’s in the model world. Well, I guess it would kick in anyway due to the activity.

I think the issue there is that Inform isn’t parsing “things which are concealed by someone else who can be seen by the player” quite how we’d expect–it’s an issue that sometimes arises with long strings of modifiers. Instead of the desired “things which are concealed by (someone else who can be seen by the player)” I think it’s interpreting it as “things (which are concealed by someone else) (who can be seen by the player)”–so the “who can be seen” clause is taken to modify “things,” which of course gives you nothing because the concealed things can’t be seen by the player.

If we put parentheses in to force the desired parsing:

Instead of wearing the vision glasses when the player can see someone else who is concealing something: now the player wears the vision glasses; say "The glasses feel warm. Immediately you can see [a list of things which are concealed by (someone else who can be seen by the player)]."

then it works as desired.

Jeff, that fix depends on all the NPCs in the game being in the same room. If the player can see any other person, whether they are holding a concealed item or not, then you’ll get the complete list of concealed items when you wear the glasses. (Try adding “Honest Joe is a man in the undertomb.”)

You could do something like this.

Instead of wearing the vision glasses when the player can see someone else who encloses a concealed thing:
	now the player wears the vision glasses;
	say "The glasses feel warm. Immediately you can see [a list of concealed things which are enclosed by (someone else who can be seen by the player)]."

Edit: matt, your solution has a problem with Honest Joe in the basement too. I have edited my fix above to include your parentheses. We may be converging on a solution…

Yep, confirmed on that as well.

Okay, so unless I missed a particular implementation, it looks like there’s really no sure-fire way to get this to work consistently unless there is a constraint that all NPCs are in that one room.

I think that the hybrid of matt w’s fix and mine should work consistently. (Matt’s fix sorts out the parsing with careful bracketing, and mine circumvents the problem with the concealment relation by replacing references to " thing concealed by" with “concealed thing enclosed by”.)

Ah, indeed, you are correct. I had missed one of the “enclosed” parts. So for those following the thread, this modified example from my original seems to work:

The Lab is a room.

Kitty Pryde is a woman in the Lab.

The Undertomb is a room.
It is down from the Lab.

A thing can be secret or obvious.
A thing is usually obvious.

Cain Marko is a man in the Lab.
Cain Marko carries a quantity of plastic explosive.
The quantity of plastic explosive is secret.

Kitty Pryde carries a laptop bag and a microfilm.
The microfilm is secret.

Rule for deciding the concealed possessions of something:
	if the particular possession is secret, yes;
	otherwise no.

Instead of examining someone:
	say "[The noun] is openly carrying [a list of unconcealed things carried by the noun]."

The player carries the vision glasses.
The vision glasses are wearable.

Instead of wearing the vision glasses:
	now the player wears the vision glasses;
	say "Nothing seems to happen."

Definition: a person is someone else if they are not the player.

Instead of wearing the vision glasses when the player can see someone else who encloses a concealed thing:
	now the player wears the vision glasses;
	say "The glasses feel warm. Immediately you can see [a list of things which are enclosed by (someone else who can be seen by the player)]."
	
After printing the name of a thing (called the item) which is carried by someone while wearing the vision glasses:
	say " (carried by [the holder of the item])"

Test secrets with "examine Kitty Pryde / examine Cain Marko / wear glasses / take off glasses / down / wear glasses".

Professor X is a man in the Undertomb.

Here I added that last statement, about Professor X, just to try out the condition of NPCs being in different rooms. When I run the above test script, I get:

Note that [3] and [6] are reporting correctly. Notice in [5] that good ol’ Professor X is hanging out in the Undertomb and the original problem does not manifest.

Sweet! I appreciate all the assistance on this. Along the way I learned a bit more Inform.

inform7.com has woken up again, so I reported the concealment bug. (I didn’t mention the parsing ambiguity, since that is a separate issue and probably not a bug.)

Thanks!

And yes, I think the parsing ambiguity isn’t a bug, or anyway not a fixable one; this is one of those areas where, since Inform isn’t really English, formulations that seem to make sense in English get parsed a different way by the compiler. Maybe it’d usually work to have which/who clauses refer to the nearest possible noun, but it seems like it’d break a lot of existing code.

I know this is old, but since the post has a high view count and it’s based on an example in the book, the topic seems worth an update.

The simplest fix without modifying core logic is a small modification to the rule for deciding concealed possessions. It should be:

Rule for deciding the concealed possessions of something (called hider):
    if the particular possession is secret and hider is not the player, yes;
    otherwise no.

but this is not a general solution, details for which follow.

What’s going on in the original code, exactly? In 6M62, the compiler’s interpretation of the meaning of statement:

say "The glasses feel warm. Immediately you can see [a list of things which are concealed by people who can be seen by the player]."

is correct – the test is exactly as intended in that it produces a list of items such that any item X must be concealed by person Y and person Y must be seen by the player.

The built-in definition of concealment from the Standard Rules:

Definition: Something is concealed rather than unconcealed if the holder of it conceals it.

also seems correct, but there is a subtlety to how it works.

The chain of logic for deciding a concealed possession is:

  1. code decides to check whether thing X is concealed
  2. concealed definition evaluates holder of X (call it thing H) and must decide whether H conceals thing X (via the concealment relation)
  3. the concealment relation logic is buried pretty deep, but essentially it runs routine TestConcealment(H,X) which in turn starts the deciding the concealed possessions of activity for H with particular possession X
  4. the deciding the concealed possessions of activity evaluates provided rules applicable to H and returns result

So what’s happening in the original code is:

  1. [a list of things which are concealed by people who can be seen by the player] is functionally translated as “any thing that is concealed by the yourself object” when the player is alone in Undertomb (since the player is a person and the player can see itself)
  2. each thing is checked for concealment by the yourself object, by running the provided rule, e.g. the rule is run for H = yourself and X = plastic explosive
  3. the rule as originally formulated ignores the identity of H and only looks at whether or not X is secret; since the plastic explosive is secret, it’s decided that yourself conceals the plastic explosive

The modified version of the rule for deciding concealed possessions at the start of this post fixes this specific issue indirectly by making it impossible for the player to conceal anything, but as @jrb points out, the built-in logic should arguably take into account whether or not the possession is in fact possessed by the person being evaluated for concealed possessions. To modify the built-in logic to do this, just add the following:

Include
(-

! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
! WorldModel.i6t: Concealment Relation (modified)
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====

[ TestConcealment A B;
    if (A ofclass K2_thing && B ofclass K2_thing) {
	    particular_possession = B;
	    if ((HolderOf(B) == A) && (CarryOutActivity(DECIDING_CONCEALED_POSSESS_ACT, A))) ! modified
		    rtrue;
    }
    rfalse;
];

-) instead of "Concealment Relation" in "WorldModel.i6t".

This update corrects the behavior in the original example code and (hopefully) fixes the problem at its root for the general case.

1 Like

Another way of looking at this is that the requirement to be the holder of a concealed possession is enforced by the adjective definition for concealed/unconcealed rather than the concealment relation, so its the direct use of the concealment relation that leads to trouble. Using the adjectives avoids the problem:

a list of concealed things which are held by people who can be seen by the player

However, if it is needed to use the concealment relation directly, the requirement to be the holder of the particular possession to be concealed can also be readily built-in for the general case-

Rule for deciding the concealed possessions of something (called the hider):
	if the hider holds the particular possession:
		if the particular possession is secret, yes; [or whatever condition(s) apply]
	no.

and now

[a list of things which are concealed by someone who can be seen by the player]

works equivalently.

As above, to exclude anything concealed that is held by the player,

Definition: a thing is other if it is not the player.
Definition: a thing is else if it is not the player.

and using ‘other person/people’ or ‘someone else’ in place of ‘someone’ / ‘people’ in the above phrases will do the trick.