Scope bug?

If something’s in scope, it’s ‘visible’, right?

I found a circumstance that hangs a game.

In this demo, you can stand upstairs on the balcony and examine the cat. An ‘understand as…when visible’ phrase lets you call the cat ‘animal’ if it’s visible, but if you use ‘animal’ when the cat’s not in the room, the game freezes.

Doing the ‘test me’ is kind of pointless as it just stops immediately without showing you the commands.

Go down, then ‘examine animal’, then up, then ‘examine cat’, then ‘examine animal’ - then it stops.

There is a room called balcony. downstairs is down from balcony.

the cat is an animal in downstairs.

Understand “animal” as cat when cat is visible.

After deciding the scope of the player when location is balcony:
place cat in scope.

Test me with “d / u / x cat / x animal”.[/code]

The game goes into an infinite loop, placing the cat in scope again and again. I don’t know exactly how the parsing mechanism works, but it’s probably tightly coupled with the scope checking mechanism so things like this can confuse it.

Saying “Understand … as X when X is visible” is redundant anyway, because understand phrases apply only to things in scope. I can’t think of a situation where you’d need to “limit” the understand phrase to only visible things.

I think scope is designed for placing a room in scope, the objects in that room. When I was using scope in a game, I could not place an object in scope unless it was in a room. I had to create a hidden room I called “imagination” then placed that room in scope.

If that’s not correct it may be true that scope is buggy.

That doesn’t sound right: if you change severedhand’s code so that the cat is initially out of play it works fine. Do you have an example that would demonstrate this behavior?

No, that’s not true. You can place any object in scope, including off-stage objects.

The Kitchen is a room. 

The cat is a thing.

After deciding the scope of the player:
	place cat in scope.

>x cat
You see nothing special about the cat.

But this is tangential to the original question.

I think the infinite loop is a bug. You’re doing a scope search (“the cat is visible”) inside a parsing routine, which is called from inside another scope search (the parser looking for objects to match “x animal”). I expect that to be inefficient, but not to hang.

However, as Juhana said, there’s no reason to use the “cat is visible” test there, so just delete it.

I gave this example because actually editing out the part of my game that causes this was too hard. But I have a reason to use this construction.

Say there are cats and dogs running all over the place. They’ve all got names. Then you climb to a vantage point, a room which places animals from all over the game in scope.

I had code saying ‘understand ‘animal’ as jonesy (a cat) when jonesy is in location’ - so that ‘animal’ would only act on jonesy if jonesy was present. I need this because I’ve got actions that work on people that are out of scope as well, and I was trying to eradicate disambiguation. Typing ‘(out-of-scopecommand animal)’ would otherwise bring up disambiguation of all animals in the game.

If I’m at my vantage point where I can see tons of animals, all the cats or dogs are in scope, but none are in the room, so ‘x animal’ says ‘you can’t see any such thing.’ That’s why I tried adding the ‘visible’.

After all that mucking around, I’m still stuck with my initial problem — I want to allow some commands to refer to out of scope creatures, but not if you haven’t met those creatures yet. Otherwise you can type (outofscopecommand cat) and get a free list of all cats in the game as it says ‘do you mean jonesy or tommy or?..’. This is bloody hard to eradicate, because inform does this before it looks at any code of mine.

How about this?

A cat is a kind of animal. A cat can be met or unmet. A cat is usually unmet. A cat is usually proper-named. Understand "cat" as a cat when the item described is met. When play begins: now all visible cats are met. Every turn: now all visible cats are met. Calling is an action applying to one visible thing. Understand "call [any cat]" as calling. Report calling: say "[Noun] is a cat and ignores you."

[UPDATE: Added the “when play begins” rule, so that cats visible when play begins will be met for the first turn (and thereafter, even if you move away on the first turn).]

No, I don’t have a sample of the game that didn’t work, when it didn’t work I completely changed it so it functioned a different way. So the code that didn’t work no longer exists.

Sounds like the easiest solution would be to use the Epistemology extension to track which cats the player has met. (This is the exact same problem that any conversation system that uses things as topics faces, so you might want to look at some conversation extensions and see how they solve it.)

Thanks. When matt posted his reply, I’d started a solution involving tagging people like he posted. His worked by letting everyone be tagged, and letting the command refer to everyone. I had already split my commands up to refer to the tagged, the untagged and folks in the room with you. I had a lot of inveigling to do because I have a bunch of commands with tricky physical requirements (and I’d be describing my whole game if I went into it all), but I got there in the end.

I was offline last week and got behind, so I just noticed this post. Curiously, I had exactly the same problem in my WIP, and came up with a totally different solution.

This is thanks to Zarf, who explained how to do it several months ago. I’ve wrapped up the solution into an extension called “Scope Caching.” Normally, Inform runs the entire scope loop for every single object each time one scope test is made. Scope Caching just does it once at the beginning of a turn and then saves the result in a property called “marked visible.”

I just posted a thread about it, which includes an example that should solve the OP’s problem. Please comment:

Speaking of Epistemology, would Eric like to make use of Scope Caching in future versions…?

[code][ It might seem more straightforward simply to write “Now everything visible in the location is seen.” but
this turns out to be unacceptably slow in practice. The following code does approximately the same thing
but much faster.]

Carry out looking (this is the mark items as seen when looking rule):
unless in darkness begin;
repeat with item running through things that are enclosed by the location begin;
if the item is not enclosed by an opaque closed container, now the item is seen;
end repeat;
end unless.

Carry out opening a container (this is the mark items as seen on opening a container rule):
repeat with item running through things that are enclosed by the noun begin;
if the item is unseen and the item is visible, now the item is seen;
end repeat.

The mark items as seen on opening a container rule is listed after the standard opening rule in the carry out opening rules.

I think this whole section could be replaced with:

[code]After reading a command (this is the mark visible items as seen rule):
Now every marked visible item is seen;

The mark visible items as seen rule is listed after the cache scope after reading a command rule in the after reading a command rulebook.[/code]

…although there may be some extra fiddling needed when objects are revealed during multiple actions - I think that may already be true.

I remembered today that I can deal with it in my own extension, using the “in place of” section designation. I’ve done that:

[code]Book 2 - Sight (in place of Book 1 - Sight in Epistemology by Eric Eve)

A thing can be either seen or unseen. A thing is usually unseen.

[ With the speed advantages of scope caching, we can now do more accurate accounting of what has actually been seen. ]

After reading a command (this is the mark cached items as seen rule):
Now every marked visible thing is seen.

The mark cached items as seen rule is listed after the cache player’s scope rule in the after reading a command rulebook.

The cache player’s scope rule is listed last in the carry out looking rules.
The mark cached items as seen rule is listed last in the carry out looking rules.

The cache player’s scope rule is listed last in the carry out opening rules.
The mark cached items as seen rule is listed last in the carry out opening rules.[/code]

(full source and links are at the other thread I started:

I’m wondering if anyone can tell me whether it’s redundant to add the “marked as seen” rules to the looking and opening rules in addition to the “after reading a command” rules. Are there cases where after reading a command would miss that?