new object $exit_frob: $thing_frob, $exit;
var $described prose = [];
var $has_commands local = #[];
var $has_commands remote = #[];
var $has_commands shortcuts = #[];
var $has_name name = ['prop, "Exit Frob", "Exit Frob"];
var $located location = $void;
var $located obvious = 1;
var $root created_on = 849130536;
var $root flags = ['variables, 'methods, 'code, 'core];
var $root inited = 1;
var $root managed = [$exit_frob];
var $root manager = $exit_frob;
var $thing gender = $gender_neuter;
frob method .all_defined_settings(): nooverride {
arg this;
var sets;
sets = (> pass(this) <);
sets = dict_del(sets, "home");
sets = dict_del(sets, "gender");
return sets;
};
frob method .attach() {
arg this, source, dest, @ignore;
(source.is($place)) || throw(~place, (source.namef('ref)) + " is not a place.");
(dest.is($place)) || throw(~place, (dest.namef('ref)) + " is not a place.");
(| .detach() |);
(> source.will_attach('source, sender()) <);
(> dest.will_attach('dest, sender()) <);
this = this.del('location);
this = this.add('source, source);
this = this.add('dest, dest);
(> source.attach_exit('source, (<this(), this>)) <);
(> dest.attach_exit('dest, (<this(), this>)) <);
};
protected method .change_data() {
arg this, what, new, @remove;
if (this['source])
return (this['source]).update_exit_frob(this, what, new, @remove);
else if (remove)
return (<this(), (this.del(what))>);
else
return (<this(), (this.add(what, new))>);
};
frob method .clear_closable() {
arg this, name;
if (dict_contains(this, 'closed))
this = .change_data(this, 'closed, 0, 'remove);
return .change_data(this, 'closable, 0, 'remove);
};
frob method .close_cmd() {
arg frob, cmdstr, cmd, this;
var vars, m, source, dest;
catch ~locked
.try_lock(frob, sender());
with
return (traceback()[1])[2];
if (dict_contains(frob, 'closable)) {
if (dict_contains(frob, 'closed)) {
return ((.name(frob)).capitalize()) + " is already closed.";
} else {
source = frob['source];
dest = frob['dest];
frob = .change_data(frob, 'closed, 1);
vars = #[["$actor", sender()], ["actor", sender().name()], ["$this", frob], ["this", frob.name()]];
m = frob.eval_message("exit-close", $exit, vars);
source.announce(m);
dest.announce(m);
}
} else {
return ((.name(frob)).capitalize()) + " cannot be closed.";
}
};
public method .default_exit_msg_vars() {
arg this, actor, @more;
var vars;
vars = #[["actor", actor.name()], ["source", (this['source]).name()], ["dest", (this['dest]).name()], ["this", name]];
if (more)
vars = dict_union(vars, more[1]);
return vars;
};
frob method .description() {
arg this, flags;
var desc;
if (dict_contains(this, 'closed))
return (> pass(this, flags) <) + [(.name(this)) + " is closed."];
if ((!(| flags['prose] |)) || (!valid(this['dest])))
return (> pass(this, flags) <);
return [(<$ctext_frob, [[(<$format, ["subj", [], [("Through " + (.name(this))) + " you see.."], 'do_subj]>)], #[]]>), (this['dest]).get_description(flags)];
};
frob method .dest() {
arg this;
return this['dest];
};
frob method .destination_destroyed() {
arg this;
if (!(caller().is($place)))
throw(~perm, "Must be called by $place");
(this['source]).detach_exit('source, (<this(), this>));
};
frob method .detach(): nooverride {
arg this;
(this['source]) && (| (this['source]).detach_exit('source, (<this(), this>)) |);
(this['dest]) && (| (this['dest]).detach_exit('dest, (<this(), this>)) |);
};
frob method .discard() {
arg data;
if (!(.is_writable_by(sender())))
throw(~perm, "Only writers and managers can discard exits.");
return (> .detach(data) <);
};
frob method .exit_msg_vars() {
arg this, actor, @more;
var vars, s, d;
s = this['source];
d = this['dest];
vars = #[["$actor", actor], ["actor", actor.name()], ["$source", s], ["source", s.name()], ["$dest", d], ["dest", d.name()], ["$this", this()], ["this", .name(this)]];
if (more)
vars = dict_union(vars, more[1]);
return vars;
};
frob method .get_closable() {
arg this, name, definer;
return (| this['closable] |) || 0;
};
frob method .invoke() {
arg this, @flags;
var s, here, vars, m, actor, ln, v, dest;
s = (actor = sender());
if (dict_contains(this, 'closed)) {
m = .eval_message(this, "exit-closed", $exit, .exit_msg_vars(this, s));
return (this['source]).announce(m);
}
if (flags)
flags = flags[1];
else
flags = #[];
flags = flags.add('actor, s);
flags = flags.add_elem('exclude, s);
dest = this['dest];
if (!valid(dest))
return s.tell((.name(this)) + " has an invalid destination!");
if (!(> .try_lock(this, s) <)) {
v = #[["lock", (this['lock]).lock_name()]];
m = .eval_message(this, "lock-fail", $exit, .exit_msg_vars(this, s, v));
return (this['source]).announce(m);
}
s.move_to(dest);
vars = .exit_msg_vars(this, s);
m = .eval_message(this, "invoke", $exit, vars);
dest.announce(m);
(this['source]).announce(m);
};
frob method .invoke_notify(): forked {
arg this, actor, flags;
var vars, m, name;
name = .name(this);
if (flags.contains('simple)) {
actor.tell("You take " + name);
(this['dest]).announce((actor.name()) + " arrives.");
(this['source]).announce((((actor.name()) + " goes through ") + name) + ".");
} else {
// this does not let you set specific messages on each exit--
// we need to add $has_messages_frob
vars = #[["$actor", actor], ["actor", actor.name()], ["$source", this['source]], ["source", (this['source]).name()], ["$dest", this['dest]], ["dest", (this['dest]).name()], ["$exit", this()], ["exit", name]];
m = .eval_message(this, "invoke", $exit, vars);
(this['dest]).announce(m);
(this['source]).announce(m);
}
};
frob method .is_visible_to() {
arg this, whom;
return (.visibility(this)) >= ((whom.location()).darkness());
};
frob method .lock() {
arg this;
if ((this.contains('lock)) && (this['lock]))
return this['lock];
return $true_lock_frob.new();
};
frob method .lock_cmd() {
arg this, cmdstr, cmd, ignore;
if (!(| .perms(this, sender()) |))
return ((("Only " + ((.manager(this)).name())) + " can lock ") + (.name(this))) + "!";
.change_data(this, 'lock, $false_lock_frob.new());
return "You lock " + (.name(this));
};
frob method .lock_with_cmd() {
arg this, cmdstr, cmd, ignore, prep, str;
var frob;
if (!(| .perms(this, sender()) |))
return ((("Only " + ((.manager(this)).name())) + " can lock ") + (.name(this))) + "!";
catch ~objnf, ~parse {
frob = .change_data(this, 'lock, $lock_parser.parse(str, sender()));
return ((("You lock " + (.name(this))) + " to allow ") + ((frob.lock()).lock_name('exit))) + ".";
} with {
switch (error()) {
case ~objnf:
return "Object not found in lock string.";
case ~parse:
return "Invalid lock string.";
}
}
};
public method .new() {
var this;
this = (> pass() <).value();
this = this.add('source, 0);
this = this.add('dest, 0);
return (<this(), this>);
};
public method .open() {
arg this;
return .change_data(this, 'closed, 0);
};
frob method .open_cmd() {
arg frob, cmdstr, cmd, this;
var vars, m, source, dest;
catch ~locked
.try_lock(frob, sender());
with
return (traceback()[1])[2];
if (dict_contains(frob, 'closable)) {
if (dict_contains(frob, 'closed)) {
source = frob['source];
dest = frob['dest];
frob = .change_data(frob, 'closed, 0, 'remove);
vars = #[["$actor", sender()], ["actor", sender().name()], ["$this", frob], ["this", frob.name()]];
m = frob.eval_message("exit-open", $exit, vars);
source.announce(m);
dest.announce(m);
} else {
return ((.name(frob)).capitalize()) + " is already opened.";
}
} else {
return ((.name(frob)).capitalize()) + " cannot be opened.";
}
};
frob method .perms() {
arg this, what, @args;
return (what == (this['manager])) || (> (this['source]).perms(what, @args) <);
};
frob method .place_destroyed() {
arg this, place;
(> .perms(this, caller(), $place) <);
.detach(this);
};
frob method .set_closable() {
arg this, name, definer, value;
if (value) {
return .change_data(this, 'closable, 1);
} else if (dict_contains(this, 'closable)) {
if (dict_contains(this, 'closed))
this = .change_data(this, 'closed, 0, 'remove);
return .change_data(this, 'closable, 0, 'remove);
}
return (<this(), this>);
};
frob method .source() {
arg this;
return this['source];
};
public method .try_lock() {
arg this, @args;
return (| this['lock] |) ? ((this['lock]).try(@args)) : 1;
};
frob method .unlock_cmd() {
arg this, cmdstr, cmd, ignore;
if (!(| .perms(this, sender()) |))
return ((("Only " + ((.manager(this)).name())) + " can lock ") + (.name(this))) + "!";
.change_data(this, 'lock, $true_lock_frob.new());
return "You unlock " + (.name(this));
};
frob method .will_move() {
arg this, mover, place;
throw(~nomove, "You cannot do that to an exit!");
};