/
CDC-1.1/
parent $location
parent $public
object $place

var $root child_index 88
var $root fertile 0
var $root manager $place
var $root owned [$place]
var $root owners [$place]
var $root writable []
var $root readable ['parameters, 'methods, 'code]
var $root inited 1
var $gendered gender $gender_neuter
var $described prose #[]
var $has_verbs verbs #[]
var $has_commands commands [["l?ook", 'look_cmd]]
var $has_commands shortcuts []
var $root dbref 'place
var $named name ['uniq, "place"]
var $named name_aliases []
var $place realm 0
var $place exits 0
var $place coordinates 0
var $public public ['readable]

method init_place
    .perms($root, caller());
    exits = [];
    realm = $realm_of_creation.new();
    coordinates = #[];
    .set_public('location);
.

method uninit_place
    var x;
    
    .perms($root, caller());
    for x in (exits)
        (| x.destroy() |);
    (| realm.place_destroyed(this()) |);
    for x in (.area())
        (| x.place_destroyed(this()) |);
    (| $place_db.place_destroyed() |);
.

method environment
    return pass() + exits;
.

method description
    arg actor, [exclude];
    var output, dark;
    
    output = pass(actor, exclude);
    output = output + (._desc_contents(actor, exclude));
    output = output + (._desc_exits(actor, exclude));
    return output;
.

method exits
    return exits;
.

method add_exit
    disallow_overrides;
    arg coord1, coord2;
    var exit;
    
    // coordinates are not standard x/y, but radial/azimuth
    .perms($exit, caller());
    exit = sender();
    (> ._add_exit(exit) <);
    (> ._add_coordinate(exit, coord1, coord2) <);
    (> ._add_coordinate(exit.dest(), coord1, coord2) <);
.

method _add_exit
    disallow_overrides;
    arg obj;
    
    // use .add_exit()
    .perms(sender(), 'this);
    exits = [@exits, obj];
.

method _del_exit
    disallow_overrides;
    arg obj;
    
    // use .del_exit()
    .perms(sender(), 'this);
    exits = setremove(exits, obj);
.

method del_exit
    disallow_overrides;
    var exit;
    
    exit = sender();
    .perms(caller(), $exit);
    (| ._del_exit(exit) |);
    (| ._del_coordinate(exit) |);
    (| ._del_coordinate(exit.dest()) |);
.

method _add_coordinate
    disallow_overrides;
    arg obj, coord1, coord2;
    
    .perms(sender(), 'this);
    
    // should only be called from inside this object.
    coordinates = dict_add(coordinates, obj, [coord1, coord2]);
.

method _del_coordinate
    disallow_overrides;
    arg obj;
    
    .perms(sender(), 'this);
    
    // should only be called from inside this object.
    coordinates = dict_del(coordinates, obj);
.

method did_connect
    if ((.visibility()) >= 0)
        .announce((sender().namef()) + " has connected.", sender());
.

method did_disconnect
    if ((.visibility()) >= 0)
        .announce((sender().namef()) + " has disconnected.", sender());
.

method look_cmd
    arg cmd;
    var actor, text;
    
    sender().tell(.description(sender(), sender()));
.

method realm
    arg [args];
    var tmp, r;
    
    return realm;
.

method announce
    arg str, [except];
    var obj;
    
    for obj in (.contents()) {
        if (!(obj in except))
            (| obj.tell(str) |);
    }
.

method did_housekeep
    arg who;
    var message;
    
    // catch ~msgnf {
    catch any {
        message = .get_message('housekeeper);
    } with handler {
        message = "The housekeeper hauls %N away";
    }
    
    // this will have to do until we get a correct action setup
    .announce(strsub(message, "%N", who.namef()));
.

method set_name
    arg [args];
    var old_name;
    
    old_name = .name();
    (> pass(@args) <);
    (| $place_db.room_changed_name(old_name) |);
.

method set_realm
    arg frob_class, where;
    
    .perms(sender());
    if (!(frob_class.has_ancestor($frob_class)))
        throw(~type, "Realm must be submitted as a frob class object.");
    realm = frob_class.new([where]);
.

method examine_vrb
    arg vrb, [args];
    var actor, text;
    
    actor = sender();
    text = .description(actor, [actor], 'desc_name, 'long_description, '_desc_contents, '_desc_long_exits);
    actor.tell(text);
.

method _desc_contents
    arg actor, dont_show;
    var users, objects, output, obj, line;
    
    // called by .description
    .perms(sender(), 'this);
    users = [];
    objects = [];
    for obj in (.contents()) {
        if ((!(obj in dont_show)) || (| !(obj.obvious()) |)) {
            if (obj.has_ancestor($body))
                users = [@users, obj.namef('nactivity)];
            else
                objects = [@objects, obj.namef()];
        }
    }
    output = [];
    
    // we will get these both using @options eventually.
    if (users) {
        line = ($list.to_english(users)) + " ";
        line = (line + ((listlen(users) > 1) ? "are" | "is")) + " here.";
        output = [@output, line];
    }
    if (objects) {
        line = "You see ";
        line = (line + ($list.to_english(objects))) + " here.";
        output = [@output, line];
    }
    return output;
.

method _desc_exits
    arg actor, mode;
    
    .perms(sender(), 'this);
    return .visible_exits_formatted(actor, 'verbose);
.

method visible_exits
    var obv, exit;
    
    obv = [];
    for exit in (.exits()) {
        if ((exit.visibility()) >= (.visibility()))
            obv = [@obv, exit];
    }
    return obv;
.

method area
    var out, x;
    
    out = [];
    for x in (dict_keys(coordinates)) {
        if (x.has_ancestor($place))
            out = out + [x];
    }
    return out;
.

method realm_name
    return (((realm.name()) + " [") + (.name())) + "]";
.

method will_attach
    arg type, obj;
    
    // callable only from the methods on $exit, so don't worry too much.
    switch (type) {
        case 'source:
            .perms(obj);
        case 'dest:
            if ((!(.is_publicly('location))) && (!(| .perms(obj) |)))
                throw(~perm, ("Place refuses to link with " + (obj.namef('ref))) + ".");
    }
.

method visible_exits_formatted
    arg actor, how;
    var output, ex, exits, line;
    
    exits = .visible_exits();
    switch (how) {
        case 'none:
            return [];
        case 'brief:
            if (!exits)
                return [];
            return ["Exits: " + ($list.to_english($list.map(exits, 'namef), "none"))];
        case 'average:
            output = [];
            for ex in (exits) {
                line = (ex.namef()) + " (";
                line = line + ($list.to_english(ex.name_aliases(), "no aliases"));
                output = [@output, line];
            }
            return output ? ["Exits: " + ($list.to_english(output))] | [];
        case 'long:
            output = [];
            for ex in (exits)
                output = [@output, ((("  " + (ex.namef())) + " to: ") + ((ex.dest()).namef())) + "."];
            return output ? ["Exits: ", @$list.lcolumnize(output, actor.linelen())] | [];
        case 'verbose:
            output = [];
            for ex in (exits)
                output = [@output, ex.description(actor, 'short)];
            return output ? [$list.to_string(@output)] | [];
    }
.

method place_destroyed
    arg place;
    
    // announces when a place is destroyed
    .perms(caller(), $place, $realms_class);
    (| ._del_coordinate(place) |);
.