Located object

    This object defines behavior having to do with having a location.

    Public methods (non-overridable):

	location()			Get location

    Methods for which I haven't decided on authentication yet:

	move(place)			Move to new place

    Overridable notification calls from $located:

	will_move(obj, place)		Notification of impending move
	did_move(obj, old_place)	Notification of move

    Protected methods:

	verbs_changed_on_leaf()		Notification that verbs changed

parent vr
object located

var located inited 0
var located location 0

method init
    arg ancestors;

    (> pass(ancestors) <);
    if (definer() in ancestors) {
	location = $sys.starting_room();
	location.add_sender_to_contents();
    }
.

method uninit
    arg ancestors;
    var old;

    if (!caller().is_agent('hierarchy))
	throw(~perm, "Caller is not an agent of hierarchy protocol.");
    catch any {
	if (definer() in ancestors) {
	    old = location;
	    location = 0;
	    old.remove_sender_from_contents();
	}
    }
    pass(ancestors);
.

eval
    .initialize();
    .set_name("Generic located object");
.

method location
    disallow_overrides;

    return location;
.

method move
    disallow_overrides;
    arg place;
    var old;

    // Don't do anything if we're already here.
    if (place == location)
	return;
    if (!place.follows('container))
	throw(~type, "Argument doesn't follow container protocol.");

    // Notify involved parties of impending move, allowing them to throw
    // errors.
    (> .will_move(sender(), place) <);
    (> location.will_leave(place) <);
    (> place.will_arrive(location) <);

    // Set location.
    old = location;
    location = place;
    old.remove_sender_from_contents();
    place.add_sender_to_contents();

    // Notify involved parties of completed move, in reverse order.
    place.did_arrive(old);
    old.did_leave(place);
    .did_move(sender(), old);
.

method will_move
    arg mover, place;

    if (caller() != definer() || sender() != this())
	throw(~perm, "Invalid call to private method.");
.

method did_move
    arg mover, old_place;

    if (caller() != definer() || sender() != this())
	throw(~perm, "Invalid call to private method.");
.

method verbs_changed_on_leaf
    // This is a leaf object (it has no descendents) and the verbs on it
    // changed.  We must invalidate the cache on all objects for which this
    // object is visible.  We'll let the location handle that.
    (> pass() <);
    if (location.follows('room))
	location.verb_changed_inside();
.