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

parent vr
object located

var root name 'located
var located inited 0
var located location 0

method init_located
    if (caller() != $root)
        throw(~perm, "Caller is not root.");
    location = $sys.starting_room();
    location.add_sender_to_contents();
.

method uninit
    if (caller() != $root)
        throw(~perm, "Caller is not root.");
    location.remove_sender_from_contents();
    location = 0;
.

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

method environment
    return [this()] + setremove(location.environment(), this());
.

method match_environment
    arg s;

    if (s == "here")
        return location;
    else
        return (> pass(s) <);
.

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.has_ancestor($container))
        throw(~type, "Argument isn't a container.");

    // 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 protected method.");
.

method did_move
    arg mover, old_place;

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