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) <); };