parent described
object vr

var root name 'vr
var vr vr_name 0

method init_vr
    if (caller() != $root)
        throw(~perm, "Caller is not $root.");
    vr_name = tostr(.name());
.

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

method set_vr_name
    arg new_name;

    if (!.is_owned_by(sender()))
        throw(~perm, "Sender is not an owner.");
    if (type(new_name) != 'string)
        throw(~type, "New name is not a string.");
    vr_name = new_name;
.

eval
    .initialize();
    .set_vr_name("Generic virtual reality object");
.

method vr_name
    disallow_overrides;

    return vr_name;
.

method environment
    return [];
.

method match_environment
    arg s;
    var loc, obj, env;

    if (!s)
        throw(~objnf, "No object \"\" in environment.", s);

    // Handle special cases.
    if (s == "me")
        return this();
    if (s && s[1] == "$") {
        obj = (| get_name(tosym(substr(s, 2))) |);
        if (!valid(obj))
            throw(~objnf, "No such object " + s, s);
        return obj;
    }

    // Look first for exact matches.
    env = .environment();
    for obj in (env) {
        if (obj.vr_name() == s)
            return obj;
    }

    // Now look for partial matches.
    for obj in (env) {
        if (match_begin(obj.vr_name(), s))
            return obj;
    }

    throw(~objnf, "No object " + s + " in environment.", s);
.

method local_to_environment
    arg obj;
    var loc;

    return (obj in .environment()) ? 1 | 0;
.