# Original Parser

## version 1 by Ron Newcomb

Chapter - SearchScope

[Level 1. The method is:
(a) If the context is a |scope=...| token, then the search is delegated
to stage 2'' of the scope routine. This was the old I6 way to override
the searching behaviour: while users probably won't be using it any more,
the template does, in order to give testing commands universal scope which
is exempt from the activity below; and the NI compiler creates |scope=...|
tokens to handle Understand grammar such as [any room]''. So the feature
remains very much still in use.
(b) The deciding the scope of'' activity is given the chance to intervene.
This is the I7 way to override the searching behaviour, and is the one taken
by users.
(c) And otherwise:
(-1) The I6 |multiinside| token, used as the first noun of its grammar line,
has as its scope all of the objects which are inside or on top of the
{\it second} noun of the grammar line. This provides a neat scope for the
ALL in a command like GET ALL FROM CUPBOARD, where the player clearly
does not intend ALL to refer to the cupboard itself, for instance. The
difficulty is that we don't yet know what the second object is, if we are
parsing left to right. But the parser code above has taken care of all of
that, and the |advance_warning| global is set to the object number of the
second noun, or to $-1$ if that is not yet known. Note that we check that
the contents are visible before adding them to scope, because otherwise
an unscrupulous player could use such a command to detect the contents of
an opaque locked box. If this rule applies, we skip (c.2), (c.3) and (c.4).
(-2) For all other tokens except |creature|, searching scope for the room
holding the current actor always catches the compass directions unless a
definite article has already been typed. (Thus OPEN THE EAST would match
an object called east door'', but not the compass direction east''.)
(-3) The contents of |domain1| which are not contents of |domain2| are
placed in scope, and so are any component parts of |domain1|. If |domain1|
is a container or supporter, it is placed in scope itself.
(-4) The contents and component parts of |domain2| are placed in scope.
If |domain2| is a container or supporter, it is placed in scope itself.
(-5) In darkness, the actor and his component parts are in scope. If the
actor is inside or on top of something, then that thing is also in scope.
(This avoids a situation where the player gets into an opaque box, then
pulls it closed from the inside, plunging himself into darkness, then types
OPEN BOX only to be told that he can't see any such thing.)]

To search the scope of (first domain - an object) and (second domain - an object) under (context - a grammar token) (this is SearchScope):
if the first domain is nothing, stop;
[ Rule (a) - If the current scope limit is set by an understand token like Understand "[any room]" as... or one of those described in 25.22 of _Writing with Inform_ then invoke that phrase/function/routine. ]
if the scope decider is not currently blank:
if TRACE 3, say " [bracket]Scope routine called at stage 2[close bracket][line break]";
if the scope decider returns true, stop the action;
[ Rule (b) - The "deciding the scope" activity allows the I7 author their preferences now.]
begin the deciding the scope activity with the person asked;
if handling the deciding the scope activity with the person asked:
[ Rule (c) - if the author has no special preferences, then the default is these five rules: ]
[ Rule (c.1) - for GET ALL FROM CUPBOARD we place the contents of the second noun into scope, assuming we can see the contents (i.e. the second noun is a supporter, open container, transparent anything, etc.). ]
if the reason for deciding scope is because we're parsing the predicate nouns and the context is 'things inside' and we suspect what the second noun will be:
if the likely second noun is see-through:
place the contents of the likely second noun into scope excluding nothing under the context;
otherwise:
[ Rule (c.2) - For non-creatures, searching scope for the room containing the actor always catches the compass directions unless a definite article has already been typed. (Thus OPEN THE EAST would match "east door" but not the compass direction "east".)]
if the reason for deciding scope is because we're parsing the predicate nouns and the context is not 'someone' and the indefinite article mode is false and the first domain is the actor's scopewise location:
place the contents of the compass in scope;
[ Rule (c.3) - The contents of |domain1| which are not contents of |domain2| are placed in scope, and so are any component parts of |domain1|. If |domain1| is a container or supporter, itself is placed in scope.]
if the first domain is a supporter or container:
do scope action on the first domain;
place the contents of the first domain in scope excluding the second domain under the context;
[ Rule (c.4) - The contents and component parts of |domain2| are placed in scope. If |domain2| is a container or supporter, it is placed in scope itself.]
unless the second domain is nothing:
if the second domain is a supporter or container:
do scope action on the second domain;
place the contents of the second domain in scope excluding nothing under the context;
[ Rule (c.5) - avoid the situation where the player gets into an opaque box, then pulls it closed from the inside, plunging himself into darkness, then types OPEN BOX only to be told that he can't see any such thing.]
if the first domain is the ur-darkness or the second domain is the ur-darkness:
recursively do scope action on the person asked excluding the person asked under the context;
if the parent of the person asked is a supporter or container:
recursively do scope action on the parent of the person asked excluding the parent of the person asked under the context;
end the deciding the scope activity with the person asked.

[ SearchScope domain1 domain2 context i;
if (domain1 == 0) return;
! (a)
if (scope_token) {
scope_stage = 2;
#Ifdef DEBUG;
if (parser_trace >= 3) print " [Scope routine called at stage 2]^";
#Endif;
if (indirect(scope_token) ~= 0) rtrue;
}
! (b)
BeginActivity(DECIDING_SCOPE_ACT, actor);
if (ForActivity(DECIDING_SCOPE_ACT, actor) == false) {
! (c.1)
if ((scope_reason == PARSING_REASON) && (context == MULTIINSIDE_TOKEN) &&
} else {
! (c.2)
if ((scope_reason == PARSING_REASON) && (context ~= CREATURE_TOKEN) &&
(indef_mode == 0) && (domain1 == actors_location))
ScopeWithin(compass);
! (c.3)
if (domain1 has supporter or container) DoScopeAction(domain1);
ScopeWithin(domain1, domain2, context);
! (c.4)
if (domain2) {
if (domain2 has supporter or container) DoScopeAction(domain2);
ScopeWithin(domain2, 0, context);
}
}
! (c.5)
if (thedark == domain1 or domain2) {
DoScopeActionAndRecurse(actor, actor, context);
if (parent(actor) has supporter or container)
DoScopeActionAndRecurse(parent(actor), parent(actor), context);
}
}
EndActivity(DECIDING_SCOPE_ACT, actor);
]