! Written by Daniel Barkalow, v1.0, Sat Jan 29 2000.
! This file defines objects which will determine what rooms are
! visible from a given location. This is useful for having open spaces
! comprised of multiple game locations. It is not able to change
! dynamically, however. The simplest example is of a setup where the
! player has some way of seeing what's in adjacent locations (perhaps
! a LOOK <DIRECTION> command), and the game isn't responsible for
! mentioning objects in the other room all the time. To do this,
! simply create a Scoper with the adjacent locations in the "locs"
! property, and the directions to the locations in the "dirs"
! property.
! Note that objects found_in distant locations do not get added to
! scope with this mechanism. However, if an object which provides
! found_in is listed in the "locs" property of a Scoper, the object as
! well as its contents will be added to the scope.
! In order to have a single conceptual room with multiple locations,
! you want all of the objects, including the ones in different parts
! of the room to be listed when the room contents are listed. To
! handle this, use Locale() in the after Look method of each room to
! list the contents of other rooms with appropriate information.
! For instance:
! Room1
! ...
! after [;
! Look:
! if (Locale(Room2, "You see", "You also see"))
! print " on the other side of the room.^";
! ]
! ...
! Scoper ->
! with locs Room2,
! dirs "on the other side of the room";
! The player is permitted to Examine and Listen to objects in the
! distance, which prints a message saying
! In order to permit further interaction with distant objects (beyond
! Examine and Listen), add the verbs to the list at the beginning of
! react_before.
! To find out where an object is, use the procedure
! Scoper_locate(obj), which returns the "dirs" entry corresponding to
! the "locs" entry that got the object added. This probably won't work
! with things added by the add_to_scope property of an object.
! TestScope(obj) reports true if the thing is in scope via a scoper;
! the ScopeCeiling(obj) does not get transferred, however, which can
! distinguish distant objects. Note that TestScope(actor1, actor2)
! might not be the same as TestScope(acter2, actor1) now, since
! Scopers aren't necessarily commutative.
Class Scoper
with locs 0,
dirs 0,
add_to_scope
[i j k l n;
n = self.#locs;
k = self.&locs;
l = self.&dirs;
for (j = 0 : (2 * j) < n : j++)
{
if ((k-->j) provides found_in)
AddToScope(k-->j);
else
objectloop (i in k-->j)
if (~~(i ofclass Scoper))
AddToScope(i);
}
],
react_before
[i j k n;
Listen, Examine: ! Add other generally permissible actions here
i = Scoper_locate(noun);
if (i)
print "(", (the) noun, " ", (string) i, ")^";
rfalse;
! This would be a good place to add traps for things that
! the scoper should handle, like figuring out where a named
! object actually is.
default:
if (inp1 ~= 1 && noun ~= 0) ! test for permissible actions
! with noun.
{
i = Scoper_locate(noun);
if (i)
print_ret "You can't reach ", (the) noun, ", since it's ",
(string) i, ". ";
}
if (inp2 == 1 || second == 0 || action == ##ThrowAt) ! add
! permissible actions with second here.
rfalse;
i = Scoper_locate(second);
if (i)
print_ret "You can't reach ", (the) second, ", since it's ",
(string) i, ". ";
],
has concealed;
[Scoper_locate obj i j k l n;
objectloop (i ofclass Scoper)
if (parent(i) == real_location)
l = i;
if (~~l)
rfalse; ! no scoper here.
i = ScopeCeiling(obj);
k = l.&locs;
n = l.#locs;
for (j = 0 : (2 * j) < n : j++)
{
if (i == k-->j)
return l.&dirs-->j;
}
rfalse; ! not added via a scoper
];