new object $body: $located_location;
var $body actions = 0;
var $body available_body_parts = 0;
var $body body_parts = #[];
var $body interaction = 0;
var $body remote_command_cache = 0;
var $body wearing = [];
var $described prose = [];
var $has_commands local = \
#[["wh?isper", [["wh?isper", "* to *", "wh?isper <any> to <any>", 'whisper_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]],\
["say",\
[["say", "*", "say <any>", 'say_cmd, #[[1, ['any, []]]]]]],\
["to",\
[["to", "* say *", "to <any> say <any>", 'to_say_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]],\
["emote",\
[["emote", "*", "emote <any>", 'emote_cmd, #[[1, ['any, []]]]]]],\
["quote",\
[["quote", "*", "quote <any>", 'quote_cmd, #[[1, ['any, []]]]]]],\
["spoof",\
[["spoof", "*", "spoof <any>", 'spoof_cmd, #[[1, ['any, []]]]]]],\
["pose",\
[["pose", "*", "pose <any>", 'spoof_cmd, #[[1, ['any, []]]]]]],\
["think",\
[["think", "*", "think <any>", 'think_cmd, #[[1, ['any, []]]]]]],\
["wear",\
[["wear", "*", "wear <any>", 'wear_cmd, #[[1, ['any, []]]]]]],\
["remove|shed",\
[["remove|shed", "*", "remove|shed <any>", 'remove_cmd, #[[1, ['any, []]]]]]],\
["@a?ction",\
[["@a?ction", "*", "@a?ction <any>", 'action_cmd, #[[1, ['any, []]]]]]]];
var $has_commands shortcuts = #[["|*", ['quote_cmd, ["quote ", 1]]], ["\"*", ['say_cmd, ["say ", 1]]], ["%*", ['think_cmd, ["think ", 1]]], ["!*", ['spoof_cmd, ["spoof ", 1]]], [",*,*", ['esay_cmd, ["esay ", 1, " with ", 2]]], [":*", ['emote_cmd, ["emote ", 1]]], [".*", ['pose_cmd, ["pose ", 1]]], ["''*", ['to_say_cmd, ["to ", "", " say ", 1]]], ["'* *", ['to_say_cmd, ["to ", 1, " say ", 2]]]];
var $has_name name = ['uniq, "Generic Body", "the Generic Body"];
var $located location = $void;
var $located obvious = 1;
var $location contents = [];
var $root created_on = 796268969;
var $root fertile = 1;
var $root flags = ['methods, 'code, 'fertile, 'variables, 'core, 'command_cache];
var $root inited = 1;
var $root managed = [$body];
var $root manager = $body;
var $thing gender = $gender_neuter;
public method ._tell() {
arg @args;
var m;
m = .manager();
if ((m != this()) && ((m.location()) != (.location())))
(| m.tell(@args.prefix(("<" + (.name())) + "> ")) |);
};
protected method .action_cmd() {
arg cmdstr, cmd, string;
var a, data, parse, out;
(> .perms(caller(), 'command) <);
if (!string) {
out = [];
if (actions)
out = map a in (actions) to (pad(a[1], 25) + (a[2]));
if ((data = ((.location()).prose()).get_var('details)))
out += map a in (data) to ((pad(a[1], 25) + "look detail ") + (a[1]));
if (!out)
return "No actions registered.";
return [strfmt("%25sCommand", "What"), strfmt("%25s-------", "----"), @out, "---"];
}
if (actions) {
for a in (actions) {
if ((a[1]).match_begin(string)) {
data = a;
break;
}
}
if (data) {
parse = $command_parser.parse(this(), data[2], $null_parser);
(> .handle_parser_result(@parse) <);
return;
}
}
catch ~nodetail
return (.location()).get_detail(string);
.ptell(("No '" + string) + "' action registered.", #[['type, 'error]]);
};
public method .actions() {
return actions;
};
protected method .add_interaction() {
arg key, value;
if (!interaction)
interaction = #[];
if (type(value) != 'list)
value = [value];
value = [time(), value];
interaction = interaction.add(key, value);
};
public method .available_body_parts() {
return available_body_parts || ['head, 'rleg, 'lleg, 'rarm, 'larm, 'torso];
};
public method .body_parts() {
return body_parts;
};
public method .description() {
arg flags;
var ctext, what, w, o;
o = [];
ctext = (> pass(flags) <);
if ((w = .wearing()))
o += [((((.gender()).pronoun('psc)) + " is wearing ") + ((w.mmap('name)).to_english())) + "."];
// else
// o += [.gender().pronoun('psc) + " is naked, baring it all to the world."];
ctext += [$ctext_frob.new_with(o)];
return ctext;
};
public method .directed_tell() {
arg what, type;
._tell(what);
.send_event('social, sender(), type, what);
};
protected method .emote_cmd() {
arg cmdstr, com, what;
(> .perms(caller(), $user, $body) <);
if (what && ((what[1]) == ":"))
(.location()).announce((.name()) + (what.subrange(2)));
else
(.location()).announce(((.name()) + " ") + what);
};
public method .environment() {
return pass() + (wearing || []);
};
protected method .esay_cmd() {
arg cmdstr, cmd, how, prep, what;
(> .perms(caller(), $user, $body) <);
(.location()).announce((((((.name()) + " ") + (how.trim())) + ", \"") + (what.trim())) + "\"");
};
public method .event_notify() {
arg event, origin, @args;
if (caller() != $event_handler)
throw(~perm, caller() + " is not $event_handler.");
if (event == 'realm_announce)
.tell_realm_announce(origin, args[1]);
};
protected method .handle_parser_result() {
arg action, @more;
var r, c;
switch (action) {
case 'error:
._tell(more[1]);
case 'match, 'command:
r = (> (more[1]).(more[2])(@more.subrange(3)) <);
if (type(r) in ['list, 'frob, 'string])
.ptell(r, #[['type, 'parser], ['command, more[2]]]);
case 'failed:
for c in (($place_lib.coordinate_shortcuts()).keys()) {
if (action.match_template(c)) {
.tell(("There is no exit " + action) + " here.");
r = 1;
}
}
if (!r)
.tell(("I don't understand " + (action.chop((.actionlen()) - 22))) + ".");
case 'ok:
// do nothing, probably a null command
default:
._tell("Unusual response from the parser: " + toliteral(more));
}
};
public method .namef() {
arg type;
var str;
switch (type) {
case 'doing, 'nactivity, 'activity, 'titled:
return .name();
default:
return (> pass(type) <);
}
};
protected method .parse_interaction_reference() {
arg targets, what, @userdb;
var recip, target, msg, out;
[(userdb ?= 0)] = userdb;
targets = (targets && (targets.explode_list())) || [];
if (!targets) {
if (!(targets = (| interaction['objs] |)))
throw(~stop, ("You must direct your " + what) + " to a target.");
out = targets[2];
} else {
out = [];
for recip in (targets) {
target = 0;
if (userdb)
target = (| $user_db.match_begin(recip) |);
if (!target) {
catch ~objnf
target = (> .match_environment(recip) <);
with
throw(~stop, (traceback()[1])[2]);
}
if (!(target.is($body)))
throw(~stop, (target.namef('ref)) + " is not a valid recipient.");
out = setadd(out, target);
}
}
return out;
};
protected method .pose_cmd() {
arg cmdstr, cmd, args;
var action, targs, m, word, tail, i, str1, str2, str3, line, objs;
(> .perms(caller(), $user, $body) <);
if (!args) {
(.location()).announce(.name());
return;
}
action = args.word(1);
if (" " in args) {
args = substr(args, (" " in args) + 1);
if ("and" in args) {
targs = args.explode_english_list();
word = targs.last();
targs = delete(targs, listlen(targs));
targs = map m in (targs) to ((| .match_environment(m) |) || m);
if ((m = (| .match_environment(word) |))) {
args = "";
targs += [m];
} else {
args = substr(word, " " in word);
m = word.word(1);
targs += [(| .match_environment(m) |) || m];
}
} else {
m = " " + (args.word(1));
targs = [(| .match_environment(m) |) || m];
args = (| substr(args, (" " in args) + 1) |) || "";
}
} else {
.tell("You " + action);
(.location()).announce((((.name()) + " ") + action) + "s", this());
return;
}
// convert to ctext some day
if (args) {
str1 = strsed(args, " +my($| |\.)", " your%1");
str1 = strsed(args, " +me($| |\.)", " yourself%1");
word = (" " + ((.gender()).pronoun('pp))) + "%1";
str2 = strsed(args, " +my($| |\.)", word);
word = (" " + ((.gender()).pronoun('pr))) + "%1";
str2 = strsed(args, " +me($| |\.)", word);
str3 = str2;
}
objs = map m in (targs) to (((type(m) == 'objnum) && (m.name())) || m).to_english();
.tell(((("You " + action) + " ") + objs) + args);
// I'll do something better later
for m in (targs) {
line = (((.name()) + " ") + action) + "s ";
if (type(m) == 'objnum)
m.tell((line + strsub(objs, m.name(), "you")) + args);
}
line += objs + args;
objs = filter m in (targs) where (type(m) == 'objnum) + [this()];
(.location()).announce(line, @objs);
};
public method .ptell() {
arg what, flags;
.tell(what);
};
protected method .quote_cmd() {
arg cmdstr, cmd, what;
(.location()).announce(((.name()) + " | ") + what);
};
public method .register_action() {
arg name, link;
actions = dict_add(actions || #[], name, link);
};
protected method .remove_cmd() {
arg cmd, cmdstr, what;
(> .perms(caller(), $user, $body) <);
what = (> .match_env_nice(what) <);
if (!(what.is($wearable_frob)))
return ("You are not wearing " + (what.name())) + ".";
what = (> what.shed() <);
return "You remove " + (what.name());
};
public method .reset_actions() {
(| clear_var('actions) |);
};
protected method .say_cmd() {
arg cmdstr, cmd, what;
var type, how, idx;
(> .perms(caller(), $user, $body) <);
if (what)
how = $code_lib.punctuation_type(what);
else
how = "say";
(.location()).announce((((((.name()) + " ") + how) + "s, \"") + what) + "\"");
};
public method .set_body_part() {
arg part, frob, param;
if (sender().has_ancestor($wearable_frob))
throw(~perm, "Sender must be $wearable_frob.");
body_parts = body_parts.add(frob.new_with(part, param));
};
public method .shed() {
arg what;
if (caller() != $wearable_frob)
throw(~wear, "You can only wear descendants of $wearable_frob.");
wearing = setremove(wearing, what);
};
protected method .spoof_cmd() {
arg cmdstr, cmd, what;
var name;
(> .perms(caller(), $user, $body) <);
name = .name();
if (!(((name + " ") in what) || ((" " + name) in what)))
what = (what + " -- ") + name;
(.location()).announce(what);
};
public method .tell() {
arg @args;
};
public method .tell_realm_announce() {
arg realm, message;
var loc, realm, propagator, prop_list, len, i;
pause();
loc = .location();
if (!(propagator = loc.will_propagate()))
return;
prop_list = [propagator];
realm = (.location()).realm();
while (realm != $realm) {
if (realm == realm) {
len = prop_list.length();
for i in [1 .. len] {
message = message.propagate(prop_list[(len - i) + 1]);
if (!message)
return;
}
.tell(message);
}
if (!(propagator = realm.will_propagate()))
return;
prop_list += [propagator];
realm = (realm.parents())[1];
}
};
public method .tell_traceback() {
arg traceback;
if ((.manager()) != this())
(.manager()).tell_traceback(traceback);
};
protected method .think_cmd() {
arg cmdstr, cmd, what;
(> .perms(caller(), $user, $body) <);
(.location()).announce((((.name()) + " . o O ( ") + what) + " )");
};
protected method .to_say_cmd() {
arg cmdstr, com, who, prep, message;
var targets, target, line;
(> .perms(caller(), $user, $body) <);
catch ~ambig
targets = (> .parse_interaction_reference(who, "say") <);
with
return (traceback()[1])[2];
.add_interaction('objs, targets);
line = (((.name()) + " (to ") + ((targets.mmap('name)).to_english())) + ") ";
if (message)
line += ((message[1]) == ":") ? (message.subrange(2)) : (((($code_lib.punctuation_type(message)) + "s, \"") + message) + "\"");
else
line += "says, \"\"";
for target in (targets)
target.directed_tell(line, 'tosay);
(.location()).announce(line, @targets);
};
public method .wear() {
arg what;
if (caller() != $wearable_frob)
throw(~wear, "You can only wear descendants of $wearable_frob.");
wearing = setadd(wearing || [], what);
};
protected method .wear_cmd() {
arg cmd, cmdstr, what;
(> .perms(caller(), $user, $body) <);
what = (> .match_env_nice(what) <);
if (!(what.is($wearable_frob)))
return ("You cannot wear " + (what.name())) + ".";
what = (> what.wear() <);
return "You wear " + (what.name());
};
public method .wearing() {
arg @args;
var x, w;
w = wearing || [];
if (args && ('objects in args)) {
for x in [1 .. w.length()]
w = w.replace(x, class(w[x]));
}
return w;
};
protected method .whisper_cmd() {
arg cmdstr, com, what, prep, who;
var loc, targets, t, msg, recips;
(> .perms(caller(), $user, $body) <);
targets = (> .parse_interaction_reference(who, "whisper") <);
.add_interaction('objs, targets);
loc = .location();
if (((targets.mmap('location)).compress()) != [loc]) {
who = filter t in (targets) where ((t.location()) != loc);
return ("You must be in the same place as " + (who.english_name_list())) + ", to whisper to them.";
}
msg = (((.name()) + " whispers, \"") + what) + "\"";
for t in (targets)
(| t.directed_tell(msg, 'whisper) |);
recips = (targets.mmap('name)).to_english();
loc.announce((((.name()) + " whispers to ") + recips) + ".", this(), @targets);
.tell(((("You whisper, \"" + what) + "\" to ") + recips) + ".");
};
public method .will_move() {
arg mover, place;
// exits should always be able to pull "bodies" through them
// this becomes sortof a big override returning, but ... *shrug*
if (mover.is($exit))
return;
(> pass(mover, place) <);
};